springMVC方法入参灵活绑定

Posted jeanheo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了springMVC方法入参灵活绑定相关的知识,希望对你有一定的参考价值。

在原生Servlet中,我们通过在doGet和doPost方法绑定web资源访问接口:HttpServletRequest和HttpServletResponse到入参来进一步通过request.getParameter()等方法获取我们的web资源。在SpringMVC中,我们一样可以将HttpServletRequest和HttpServletResponse绑定到入参中使用,但除此之外,SpringMVC还能进一步分析我们处理方法的入参信息,将各类请求资源绑定到我们的方法入参上,并将数据类型转化为我们定义的类型,为我们可以节省了大量的参数获取、初始化工作。

简单名称对应绑定参数

最基本的数据绑定是通过参数名对应完成绑定,如下例

@RequestMapping("test")
public void test8(Integer id ){
    System.out.println(id);
}

下面我们访问root/test?id=111后面示例项目根路径默认使用“root”表示,),会发现控制台打印“111”,即控制台轻松的帮我们完成了入参绑定,这里我们定义id为Integer,如果我们定义String类型,spring也会帮我们完成相应的类型转换。而如果我们直接访问root.test,即不带任何参数,则方法入参id找不到对应的请求参数名,就为null了。
但现在,我们尝试访问root/test?id=aaa则服务器会响应400错误。这是因为类型转换异常“aaa”不能转换java.lang.Integer。

在这里,我们谈到的是基本类型绑定,但实际上,springMVC还可以帮我们完成很多复杂类型的数据绑定,如:自定义对象User,数组User[],List,Set,Map等,这些都会在我后面的文章提到,敬请关注

使用@RequestParam绑定参数

方法入参上使用注解@RequestParam能为我们完成更灵活的参数绑定工作,在上一个实例中,我们通过名称对应简单地完成了参数绑定,假如我们现在有需求:
1. 某个关键参数必须传入(比如登陆,我们要求必须有用户名和密码)
2. 某个参数可以不传,但必须要有默认值。

针对这些需求,我们来看下面实例:

@RequestMapping("login")
public void login(@RequestParam(value = "userName",required = true) String userName,//绑定userName,要求必须
        @RequestParam(value = "password",required = true) String pwd){//绑定password,因为在value上对应了,所以方法入参名称可以为其他字符串
    System.out.println(userName + "-" + pwd);
}
@RequestMapping("list")
public void list(@RequestParam(value = "pageNow",required = false , defaultValue = "1") Integer pageNow){//模拟分页查询,当前页码可以不传,默认为第一页
    System.out.println(pageNow);
}

@RequestParam涉及三个参数:

参数 说明
value 参数名
required 是否必须,一旦使用了@RequestParam注解,默认为true,如果不存在对应请求参数会出现异常:HTTP Status 400 - Required String parameter ‘userName‘ is not present
defaultValue 默认参数值

根据项目需求合理地使用以上三个参数值,能在实际开发中为我们带来一定的便利。

使用@CookieValue绑定cookie

在一般情况下,我们要获取cookie信息,需要使用request.getHeader("cookie")request.getCookies()等方法来获取,而使用@CookieValue能将我们需要的特定cookie信息绑定到方法入参中。

@RequestMapping("cookie")
public void cookie(@CookieValue(value = "JSESSIONID",required = false) String cookie ){
    System.out.println(cookie);
}

value指定了对应cookie的名称,required设置为false表示非必须的,它还有一个属性defaultValue设置不存在时的默认值

使用@RequestHeader绑定头信息

我们先来看一个完整的的头信息组成

Accept text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
Accept-Encoding gzip, deflate
Accept-Language en-US,en;q=0.5
Connection keep-alive
Host localhost:8080
User-Agent Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:45.0) Gecko/20100101 Firefox/45.0

在springMVC中,我们可以使用@RequestHeader来获取上述头信息的相应数值,如下面实例

@RequestMapping("headerInfo")
public void headerInfo(@RequestHeader("Accept-Encoding") String Encoding,
        @RequestHeader("Accept-Language") String Language,
        @RequestHeader("Cache-Control") String Cache,
        @RequestHeader("Connection") String Connection,
        @RequestHeader("Cookie") String Cookie,
        @RequestHeader("Host") String Host,
        @RequestHeader("User-Agent") String Agent
        ){
    System.out.println(Language);
    System.out.println(Cache);
    System.out.println(Connection);
    System.out.println(Cookie);
    System.out.println(Host);
    System.out.println(Agent);
}

访问/root/headerInfo,控制台打印:

en-US,en;q=0.5
max-age 0
keep-alive
JSESSIONID=854678F41A231776AFB366DE8A90A356
localhost:8080
Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:45.0) Gecko/20100101 Firefox/45.0

需要注意的是,如果我们这里缺少对应的头信息,而尝试获取的话,而抛出异常类似: Missing header ‘xxxxx’ of type [java.lang.String]

使用IO对象作为入参

在HttpServlet中,我们可以通过request.getReader()方法读取请求信息,使用response.getOutputStream(),getWriter()方法输出响应信息,通样的,在springMVC中,我们可以将上述IO对象绑定到方法入参中使用。我们来看代码实例

@RequestMapping("IO")
public void IO(BufferedReader reader,PrintWriter printWriter ){
    System.out.println(reader);//输出[email protected]
    System.out.println(printWriter);//输出[email protected]
}
@RequestMapping("IO2")
public void IO2(InputStream inputStream,OutputStream outputStream){
    System.out.println(inputStream);//输出[email protected]
    System.out.println(outputStream);//输出[email protected]
}
@RequestMapping("IO3")
public void IO3(InputStream inputStream,BufferedReader reader){
    System.out.println(inputStream);
    System.out.println(reader);
    //报错java.lang.IllegalStateException: getInputStream() has already been called for this request
}
@RequestMapping("IO4")
public void IO4(PrintWriter printWriter ,OutputStream outputStream){
    System.out.println(printWriter);
    System.out.println(outputStream);
    //报错java.lang.IllegalStateException: getWriter() has already been called for this response
}

从这里我们看到,spring会帮我们完成IO**包装和绑定**,输入输出各一个,如果同类超过一个,就会报错

以上是关于springMVC方法入参灵活绑定的主要内容,如果未能解决你的问题,请参考以下文章

springMVC4模型数据绑定全面分析

SpringMVC----@RequestMapping_PathVariable映射URL绑定的占位符

学习SpringMVC(十六)之数据绑定流程

数据绑定流程分析

解决SpringMVC入参出现The request sent by the client was syntactically incorrect请求语法错误方法

Spring MVC 基础篇 2