SpringMVC - 方法中的各种参数绑定方式

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

A、处理request uri 部分(这里指uri template中variable,不含queryString部分)的注解: @PathVariable;

B、处理request header部分的注解: @RequestHeader, @CookieValue;

C、处理request body部分的注解:@RequestParam, @RequestBody;

D、处理attribute类型是注解: @SessionAttributes, @ModelAttribute;


【1】@PathVariabl注解获取路径中传递参数

  • 只能绑定路径中的参数,且路径中必须有参数

如:

Request URL:http://localhost:8080/SpringMVC-1/springmvc/testPathVariable/1

  • 后台接收方法
@RequestMapping(value= " /testPathVariable/{id}/{str} " )  
 public ModelAndView helloWorld(@PathVariable String id, @PathVariable String str) {  
 System.out.println(id);  
 System.out.println(str);  
 return new ModelAndView( " /helloWorld " );  
}  

【2】@RequestParam注解获取请求参数

A) 常用来处理简单类型的绑定,通过Request.getParameter() 获取的String可直接转换为简单类型的情况( String–> 简单类型的转换操作由ConversionService配置的转换器来完成)。

因为使用request.getParameter()方式获取参数,所以可以处理get 方式中queryString的值(key : value 形式),也可以处理post方式中 body data的值;

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

C) 该注解有三个属性: value、required、defaultValue; value用来指定要传入值的id名称;required用来指示参数是否必须绑定,默认为true;defaultValue为设置默认值。

示例代码:

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

    // ...

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

请求参数位于链接中:

http://localhost:8080/Springmvc/user/page.do?pageSize=3&pageNow=2

@RequestMapping(value= "/page.do " )  
public String page(@RequestParam(value="pageSize",required)  int pageSize,@RequestParam(value="pageNow",required)  int pageNow){
    System.out.println(pageSize+""+pageNow);
    return "test";
}

【3】@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上。


【4】@CookieValue 可以把Request header中关于cookie的值绑定到方法的参数上

例如有如下Cookie值:


JSESSIONID=415A4AC178C59DACE0B2C9CA727CDD84

参数绑定的代码:

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

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


【5】@RequestBody

该注解常用来处理Content-Type: 不是application/x-www-form-urlencoded编码的内容,例如application/json, application/xml等。

它是通过使用HandlerAdapter 配置的HttpMessageConverters来解析post data body,然后绑定到相应的bean上的。

如果配置有FormHttpMessageConverter,所以也可以用来处理 application/x-www-form-urlencoded的内容,处理完的结果放在一个MultiValueMap

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

如果方法参数使用了该注解,但是请求头中的ContentType非application/json, application/xml,则会抛出Resolved exception caused by Handler execution: org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported类似异常!!!


【6】@SessionAttributes

该注解用来绑定HttpSession中的attribute对象的值,便于在方法中的参数里使用。在整个会话期间都有效。

该注解有value、types两个属性,可以通过名字和类型指定要使用的attribute 对象;

【value属性值为字符串数组,故可以放多个键的名字 如”user”,”name”】

@SessionAttributes 除了可以通过属性名指定需要放到会话中的属性外(实际上使用的是 value 属性值),
还可以通过模型属性的对象类型指定哪些模型属性需要放到会话中(实际上使用的是 types 属性值)

注意: 该注解只能放在类的上面. 而不能修饰放方法.


示例代码:

@SessionAttributes(value={"user"}, types={String.class})
@RequestMapping("/springmvc")
@Controller
public class SpringMVCTest {

    @RequestMapping("/testSessionAttributes")
    public String testSessionAttributes(Map map){
        User user = new User("Tom", "123456", "[email protected]", 15);
        map.put("user", user);
        /*值的类型是string 自动放入类注解的requestScope sessionScope
         * @SessionAttributes(value={"user"}, types={String.class})
         * */
        map.put("school", "atguigu");
        return SUCCESS;
    }
}
  • result as follows :

SpringMVC - 方法中的各种参数绑定方式_第1张图片

如上图所示,map里面的对象将默认放入request域中;因为使用了@SessionAttributes(value={“user”}, types={String.class}) 注解,故user 和 school 也会自动放入session中。

所以页面从两个域取值,都可以正确取到。


【7】@ModelAttribute

该注解有两个用法,一个是用于方法上,一个是用于参数上;

用于方法上时: 通常用来在处理@RequestMapping之前,为请求绑定需要从后台查询的model;该方法会首先调用。【此时是向model里面加入数据】

用于参数上时: 用来通过名称对应,把相应名称的值绑定到注解的参数bean上;【此时是从model里面寻找并取出数据】要绑定的值来源于:

A) @SessionAttributes 启用的attribute 对象上;

B) @ModelAttribute 用于方法上时指定的model对象;

C) 上述两种情况都没有时,new一个需要绑定的bean对象,然后把request中按名称对应的方式把值绑定到bean中。

用到方法上@ModelAttribute的示例代码:

// Add one attribute
// The return value of the method is added to the model under the name "account"
// You can customize the name via @ModelAttribute("myAccount")

@ModelAttribute("account")
public Account addAccount(@RequestParam String number) {
    return accountManager.findAccount(number);
}

这种方式实际的效果就是在调用@RequestMapping的方法之前,为request对象的model里put(“account”, Account);

用在参数上的@ModelAttribute示例代码:

@RequestMapping(value="/owners/{ownerId}/pets/{petId}/edit", method = RequestMethod.POST)
public String processSubmit(@ModelAttribute("pet") Pet pet) {

}

首先查询 @SessionAttributes有无绑定的Pet对象,若没有则查询@ModelAttribute方法层面上是否绑定了Pet对象,若没有则将URI template中的值按对应的名称绑定到Pet对象的各属性上。


【8】@RequestBody和@RequestParam区别

@RequestParam

用来处理Content-Type: 为 application/x-www-form-urlencoded编码的内容。(Http协议中,如果不指定Content-Type,则默认传递的参数就是application/x-www-form-urlencoded类型)

RequestParam可以接受简单类型的属性,也可以接受对象类型。实质是将Request.getParameter() 中的Key-Value参数Map利用Spring的转化机制ConversionService配置,转化成参数接收对象或字段。

在Content-Type: application/x-www-form-urlencoded的请求中, get 方式中queryString的值,和post方式中 body data的值都会被Servlet接受到并转化到Request.getParameter()参数集中,所以@RequestParam可以获取的到。


@RequestBody

处理HttpEntity传递过来的数据,一般用来处理非Content-Type: application/x-www-form-urlencoded编码格式的数据。

GET请求中,因为没有HttpEntity,所以@RequestBody并不适用。

POST请求中,通过HttpEntity传递的参数,必须要在请求头中声明数据的类型Content-Type,SpringMVC通过使用HandlerAdapter 配置的HttpMessageConverters来解析HttpEntity中的数据,然后绑定到相应的bean上。

总结

在GET请求中,不能使用@RequestBody。

在POST请求,可以使用@RequestBody和@RequestParam,但是如果使用@RequestBody,对于参数转化的配置必须统一。

举个例子,在SpringMVC配置了HttpMessageConverters处理栈中,指定json转化的格式,如Date转成‘yyyy-MM-dd’,则参数接收对象包含的字段如果是Date类型,就只能让客户端传递年月日的格式,不能传时分秒。因为不同的接口,它的参数可能对时间参数有不同的格式要求,所以这样做会让客户端调用同事对参数的格式有点困惑,所以说扩展性不高。

如果使用@RequestParam来接受参数,可以在接受参数的model中设置@DateFormat指定所需要接受时间参数的格式。

另外,使用@RequestBody接受的参数是不会被Servlet转化统一放在request对象的Param参数集中,@RequestParam是可以的。

综上所述,一般情况下,推荐使用@RequestParam注解来接受Http请求参数。

你可能感兴趣的:(SpringMVC)