文章目录
Spring MVC 控制器详解
请求处理
1. 处理器映射
当你要处理请求映射时需要使用 @RequestMapping 注解。@RequestMapping 注解不仅可以放在函数前 也可以放在类前。
1.1 依据请求映射
a. 请求参数
对于请求参数的设置如下,使用 params 标注出使用 url 传递的变量的变量名称。
@RequestMapping( value="请求的URL" , params={"param1","param2"} )
如果设置 param1=value1 那么意味着当变量 param1 值为 value1 时才会跳转到相应的ulr,如果是 != 符号则意味着变量 param1 不为 value1 时才会跳转到相应 url。如果请求的 url 缺少任意一个需要的参数,控制器将不会相应请求。
欢迎页面
<h3><a href="demo1/reqParam?username=xiaoming&id=160017">test the request <u>Param</u></a></h3>
请求页面(testReqParam.jsp)
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<p>testSuccess</p>
</body>
</html>
控制器
public String REQPARAM = "testReqParam";
@RequestMapping(value="/reqParam",params = {"username","id=160017"})
public String testReqParam() {
return REQPARAM;
}
b. 请求方法
设置请求方法使得只有在使用该形式的请求时才会调用相应的控制器方法。设置方法为 method =
加上你所需的方法。
@RequestMapping( value="请求的URL" , method = RequestMethod.POST )
【示例】
欢迎页面 (index.jsp)
该页面设有两个链接,但是跳转路径相同,只不过一个是 get 请求,另一个是 post 请求。但是这两个请求会获得不同的页面
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<h3>
<a href="demo1/sucess">Click here to the sucess page</a>
</h3>
<br>
<form action="demo1/success" method="post">
<input type="submit" value="success">
</form>
<br>
</body>
</html>
GET 请求获得的页面(success.jsp)
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<h2>The SUCESS Page</h2>
<br>
</body>
</html>
POST 请求获得的页面
与 Get 请求页面不同的是,POST 请求显示的字是 SUCCESS2。
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<h2>The SUCESS2 Page</h2>
<br>
</body>
</html>
控制器类
在类中设置了两个分别对应的处理,当发送的是 POST 请求时会调用第二个函数,如果是 GET 请求则会调用第一个请求。
package cn.edu.stu.Demo1.handlers;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@RequestMapping("/demo1")
@Controller
public class Controller1 {
public String SUCESS = "sucess";
public String SUCESS2 = "sucess2";
@RequestMapping( value = "/success", method = RequestMethod.GET)
public String toSucess() {
System.out.println("got to the sucess page");
return SUCESS;
}
@RequestMapping( value = "/success", method = RequestMethod.POST)
public String sucessWithPost() {
return SUCESS2;
}
}
c. 请求头
@RequestMapping( value="请求的URL" , headers={"Accept-Language=en-US,zh-CN})
1.2 Ant 风格的 URL 映射
@RequestMapping 支持 Ant 风格的 URL
?
匹配文件中任意一个字符*
匹配任意多个字符**
匹配多层路径
1.3 REST 风格的 URL 映射
在讲述 REST 风格的 URL 映射时,需要用到获取路径变量的的知识
@PathVariable注解
使用 @PathVariable 注解有助于处理 REST 风格的 URL。
欢迎页面
<h3><a href="demo1/testPathVariable/15">Test Path Variable</a></h3>
控制器
@RequestMapping("/testPathVariable/{id}")
public String testPathVariable(@PathVariable("id") Integer id) {
System.out.println("get the path param : " + id);
return SUCESS;
}
HiddenHttpMethodFilter 过滤器
HiddenHttpMethodFilter 过滤器可以将数据库的操作放在隐藏域中,可以使用过滤器拦截 POST 请求,然后分别转发到不同操作的 URL 中
过滤器配置 web.xml
<filter>
<filter-name>HiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HiddenHttpMethoFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
页面
有关与数据库的请求放在名为 _method
的隐藏域中,其值可以为 GET,POST,DELETE,PUT
<h3><a href="demo1/testPathVariable/15">Test Path Variable</a></h3>
<form action="demo1/testPathVariable/15" method="post">
<input type="hidden" name="_method" value="DELETE">
<input type="submit" value="Delete">
</form>
<form action="demo1/testPathVariable/15" method="post">
<input type="hidden" name="_method" value="POST">
<input type="submit" value="POST">
</form>
<form action="demo1/testPathVariable" method="post">
<input type="hidden" name="_method" value="PUT">
<input type="submit" value="PUT">
</form>
跳转页面
在使用 HiddenHttpMethodFilter 时,会出先 DELETE 或 PUT 请求无法跳转而出现的 405 错误。此时最简单的做法是在需要跳转的 jsp 页面上添加 isErrorPage="true"
语句
控制器
@RequestMapping(value="/testPathVariable/{id}",method=RequestMethod.GET)
public String testPathVariable(@PathVariable Integer id) {
System.out.println("get the path param : " + id);
return SUCESS;
}
@RequestMapping(value="/testPathVariable/{id}",method=RequestMethod.DELETE)
public String testDelVariable(@PathVariable Integer id) {
System.out.println("Delete the value : " + id);
return SUCESS;
}
@RequestMapping(value="/testPathVariable",method=RequestMethod.PUT)
public String testPUTVariable() {
System.out.println("PUT Operation");
return SUCESS;
}
@RequestMapping(value="/testPathVariable/{id}",method=RequestMethod.POST)
public String testPOSTVariable(@PathVariable Integer id) {
System.out.println("POST the value : " + id);
return SUCESS;
}
2. 接受请求的输入
Spring MVC 允许以多种方式将客户端中的数据传送到控制器的处理方法中,包括:
- 参数查询(Query Parameter)
- 表单参数(Form Parameter)
- 路径变量(Path Parameter)
2.1 获取查询参数
要获取查询参数
查询参数是跟在 URL 中
请求发送页面
在请求的 url 中设置两个查询参数,分别是 username 和 id。
<h3><a href="demo1/testReqParam?username=xiaowang&id=160017">Request <u>Param</u> Annotation</a></h3>
控制器
在函数的参数列表中使用 @RequestParam 注解,用以获取查询的参数。括号中 value 后接参数名称。在 @RequestParam 后设定参数的变量类型变量名称。
@RequestMapping(value="/testReqParam")
public String testReqParam1(@RequestParam(value="username") String username,@RequestParam(value="id",required=false) int id ) {
System.out.println("The uernaem is :" + username + " and the id is :" + id);
return SUCESS;
}
2.2 获取路径变量
使用 @PathVariable 注解有助于处理 REST 风格的 URL。
欢迎页面
<h3><a href="demo1/testPathVariable/15">Test Path Variable</a></h3>
控制器
首先在 @RequestMapping 将路径变量的参数名用{}
标注出来。然后使用 @PathVariable 将路径参数引入到函数的形参列表中。
@RequestMapping("/testPathVariable/{id}")
public String testPathVariable(@PathVariable("id") Integer id) {
System.out.println("get the path param : " + id);
return SUCESS;
}
2.3 获取表单参数
使用 POJO 对象获取表单参数
创建一个 POJO 对象
package cn.edu.stu.Bean;
public class UserInfo {
public int id;
public String name;
public String password;
public int age;
public UserInfo() {
super();
}
public UserInfo(int id, String name, String password, int age) {
super();
this.id = id;
this.name = name;
this.password = password;
this.age = age;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "UserInfo [id=" + id + ", name=" + name + ", password=" + password + ", age=" + age + "]";
}
}
请求页面
表单中的 name 属性名称要和 POJO 对象保持一致。否侧会报错。
<h1> POJO 测试</h1>
<hr>
<form action="demo1/POJOTest" method="post">
id : <input type="text" name="id"/><br>
username: <input type="text" name="name"/><br>
password: <input type="password" name="password"/><br>
age: <input type="number" name="age"/><br>
<input type="submit" value="submit"/>
</form>
控制器
@RequestMapping(value="/POJOTest",method=RequestMethod.POST)
public String testPojo(UserInfo user) {
System.out.println(user);
return SUCESS;
}
3. 获取请求头
请求发送页面
<h3><a href="demo1/testReqHeader">Request Header Annotation</a></h3>
控制器
@RequestMapping(value="/testReqHeader")
public String testReqHeader(@RequestHeader(value="Accept-Language") String La) {
System.out.println("The Accept-Language is :" + La);
return SUCESS;
}
4. 获取 Cookie 的值
请求发送页面
<h3><a href="demo1/testCookieValue">Cookie Value Annotation</a></h3>
控制器
@RequestMapping(value="/testCookieValue")
public String testCookieValue(@CookieValue("JSESSIONID") String sessionId) {
System.out.println("The Session id = " + sessionId);
return SUCESS;
}
5. 获取 Servlet API 对象
请求发送页面
<h3><a href="demo1/ServletAPITest">Test Servlet API</a></h3>
控制器
@RequestMapping(value="/ServletAPITest")
public String servletAPITest(HttpServletRequest request,HttpServletResponse response ) {
System.out.println("Request: " + request);
System.out.println("Response: " + response);
return SUCESS;
}
设置响应
1. 传递参数
1.1 将参数传递至请求域
a. 使用 ModelAndView 传递参数
请求页面
<h3><a href="demo1/ModelAndViewTest">Test Model And View</a></h3>
返回页面
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<p>The user info:<i>${requestScope.user}</i></p>
</body>
</html>
控制器
@RequestMapping(value="/ModelAndViewTest")
public ModelAndView testModelAndView() {
String viewName = "MVTest";
ModelAndView mv = new ModelAndView(viewName);
mv.addObject("user",new UserInfo(1,"zhang","123",14));
return mv;
}
b. 使用 Map 设置传递参数
请求页面
<h3><a href="demo1/MapTest">Test Map</a></h3>
控制器
@RequestMapping("/MapTest")
public String mapTest(Map<String,Object> map) {
map.put("user", new UserInfo(1,"zhang","123",14));
return "MVTest";
}
c. 将后台模型传递至请求域
页面
<h1>ModelAttribute Test</h1>
<hr>
<form action="demo1/testModelAttribute" method="post">
<input type="hidden" name="id" value="1">
username: <input type="text" name="name" value="TOM"/><br>
age: <input type="number" name="age" value="12"/><br>
<input type="submit" value="submit"/>
</form>
Controller 类
ModelAttribute 注解标注的函数都会在 @Request 注解标注的函数之前执行。用它可以获取后台数据,并且可以将数据放在请求域。
ModelAttribute 注解标注的函数中,有一个 map 映射的参数,用于存放模型的键值对,同时这些键值对也会存放到请求域。
在对某一项值进行更新时可以使用 ModelAttribute, 让 ModelAttribute 从后台获取需要更新的数据,和前台获取的数据进行合并。
前台数据提交时,先会在请求域中查找是否存在与 POJO 对象类名的第一个首字母小写的键,若存在则可以直接获取后台数据,如果不一致,则需要在传入的 POJO 对象前使用 ModelAttribute 标注出需要获取的对象的键名。
@ModelAttribute
public void useModelAttribute(@RequestParam(value="id",required=false) Integer id,Map<String,Object> map) {
if(id != null) {
// 模拟从数据库中获取数据
UserInfo user = new UserInfo(1,"xiaoming","123456",22);
System.out.println("Get the UserInfo from DataBase: " + user);
// 放置的模型与传入参数的 POJO 的类名的第一个首字母小写的字符串保持一致
map.put("userInfo",user);
}
}
@RequestMapping(value="/testModelAttribute")
public String testModelAttribute(UserInfo user) {
System.out.println("Get the UserInfo from Page: " + user);
return SUCESS;
}
1.2 将参数传递至Session域
在控制类上加上注解
在被 @Controller 注解标注的控制类上,可以将传递给请求域的参数同时也传递给 Session 域
@SessionAttributes(value= {"user"},types= {UserInfo.class})
返回页面
<p>The user info:<i>${requestScope.user}</i></p>
<p>The user in the Session Scope <i>${sessionScope.user}</i></p>