zoukankan      html  css  js  c++  java
  • @requestBody注解的使用(下)

    提示: 建议一定要看后面的@RequestBody的核心逻辑源码以及六个重要结论!本文前半部分的内容都是一些基本知识常
             识,可选择性跳过。

    说明:

    @RequestBody主要用来接收前端传递给后端的json字符串中的数据的(请求体中的数据的);

    GET方式无请求体,所以使用@RequestBody接收数据时,前端不能使用GET方式提交数据,而是用POST方式进行提交。

    在后端的同一个接收方法里,@RequestBody 与@RequestParam()可以同时使用,@RequestBody最多只能有一个,而@RequestParam()可以有多个。

    注:一个请求,只有一个RequestBody;一个请求,可以有多个RequestParam

    原因:

    @requestbody的含义是在当前对象获取整个http请求的body里面的所有数据,因此spring就不可能将这个数据强制包装成Course或者List类型,并且从@requestbody设计上来说,只获取一次就可以拿到请求body里面的所有数据,就没必要出现有多个@requestbody出现在controller的函数的形参列表当中

    如果想解决这种问题

    1.新建一个包装上面两种entity的entity类:

    2..用Map<String, Object>接受request body,自己反序列化到各个entity中。

    注:当同时使用@RequestParam()和@RequestBody时,@RequestParam()指定的参数可以是普通元素、数组、集合、对象等等(即:当,@RequestBody 与@RequestParam()可以同时使用时,原SpringMVC接收参数的机制不变,只不过RequestBody 接收的是请求体里面的数据;而RequestParam接收的是key-value里面的参数,所以它会被切面进行处理从而可以用普通元素、数组、集合、对象等接收)。

    即:如果参数时放在请求体中,传入后台的话,那么后台要用@RequestBody才能接收到;如果不是放在请求体中的话,那么后台接收前台传过来的参数时,要用@RequestParam()来接收,或则形参前什么也不写也能接收

    注:如果参数前写了@RequestParam(xxx),那么前端必须有对应的xxx名字才行(不管其是否有值),如果没有xxx名的话,那么请求会出错,报400

    注:如果参数前不写@RequestParam(xxx)的话,那么就前端可以有可以没有对应的xxx名字才行,如果有xxx名的话,那么就会自动匹配;没有的话,请求也能正确发送。

        追注:这里与feign消费服务时不同;feign消费服务时,如果参数前什么也不写,那么会被默认是@RequestBody的

    注:如果后端参数是一个对象,且该参数前是以@RequestBody修饰的,那么前端传递json参数时,必须满足以下要求:

    后端@RequestBody注解对应的类在将HTTP的输入流(含请求体)装配到目标类(即:@RequestBody后面的类)时,
       会根据json字符  串中的key来匹配对应实体类的属性,如果匹配一致且json中的该key对应的值符合(或可转换为)
       实体类的对应属性的类型要求时,会调用实体类的setter方法将值赋给该属性
    ,这一条我会在本节末尾详细分析,
       其他的都可简单略过,但是
    本文末的核心逻辑代码以及几个结论一定要看!

    json字符串中,如果value为""的话,后端对应属性如果是String类型的,那么接受到的就是"",如果是后端属性的
      类型是Integer、Double等类型,那么接收到的就是null

    json字符串中,如果value为null的话,后端对应收到的就是null。

    如果某个参数没有value的话,在传json字符串给后端时,要么干脆就不把该字段写到json字符串中;要么写value时,
        必须有值,null  或""都行
    千万不能有类似"stature":,这样的写法,如:

    注:关于@RequestParam()的用法,这里就不再一一说明了,可详见 《程序员成长笔记(一)》中的相关章节。

    微笑声明:以下代码为图片版,项目代码托管在https://github.com/JustryDeng/PublicRepository

    示例详细说明:

    先给出两个等下要用到的实体类

    User实体类:

    Team实体类:

     

    @RequestBody直接以String接收前端传过来的json数据

    后端对应的Controller:

    使用PostMan测试:

    @RequestBody以简单对象接收前端传过来的json数据

    后端对应的Controller:

     

    使用PostMan测试:

     

    @RequestBody以复杂对象接收前端传过来的json数据

    后端对应的Controller:

    使用PostMan测试:

    @RequestBody与简单的@RequestParam()同时使用

    后端对应的Controller:

    使用PostMan测试:

     

    @RequestBody与复杂的@RequestParam()同时使用

    后端对应的Controller:

    使用PostMan测试:

    @RequestBody接收请求体中的json数据;不加注解接收URL中的数据并组装为对象

    后端对应的Controller:

    使用PostMan测试:

    注:如果在后端方法参数前,指定了@RequestParam()的话,那么前端必须要有对应字段才行,否者会报错;如果参数前没有任何该注解,那么前端可以传,也可以不传

     如:

     

    中,如果我们传参中没有指定token,那么请求能正常进去,但是token为null;如果在String token前指定了@RequestParam(“token”),那么前端必须要有token这个键时,请求才能正常进去,否者报400错误。

    @RequestBody与前端传过来的json数据的匹配规则

    声明:根据不同的Content-Type等情况,Spring-MVC会采取不同的HttpMessageConverter实现来进行信息转换解析。
            下面介绍的是最常用的:前端以Content-Type 为application/json,传递json字符串数据;后端以@RequestBody
             模型接收数据的情况。

    解析json数据大体流程概述
              Http传递请求体信息,最终会被封装进com.fasterxml.jackson.core.json.UTF8StreamJsonParser中(提
              示:Spring采用CharacterEncodingFilter设置了默认编码为UTF-8。),然后在
             public class BeanDeserializer extends BeanDeserializerBase implements java.io.Serializable中,
             通过
     public Object deserializeFromObject(JsonParser p, DeserializationContext ctxt) throws IOException
             
    方法
    进行解析

    假设前端传的json串是这样的: {"name1":"邓沙利文","age":123,"mot":"我是一只小小小小鸟~"} 后对的模型只有name和age属性,以及对应的setter/getter方法;给出一般用到的deserializeFromObject(JsonParser p, DeserializationContext ctxt)方法的

    核心逻辑

    小技巧 之 指定模型中的属性对应什么key

    这里简单介绍,更多的可参考:

               public class BeanPropertyMap implements Iterable<SettableBeanProperty>,java.io.Serializable

    给出Controller中的测试类:

    给出模型中的属性(setter/getter方法没截出来):

    使用postman测试一下,示例:

    上图简单测试了一下,但是测得并不全面,这里就不带大家一起测试了,直接给出

    全面的结论

    结论:@JsonAlias注解,实现:json转模型时,使json中的特定key能转化为特定的模型属性;但是模型转json时,对应的
                转换后的key  仍然与属性名一致,见:上图示例中的name字段的请求与响应。
                注:以下图进一步说明

                      此时,json字符串转换为模型时,json中key为Name或为name123或为name的都能识别。

    结论:@JsonProperty注解,实现:json转模型时,使json中的特定key能转化为指定的模型属性;同样的,模型转json
                时,对应的转换后的key为指定的key,见:示例中的motto字段的请求与响应。
               注:以下图进一步说明

                   此时,json字符串转换为模型时,key为MOTTO的能识别,但key为motto的不能识别。

    结论:@JsonAlias注解需要依赖于setter、getter,而@JsonProperty注解不需要。

    结论:在不考虑上述两个注解的一般情况下,key与属性匹配时,默认大小写敏感。

    结论:有多个相同的key的json字符串中,转换为模型时,会以相同的几个key中,排在最后的那个key的值给模型属性
                 复制,因为setter会覆盖原来的值。见示例中的gender属性。

    结论:后端@RequestBody注解对应的类在将HTTP的输入流(含请求体)装配到目标类(即:@RequestBody后面
                的类)时,会根据json字符串中的key来匹配对应实体类的属性,如果匹配一致且json中的该key对应的值符
               合(或可转换为)实体类的对应属性的类型要求时,会调用实体类的setter方法将值赋给该属性。

    微笑如有不当之处,欢迎指正

    微笑代码托管链接https://github.com/JustryDeng/PublicRepository

    微笑本文已经被收录进《程序员成长笔记(二)》,笔者JustryDeng

    				<script>
    					(function(){
    						function setArticleH(btnReadmore,posi){
    							var winH = $(window).height();
    							var articleBox = $("div.article_content");
    							var artH = articleBox.height();
    							if(artH > winH*posi){
    								articleBox.css({
    									'height':winH*posi+'px',
    									'overflow':'hidden'
    								})
    								btnReadmore.click(function(){
    									if(typeof window.localStorage === "object" && typeof window.csdn.anonymousUserLimit === "object"){
    										if(!window.csdn.anonymousUserLimit.judgment()){
    											window.csdn.anonymousUserLimit.Jumplogin();
    											return false;
    										}else if(!currentUserName){
    											window.csdn.anonymousUserLimit.updata();
    										}
    									}
    									
    									articleBox.removeAttr("style");
    									$(this).parent().remove();
    								})
    							}else{
    								btnReadmore.parent().remove();
    							}
    						}
    						var btnReadmore = $("#btn-readmore");
    						if(btnReadmore.length>0){
    							if(currentUserName){
    								setArticleH(btnReadmore,3);
    							}else{
    								setArticleH(btnReadmore,1.2);
    							}
    						}
    					})()
    				</script>
    				</article>
  • 相关阅读:
    .net core读取appsettings.config中文乱码问题
    vs2017错误:当前页面的脚本发生错误
    VS Code中无法识别npm命令
    Visual Studio报错/plugin.vs.js,行:1074,错误:缺少标识符、字符串或数字
    记录一次在生成数据库服务器上出现The timeout period elapsed prior to completion of the operation or the server is not responding.和Exception has been thrown by the target of an invocation的解决办法
    Java集合框架
    java hash表
    Java Dictionary 类存储键值
    java数据结构 栈stack
    java封装
  • 原文地址:https://www.cnblogs.com/zhuhui-site/p/10088238.html
Copyright © 2011-2022 走看看