mvc-bind-annotatioan

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";
    }
原文地址:https://www.cnblogs.com/QianYue111/p/13840723.html