在原生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能为我们完成更灵活的参数绑定工作,在上一个实例中,我们通过名称对应简单地完成了参数绑定,假如我们现在有需求:
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 | 默认参数值 |
根据项目需求合理地使用以上三个参数值,能在实际开发中为我们带来一定的便利。
在一般情况下,我们要获取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设置不存在时的默认值
我们先来看一个完整的的头信息组成
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]
在HttpServlet中,我们可以通过request.getReader()方法读取请求信息,使用response.getOutputStream(),getWriter()方法输出响应信息,通样的,在springMVC中,我们可以将上述IO对象绑定到方法入参中使用。我们来看代码实例
@RequestMapping("IO")
public void IO(BufferedReader reader,PrintWriter printWriter ){
System.out.println(reader);//输出org.apache.catalina.connector.CoyoteReader@368433b8
System.out.println(printWriter);//输出org.apache.catalina.connector.CoyoteWriter@215f90fe
}
@RequestMapping("IO2")
public void IO2(InputStream inputStream,OutputStream outputStream){
System.out.println(inputStream);//输出org.apache.catalina.connector.CoyoteInputStream@3c37a4ed
System.out.println(outputStream);//输出org.apache.catalina.connector.CoyoteOutputStream@692ce27d
}
@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**包装和绑定**,输入输出各一个,如果同类超过一个,就会报错