RequestBody
@RequestBody主要用来接收前端传递给后端的json字符串中的数据的(请求体中的数据的);GET方式无请求体,所以使用@RequestBody接收数据时,前端不能使用GET方式提交数据,而是用POST方式进行提交;如果后端参数是一个对象,且该参数前是以@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": ,这样的写法,如:
@RequestBody与前端传过来的json数据的匹配规则
声明:根据不同的Content-Type等情况,Spring-MVC会采取不同的HttpMessageConverter实现来进行信息转换解析
全面的结论:
结论①:@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://blog.csdn.net/justry_deng/article/details/80972817
RequestParam
将请求参数绑定到你控制器的方法参数上
语法:@RequestParam(value=”参数名”,required=”true/false”,defaultValue=””)
RequestHeader
@RequestHeader 是获取请求头中的数据,通过指定参数 value 的值来获取请求头中指定的参数值。其他参数用法和 @RequestParam 完全一样
RequestMapping
在Spring MVC 中使用 @RequestMapping 来映射请求,也就是通过它来指定控制器可以处理哪些URL请求,相当于Servlet中在web.xml中配置
<servlet> <servlet-name>servletName</servlet-name> <servlet-class>ServletClass</servlet-class> </servlet> <servlet-mapping> <servlet-name>servletName</servlet-name> <url-pattern>url</url-pattern> </servlet-mapping>
的映射作用一致
RequestPart
@RequestPart这个注解用在multipart/form-data表单提交请求的方法上。支持的请求方法的方式MultipartFile,属于Spring的MultipartResolver类。这个请求是通过http协议传输的。
类似于@RequestParam,不过是用来接收文件的
ResponseStatus
此注解声明在方法、类上
@Controller @RequestMapping(value = "/bind") public class BindController { /** * 用法一,标注在方法上 * code reason value三种属性 * value 和 code是一个含义, 默认值就是 服务器 500错误的 HttpStatus,作用就是改变服务器响应的状态码 * reason是异常原因 * @return */ @ResponseStatus(code=HttpStatus.OK)//状态码200 @RequestMapping(value = "/index") public String index() { return "index"; } }
https://www.cnblogs.com/lvbinbin2yujie/p/10575101.html
CookieValue
用来获取Cookie中的值
参数:value:参数名称; required:是否必须 ;defaultValue:默认值
@RequestMapping("/testCookie.action") public String testCookie(@CookieValue("JSESSIONID") String sessionId) { System.out.println("testCookieValue: sessionId: " + sessionId); return "msg"; }
DeleteMapping
相当于@RequestMapping(value = "",method = RequestMethod.GET)
GetMapping
处理get请求,相当于@RequestMapping(value = "",method = RequestMethod.DELETE)
PostMapping
处理post请求,相当于@RequestMapping(value = "",method = RequestMethod.POST)
PutMapping
和PostMapping作用等同,都是用来向服务器提交信息。如果是添加信息,倾向于用@PostMapping,如果是更新信息,倾向于用@PutMapping。两者差别不是很明显
PatchMapping
Patch方式是对put方式的一种补充;
put方式是可以更新.但是更新的是整体.patch是对局部更新;
InitBinder
作用一
从字面意思可以看出这个的作用是给Binder做初始化的,被此注解的方法可以对WebDataBinder初始化。webDataBinder是用于表单到方法的数据绑定的!
@InitBinder只在@Controller中注解方法来为这个控制器注册一个绑定器初始化方法,方法只对本控制器有效。
@InitBinder public void initBinder(WebDataBinder binder, HttpServletRequest request) { System.out.println(request.getParameter("date")); binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("MM-dd-yyyy"), false)); }
上面是一个@InitBinder的简单用法, 其中binder.registerCustomEditor(Date.class,new CustomDateEditor(new SimpleDateFormat("MM-dd-yyyy"),false)); 这样一句话,作用就是将 自定义的MVC属性编辑器PropertyEditor 注册到当前binder的typeConverter的customEditors集合中,每一次请求和后端交互,每一个Controller方法入参都会创建一个Binder对象,binder对象相当于来完成请求和后端之间参数类型转换的职能类; 注意,每次请求都会创建新的binder对象,就是说上次请求的customEditors不可复用 , 每次执行都会添加到当前方法入参交互的binder的customEditors中,而且每次执行真正请求方法之前,会把 匹配上的@InitBinder标注的方法执行一遍才开始处理;
当请求中参数和方法入参开始进行转换的时候,都会先使用自定义注册的PropertyEditor,会首先根据需要的类型去binder的typeConverter的typeConverterDelegate的propertyEditorRegistry的cutomEditors集合中查找,有点绕,先记录下,typeConverterDelegate的propertyEditorRegistry就是typeConverter对象本身, 所以就是去typeConverter对象的cutomEditors寻找自定义注册的属性编辑器,又回到了原点。 比如去customEditors中根据key为Date.class查找editor, 分为两种情况,一种是找到了合适的属性编辑器,调用其setValue、setAsText方法, 之后使用getValue就得到转换后的值, 得到了转换后的值,可能不是我们想要的类型,这时候就会使用 conversionService 重新来过,放弃之前的转换; 是我们想要的类型就直接返回转换后的值; 第二种情况是没找到合适的属性编辑器, 直接调用 ConversionService 进行转换工作;
作用二
binder.setFieldDefaultPrefix(fieldDefaultPrefix);
将springmvc请求参数带有fieldDefaultPrefix前缀的参数,去掉该前缀再绑定到对应的参数上,个人觉得是为了区分具有相同名字的参数
比如:
@Setter @Getter @ToString // 代码整洁所以使用lombok,可以自行百度 public class Pojo { private String name; private String haircolor; } @Setter @ToString public class Pojo2 { private String name; private int age; }
在两个对象上各使用@ModelAttribute,来给对象分别起别名, @Initbinder这里value属性指定 别名,然后给不同的参数加上了前缀 person. 、cat. ;注意这里的两个 . 号
@RequestMapping("/test3") @ResponseBody public String test3(@ModelAttribute("person") Pojo person, @ModelAttribute("cat") Pojo2 cat){ return "test Response Ok!"+person+","+cat; } @InitBinder("person") public void initPerson(WebDataBinder binder){ binder.setFieldDefaultPrefix("person."); } @InitBinder("cat") public void initCat(WebDataBinder binder){ binder.setFieldDefaultPrefix("cat."); }
这样请求URL:………… test3?person.name=lvbinbin&cat.name=xiaobinggan&haircolor=black&age=20 这里前台改动的地方就是 person.name和 cat.name,而其他独有属性不需要前缀也可以对应赋给pojo、pojo2; 补充说明,@ModelAttribute注解不可以省略,通过这个取的别名来决定哪个@InitBinder对其生效;
作用三
WebDataBinder的setDisallowedFields(disallowedFields);
SpringMvc接收请求参数时候,有些参数禁止的,不想接收,我也没遇到过啥情况禁止接收参数,这时候可以设置setDisallowedFields不接受参数
@RequestMapping("/test4") @ResponseBody public String test4(@ModelAttribute("pojo2") Pojo2 pojo){ return "test Response Ok!"+pojo; } @InitBinder("pojo2") public void disallowFlied(WebDataBinder binder){ binder.setDisallowedFields("age"); }
另外补充一下,disallowedFields支持 * 通配符;
@Initbinder的用法简而言之,就是Controller级别的属性编辑器,将请求中的String类型转为我们需要的参数,但是从效率、内存分析,感觉一直在创建新的属性编辑器集合,如果属性编辑器太多是不是会占用大量内存呢,那请求达到一定多的数量,这个对象是不是太多了呢?
https://www.cnblogs.com/lvbinbin2yujie/p/10459303.html
ModelAttribute
注解方法
被@ModelAttribute注释的方法会在此controller每个方法执行前被执行,因此对于一个controller映射多个URL的用法来说,要谨慎使用
1.@ModelAttribute注释void返回值的方法
@Controller public class HelloWorldController { @ModelAttribute public void populateModel(@RequestParam String abc, Model model) { model.addAttribute("attributeName", abc); } @RequestMapping(value = "/helloWorld") public String helloWorld() { return "helloWorld"; } }
这个例子,在获得请求/helloWorld 后,populateModel方法在helloWorld方法之前先被调用,它把请求参数(/helloWorld?abc=text)加入到一个名为attributeName的model属性中,在它执行后 helloWorld被调用,返回视图名helloWorld和model已由@ModelAttribute方法生产好了。
2.@ModelAttribute注释返回具体类的方法
@ModelAttribute public Account addAccount(@RequestParam String number) { return accountManager.findAccount(number); }
这种情况,model属性的名称没有指定,它由返回类型隐含表示,如这个方法返回Account类型,那么这个model属性的名称是account。
这个例子中model属性名称有返回对象类型隐含表示,model属性对象就是方法的返回值。它无须要特定的参数。
这个注解标注在方法上表示往model里加,标注在参数上表示从model中取值
@RequestMapping("/model.action") public String model(@ModelAttribute("car") Car car) { System.out.println(car); return "bind/model"; }
PathVariable
映射 URL 绑定的占位符
- 带占位符的 URL 是 Spring3.0 新增的功能,该功能在SpringMVC 向 REST 目标挺进发展过程中具有里程碑的意义
- 通过 @PathVariable 可以将 URL 中占位符参数绑定到控制器处理方法的入参中:URL 中的 {xxx} 占位符可以通过@PathVariable(“xxx“) 绑定到操作方法的入参中。
- 主要是根据请求方法进行类的区别
RequestAttribute
用在方法参数上,从request中取值
SessionAttribute
用在方法参数上,从session中取值
@RequestMapping("/path.action") public String session(@SessionAttribute("sessionStr")String sessionStr) { System.out.println(sessionStr); return "msg"; }
SessionAttributes
@ModelAttribute注解作用在方法上或者方法的参数上,表示将被注解的方法的返回值或者是被注解的参数作为Model的属性加入到Model中,然后Spring框架自会将这个Model传递给ViewResolver。Model的生命周期只有一个http请求的处理过程,请求处理完后,Model就销毁了。
通过@SessionAttributes注解设置的参数有3类用法:
(1)在视图中通过request.getAttribute或session.getAttribute获取
(2)在后面请求返回的视图中通过session.getAttribute或者从model中获取
(3)自动将参数设置到后面请求所对应处理器的Model类型参数或者有@ModelAttribute注释的参数里面。
将一个参数设置到SessionAttributes中需要满足两个条件:
(1)在@SessionAttributes注解中设置了参数的名字或者类型
(2)在处理器中将参数设置到了model中
@SessionAttributes用户后可以调用SessionStatus.setComplete来清除,这个方法只是清除SessionAttribute里的参数,而不会应用Session中的参数。
CrossOrigin
https://blog.csdn.net/MobiusStrip/article/details/84849418
MatrixVariable
未知
ControllerAdvice
对于@ControllerAdvice,我们比较熟知的用法是结合@ExceptionHandler用于全局异常的处理,但其作用不仅限于此。ControllerAdvice拆分开来就是Controller Advice,关于Advice,前面我们讲解Spring Aop时讲到,其是用于封装一个切面所有属性的,包括切入点和需要织入的切面逻辑。这里ContrllerAdvice也可以这么理解,其抽象级别应该是用于对Controller进行“切面”环绕的,而具体的业务织入方式则是通过结合其他的注解来实现的。@ControllerAdvice是在类上声明的注解,其用法主要有三点:
- 结合方法型注解@ExceptionHandler,用于捕获Controller中抛出的指定类型的异常,从而达到不同类型的异常区别处理的目的;
- 结合方法型注解@InitBinder,用于request中自定义参数解析方式进行注册,从而达到自定义指定格式参数的目的;
- 结合方法型注解@ModelAttribute,表示其标注的方法将会在目标Controller方法执行之前执行。
关于这三种使用方式,需要说明的是,这三种注解如果应用于@ControllerAdvice注解所标注的类中,那么它们表示会对@ControllerAdvice所指定的范围内的接口都有效;如果单纯的将这三种注解应用于某个Controller中,那么它们将只会对该Controller中所有的接口有效,并且此时是不需要在该Controller上标注@ControllerAdvice的
RestControllerAdvice
如果返回值为接送,则使用这个注解,其他与ControllerAdvice没啥不同
ExceptionHandler
用来异常处理
@RequestMapping("/exception.action") @ExceptionHandler({RuntimeException.class}) public String exceptionhandler() { return "msg"; }