zoukankan      html  css  js  c++  java
  • spring 参数绑定

    部分资料来源:

    1. @RequestParam @RequestBody @PathVariable 等参数绑定注解详解
    2. spring学习之@ModelAttribute运用详解
    3. Spring MVC @ModelAttribute 详解

    简介

    handler method 参数绑定常用的注解,我们根据他们处理的Request的不同内容部分分为四类:(主要讲解常用类型)

    1. 处理requet uri 部分(这里指uri template中variable,不含queryString部分)的注解: @PathVariable;
    2. 处理request header部分的注解: @RequestHeader, @CookieValue;
    3. 处理request body部分的注解:@RequestParam, @RequestBody;
    4. 处理attribute类型是注解: @SessionAttributes, @ModelAttribute;

    @RequestBody作用:

    1. 该注解用于读取Request请求的body部分数据,使用系统默认配置的HttpMessageConverter进行解析,然后把相应的数据绑定到要返回的对象上;
    2. 再把HttpMessageConverter返回的对象数据绑定到 controller中方法的参数上。

    使用时机:

    1. GET、POST方式提时, 根据request header Content-Type的值来判断:
      application/x-www-form-urlencoded, 可选(即非必须,因为这种情况的数据 @RequestParam, @ModelAttribute也可以处理,当然 @RequestBody也能处理);
      multipart/form-data, 不能处理(即使用 @RequestBody不能处理这种格式的数据);
      其他格式, 必须(其他格式包括application/json, application/xml等。这些格式的数据,必须使用 @RequestBody来处理);
    2. PUT方式提交时, 根据request header Content-Type的值来判断:
      application/x-www-form-urlencoded, 必须;
      multipart/form-data, 不能处理;
      其他格式, 必须;
      说明:request的body部分的数据编码格式由header部分的Content-Type指定;

    @ResponseBody作用:
    该注解用于将Controller的方法返回的对象,通过适当的HttpMessageConverter转换为指定格式后,写入到Response对象的body数据区。
    使用时机:
    返回的数据不是html标签的页面,而是其他某种格式的数据时(如json、xml等)使用;

    @PathVariable

    当使用 @RequestMapping URI template 样式映射时, 即 someUrl/{paramId}, 这时的paramId可通过 @Pathvariable注解绑定它传过来的值到方法的参数上。

      @RequestMapping("/pets/{petId}")  
      public void findPet(@PathVariable String ownerId, @PathVariable String petId, Model model) {      
        // implementation omitted  
      }  
    

    上面代码把URI template 中变量 ownerId的值和petId的值,绑定到方法的参数上。
    若方法参数名称和需要绑定的uri template中变量名称不一致,需要在 @PathVariable("name")指定uri template中的名称。

    @RequestHeader, @CookieValue

    @RequestHeader 注解,可以把Request请求header部分的值绑定到方法的参数上。
    Request 的header部分示例:

    Host                    localhost:8080  
    Accept                  text/html,application/xhtml+xml,application/xml;q=0.9  
    Accept-Language         fr,en-gb;q=0.7,en;q=0.3  
    Accept-Encoding         gzip,deflate  
    Accept-Charset          ISO-8859-1,utf-8;q=0.7,*;q=0.7  
    Keep-Alive              300  
    

    注解示例:

    @RequestMapping("/displayHeaderInfo.do")  
    public void displayHeaderInfo(@RequestHeader("Accept-Encoding") String encoding,  
                                  @RequestHeader("Keep-Alive") long keepAlive)  {  
      
      //...  
      
    } 
    

    上面的代码,把request header部分的 Accept-Encoding的值,绑定到参数encoding上了,
    Keep-Alive header的值绑定到参数keepAlive上。

    @CookieValue 可以把Request header中关于cookie的值绑定到方法的参数上。
    cookie值如下:

    JSESSIONID=415A4AC178C59DACE0B2C9CA727CDD84  
    

    参数绑定的代码:

    @RequestMapping("/displayHeaderInfo.do")  
    public void displayHeaderInfo(@CookieValue("JSESSIONID") String cookie)  {  
      
      //...  
      
    }  
    

    即把JSESSIONID的值绑定到参数cookie上。

    @RequestParam, @RequestBody

    @RequestParam

    1. 常用来处理简单类型的绑定,通过Request.getParameter()
      获取的String可直接转换为简单类型的情况( String--> 简单类型的转换操作由ConversionService配置的转换器来完成);
      因为使用request.getParameter()方式获取参数,所以可以处理get 方式中queryString的值,也可以处理post方式中 body data的值;

    2. 用来处理Content-Type: 为 application/x-www-form-urlencoded编码的内容,提交方式GET、POST;

    3. 该注解有两个属性: value、required; value用来指定要传入值的id名称,required用来指示参数是否必须绑定;

      @Controller
      @RequestMapping("/pets")
      @SessionAttributes("pet")
      public class EditPetForm {

       // ...  
      
       @RequestMapping(method = RequestMethod.GET)  
       public String setupForm(@RequestParam("petId") int petId, ModelMap model) {  
           Pet pet = this.clinic.loadPet(petId);  
           model.addAttribute("pet", pet);  
           return "petForm";  
       }  
      

      // ...

    @RequestBody

    该注解常用来处理Content-Type: 不是application/x-www-form-urlencoded编码的内容,例如application/json, application/xml等;
    它是通过使用HandlerAdapter 配置的HttpMessageConverters来解析post data body,然后绑定到相应的bean上的。

    @RequestMapping(value = "/something", method = RequestMethod.PUT)  
    public void handle(@RequestBody String body, Writer writer) throws IOException {  
      writer.write(body);  
    } 
    

    @SessionAttributes, @ModelAttribute

    @SessionAttributes:
    该注解用来绑定HttpSession中的attribute对象的值,便于在方法中的参数里使用。
    该注解有value、types两个属性,可以通过名字和类型指定要使用的attribute 对象。
    详细描述:
    在默认情况下,ModelMap 中的属性作用域是 request 级别是,也就是说,当本次请求结束后,ModelMap 中的属性将销毁。如果希望在多个请求中共享 ModelMap 中的属性,必须将其属性转存到 session 中,这样 ModelMap 的属性才可以被跨请求访问。
    Spring 允许我们有选择地指定 ModelMap 中的哪些属性需要转存到 session 中,以便下一个请求属对应的 ModelMap 的属性列表中还能访问到这些属性。这一功能是通过类定义处标注 @SessionAttributes 注解来实现的。

    使模型对象的特定属性具有 Session 范围的作用域

    package com.baobaotao.web;  
    
    …  
    import org.springframework.ui.ModelMap;  
    import org.springframework.web.bind.annotation.SessionAttributes;  
      
    @Controller  
    @RequestMapping("/bbtForum.do")  
    @SessionAttributes("currUser") 
    //①.将ModelMap中属性名为currUser的属性  
    //放到Session属性列表中,以便这个属性可以跨请求访问  
    public class BbtForumController {  
    …  
        @RequestMapping(params = "method=listBoardTopic")  
        public String listBoardTopic(@RequestParam("id")int topicId, User user,  
    ModelMap model) {  
            bbtForumService.getBoardTopics(topicId);  
            System.out.println("topicId:" + topicId);  
            System.out.println("user:" + user);  
            model.addAttribute("currUser",user); //②.向ModelMap中添加一个属性  
            return "listTopic";  
        }  
    }  
    

    我们在 ② 处添加了一个 ModelMap 属性,其属性名为 currUser,而 ① 处通过 @SessionAttributes 注解将 ModelMap 中名为 currUser 的属性放置到 Session 中,所以我们不但可以在 listBoardTopic() 请求所对应的 JSP 视图页面中通过 request.getAttribute(“currUser”) 和 session.getAttribute(“currUser”) 获取 user 对象,还可以在下一个请求所对应的 JSP 视图页面中通过 session.getAttribute(“currUser”) 或 ModelMap#get(“currUser”) 访问到这个属性。
    这里我们仅将一个 ModelMap 的属性放入 Session 中,其实 @SessionAttributes 允许指定多个属性。你可以通过字符串数组的方式指定多个属性,如 @SessionAttributes({“attr1”,”attr2”})。此外,@SessionAttributes 还可以通过属性类型指定要 session 化的 ModelMap 属性,如 @SessionAttributes(types = User.class),当然也可以指定多个类,如 @SessionAttributes(types = {User.class,Dept.class}),还可以联合使用属性名和属性类型指定:@SessionAttributes(types = {User.class,Dept.class},value={“attr1”,”attr2”})。

    @ModelAttribute具有如下三个作用:

    1. 绑定请求参数到命令对象:放在功能处理方法的入参上时,用于将多个请求参数绑定到一个命令对象,从而简化绑定流程,而且自动暴露为模型数据用于视图页面展示时使用。其实 @ModelAttribute此处对于供视图页面展示来说与model.addAttribute("attributeName", abc);功能类似。
      此处多了一个注解 @ModelAttribute("user"),它的作用是将该绑定的命令对象以“user”为名称添加到模型对象中供视图页面展示使用。我们此时可以在视图页面使用${user.username}来获取绑定的命令对象的属性。

      public String test(@ModelAttribute("user") UserModel user) {
      // do sth.
      }

    2. 暴露 @RequestMapping 方法返回值为模型数据:放在功能处理方法的返回值上时,是暴露功能处理方法的返回值为模型数据,用于视图页面展示时使用。
      大家可以看到返回值类型是命令对象类型,而且通过 @ModelAttribute("user2")注解,此时会暴露返回值到模型数据( 名字为user2 ) 中供视图展示使用
      @ModelAttribute 注解的返回值会覆盖 @RequestMapping 注解方法中的 @ModelAttribute 注解的同名命令对象.

      public @ModelAttribute("user2") UserModel test3(@ModelAttribute("user2") UserModel user) {
      // do sth.
      }

    3. 暴露表单引用对象为模型数据:放在处理器的一般方法(非功能处理方法)上时,是为表单准备要展示的表单引用对象,如注册时需要选择的所在城市等,而且在执行功能处理方法(@RequestMapping 注解的方法)之前,自动添加到模型对象中,用于视图页面展示时使用。

    在Spring MVC里,@ModelAttribute通常使用在Controller方法的参数注解中,用于解释model entity,但同时,也可以放在方法注解里。
    如果把 @ModelAttribute放在方法的注解上时,代表的是:该Controller的所有方法在调用前,先执行此 @ModelAttribute方法。

    @Controller
    @RequestMapping(value="test")
    public class PassportController {
    
        @ModelAttribute
        public void preRun() {
            System.out.println("Test Pre-Run");
        }
        
        @RequestMapping(method=RequestMethod.GET)
        public String index() {
            return "login/index";
        }
        
        @RequestMapping(value="login", method=RequestMethod.POST)
        public ModelAndView login(@ModelAttribute @Valid Account account, BindingResult result)
            :
            :
        }
        
        @RequestMapping(value="logout", method=RequestMethod.GET)
        public String logout() {
            :
            :
        }
        
    }
    

    在调用所有方法之前,都会先执行preRun()方法。
    我们可以把这个 @ModelAttribute特性,应用在BaseController当中,所有的Controller继承BaseController,即可实现在调用Controller时,先执行 @ModelAttribute方法。
    比如权限的验证(也可以使用Interceptor)等

  • 相关阅读:
    13、字符串相互匹配删除
    12、指定长度替换制表符
    11、输入字符颠倒输出
    10、字符串输入删除末尾特殊符,清除空行
    9、筛选满足长度条件的输入内容进行输出
    8、获取输入的字符串并输出最长的那个
    7、初识函数
    6、计数垂直直方图输出
    5、计数水平直方图输出
    Tiny4412 Uboot
  • 原文地址:https://www.cnblogs.com/cuiyf/p/6247862.html
Copyright © 2011-2022 走看看