在上一篇文章中我们简单介绍了@RequestMapping与@RequestParam注解,知道了如何去配置地址映射,本篇则介绍一些用于处理request数据的注解。
1.@RequestHeader注解,该注解用于处理request中的header部分,也就是http请求头的部分,它可以把header部分的值绑定到方法的参数上,示例:
package org.zero01.test;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/test")
public class Test {
@RequestMapping("test.do")
public void method(
@RequestHeader("Host") String host,
@RequestHeader("Content-Type") String contentType
){
System.out.println(host);
System.out.println(contentType);
}
}
使用Postman进行访问,访问方式如下:
控制台打印结果:
localhost:8080
application/json
从打印结果可以看到,以上的代码把http请求头中的Host以及Content-Type字段的值,都绑定到了注解配置的方法参数上,这就是@RequestHeader注解的作用。
2.@CookieValue注解,该注解用于把http请求头中关于cookie的值绑定到方法的参数上,示例:
package org.zero01.test;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/test")
public class Test {
@RequestMapping("test.do")
public void method(
@CookieValue("JSEESIONID") String cookie
){
System.out.println(cookie);
}
}
使用Postman进行访问,访问方式如下:
控制台打印结果:
415A4AC178C59DACE0B2C9CA727CDD84
如上,@CookieValue注解帮我们把Cookie里JSEESIONID的值绑定到了该方法的参数中。
3.@PathVariable注解, 该注解可以把@RequestMapping注解中配置的URL占位符映射的值,绑定到相应的方法参数上,示例:
package org.zero01.test;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/test")
public class Test {
// 将URL上映射的值绑定到方法参数上,用 {} 来进行绑定
@RequestMapping("test.do/{typeid}/{id}")
public void method(
@PathVariable String typeid,
@PathVariable String id
) {
System.out.println(typeid);
System.out.println(id);
}
}
使用Postman进行访问,访问方式如下:
控制台打印结果:
8451
25
4.@RequestBody注解,该注解常用来处理application/json, application/xml等数据,也就是用于处理http请求体的内容。通过这个注解可以很轻松的获取到请求体的数据,再也不用像使用Servlet时那样通过流去读了,示例:
package org.zero01.test;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
@Controller
@RequestMapping("/test")
public class Test {
@RequestMapping("/test.do")
public void method(
@RequestBody String json
) {
System.out.println(json);
}
}
使用Postman进行访问,访问方式如下:
控制台打印结果:
{
"name" : "Jon",
"age" : 23,
"address" : "usa"
}
5.@SessionAttributes注解,该注解用来将方法参数中的值绑定到HttpSession的attribute中,这个注解是写在类上的,示例:
package org.zero01.test;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
@Controller
@SessionAttributes("name")
@RequestMapping("/test")
public class Test {
@RequestMapping("/test.do")
public void method(Map<String, Object> map) {
// 由于@SessionAttributes注解的作用,这对键值会被存储一份到HttpSession对象的attribute中
map.put("name", "Jon");
}
}
该注解有value、types两个属性,可以通过名字和类型来指定需要存储到HttpSession中的数据;示例:
package org.zero01.test;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
@Controller
@SessionAttributes(value = "name", types = Object.class)
@RequestMapping("/test")
public class Test {
@RequestMapping("/test.do")
public void method(Map<String, Object> map) {
// 由于@SessionAttributes注解的作用,这对键值会被存储一份到HttpSession对象的attribute中
map.put("name", "Jon");
}
}
6.@SessionAttribute注解,该注解用来访问预先存在的HttpSession中的属性值,例如HttpSession中存储了一个name的值,通过@SessionAttribute注解可以取出这个name的值,并且可以绑定到方法的参数上,所以这个注解是写在方法参数上的,示例:
package org.zero01.test;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
@Controller
@RequestMapping("/test")
public class Test {
@RequestMapping("/test.do")
// 拿出HttpSession中键为name的值,绑定到方法参数name上
public void method(@SessionAttribute("name") String name) {
}
}
7.@ModelAttribute注解,该注解有两个用法,一个是用于方法上,一个是用于参数上:
用在方法上的示例代码:
package org.zero01.test;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
@Controller
@RequestMapping("/test")
public class Test {
@ModelAttribute
@RequestMapping("/test.do")
public Account method(@RequestParam String number) {
return accountManager.findAccount(number);
}
}
用在参数上的示例代码:
package org.zero01.test;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
@Controller
@RequestMapping("/test")
public class Test {
@RequestMapping("/test.do")
public void method(@ModelAttribute String name) {
}
}
在控制器中要想获得HttpRequest以及HTTPResponse对象很简单,直接在方法上声明这两个对象的参数即可,示例:
package org.zero01.test;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Controller
@RequestMapping("/test")
public class Test {
@RequestMapping("/test.do")
public void method(HttpServletRequest request, HttpServletResponse response) {
System.out.println(request.getRequestURI());
System.out.println(response.getStatus());
}
}
使用Postman进行访问,访问方式如下:
控制台打印结果:
/test/test.do
200
通常url上会带有好几个参数,我们希望把这些参数都封装到某个对象的属性里,这样就不需要在方法上声明多个参数了,只需要声明一个对象即可。而SpringMVC可以自动帮我们完成这个事情,我们只需要创建一个封装类即可。例如我这里创建一个Student类,里面封装了与URL参数对应的属性:
Student类代码如下:
package org.zero01.test;
public class Student {
private String sname;
private int age;
private String address;
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
控制器代码如下:
package org.zero01.test;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
@Controller
@RequestMapping("/test")
public class Test {
@RequestMapping("/test.do")
// 只需要在方法上声明一个对象参数即可
public void method(Student student) {
System.out.println(student.getSname());
System.out.println(student.getAge());
System.out.println(student.getAddress());
}
}
使用Postman进行访问,访问方式如下:
控制台打印结果:
Jon
22
15
注:URL参数的名称要与对象属性的名称对应得上,不然是无法进行绑定的。如:
控制台打印结果:
Jon
0
null
SpringMVC除了可以自动帮我们绑定参数到pojo对象之外,还可以自动绑定参数到数组对象里,这里的数组指的是Integer、Stirng、Long等基本数据类型的包装类数组,以及int、long、byte等基本数据类型的数组,示例:
package org.zero01.test;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
@Controller
public class Test {
@RequestMapping(value = "/test.do")
public void method(String[] names) {
for (String name : names) {
System.out.println(name);
}
}
}
使用Postman进行访问,访问方式如下:
控制台打印结果:
Jon
Mack
Alin
Steven
Eson
基本数据类型的数组也是一样的:
package org.zero01.test;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
@Controller
public class Test {
@RequestMapping(value = "/test.do")
public void method(int[] numbers) {
for (int number : numbers) {
System.out.println(number);
}
}
}
使用Postman进行访问,访问方式如下:
控制台打印结果:
1
2
3
4
5
对于List、Set、Map等集合类型的参数绑定,如果我们尝试直接绑定,是会失败的,必须将其作为一个具体类对象的成员属性,这个时候我们也可称这个具体类对象为一个包装类。
POJO类代码如下:
package org.zero01.test;
import java.util.*;
public class Student {
private Map<String, Integer> map;
private List<String> list;
private Set<String> set;
public Map<String, Integer> getMap() {
return map;
}
public void setMap(Map<String, Integer> map) {
this.map = map;
}
public List<String> getList() {
return list;
}
public void setList(List<String> list) {
this.list = list;
}
public Set<String> getSet() {
return set;
}
public void setSet(Set<String> set) {
this.set = set;
}
}
控制器代码如下:
package org.zero01.test;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
@Controller
public class Test {
@RequestMapping(value = "/test.do")
public void method(Student student) {
System.out.println(student.getMap());
System.out.println(student.getList());
System.out.println(student.getSet());
}
}
使用Postman进行访问,访问方式如下:
控制台打印结果:
{one=1, three=3, tow=2}
[4, 5, 6]
[7, 8, 9]
在SpringMVC中控制器只需要通过方法的返回值就可以转发到某个指定的视图上,示例:
package org.zero01.test;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
@Controller
public class Test {
@RequestMapping(value = "/test.do", method = RequestMethod.GET)
public String method() {
return "index.jsp";
}
}
index.jsp内容如下:
<html>
<body>
<h2>Hello World!</h2>
</body>
</html>
使用Postman进行访问,访问结果如下:
默认情况下不加任何关键字是使用转发机制(forward),如果在视图名称前面加上redirect关键字则是使用重定向机制(redirect)示例:
package org.zero01.test;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
@Controller
public class Test {
@RequestMapping(value = "/test.do", method = RequestMethod.GET)
public String method() {
return "redirect:index.jsp";
}
}
但是大多数情况下为了安全性,我们一般会把jsp文件都放在WEB-INF目录下,而放在该目录下的jsp文件是无法通过重定向来进行访问的,只能通过转发机制进行访问。因为WEB-INF目录下的文件是不允许外部访问的,重定向属于外部访问,外部访问的话会报404错误,如下:
只能通过内部转发进行访问:
package org.zero01.test;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
@Controller
public class Test {
@RequestMapping(value = "/test.do")
public String method() {
return "WEB-INF/index.jsp";
}
}
访问结果:
在以上的实验中,我们只把jsp文件放在了WEB-INF目录下,但是如果这个jsp文件是在很多级目录下,那么我们通过返回值来转发到jsp上时,需要写的路径就很长了。例如我在WEB-INF目录下创建一个pages目录,在pages目录里再创建一个index目录,然后把index.jsp文件放在这个index目录下,那么我们需要写的路径就是这样子的:
package org.zero01.test;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
@Controller
public class Test {
@RequestMapping(value = "/test.do")
public String method() {
return "WEB-INF/pages/index/index.jsp";
}
}
如果不想写这么长的路径,就需要用到SpringMVC中的视图解析器了,在Spring配置文件中,添加如下内容:
<!-- 配置视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 视图名称的前缀 -->
<property name="prefix" value="/WEB-INF/pages/index/"/>
<!-- 视图名称的后缀 -->
<property name="suffix" value=".jsp"/>
</bean>
控制器代码:
package org.zero01.test;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
@Controller
public class Test {
@RequestMapping(value = "/test.do")
public String method() {
return "index";
}
}
从控制器代码中可以看到,配置了视图解析器之后,我们只需要写个视图的名称就可以了,不需要去写全路径。
访问结果:
SpringMVC中用于绑定请求数据的注解以及配置视图解析器
原文:http://blog.51cto.com/zero01/2086981