Spring 2.5 引入了一种基于注解的编程模式,注解支持 Servlet MVC 和 Portlet MVC。控制器可以不必继承特定的基类或实现特定的接口。
1. @Controller
在 Spring MVC 中,控制器 Controller 负责处理由 DispatcherServlet 分发的请求,它把用户请求的数据经过业务处理层处理之后封装成一个 Model,然后再把该 Model 返回给对应的 View 进行展示。
不使用注解的方式,需要在 Spring MVC 配置文件 springmvc-config.xml 中添加 Controller 类的 Bean 对象,如:
<bean class="gler.springmvc.controller.UserController"/>
使用 @Controller 注解的类不再需要继承特定的基类或实现特定的接口,并且可以同时处理多个请求动作。
配置文件写法:
- 首先在头文件引入 spring-context。
- 启动包扫描功能,添加类似如下的代码:
<context:component-scan base-package="gler.springmvc.controller" />
base-package 是指定要扫描的包及其子包。
先看一段 Controller 类的代码:
/**
* UserController 是一个基于注解的控制器
* 可以同时处理多个请求动作
*/
@Controller
public class UserController {
/**
* RequestMapping 用来映射一个请求和请求的方法
* value="/register" 表示请求由 register 方法进行处理
*/
@RequestMapping(value="/register")
public String Register(@ModelAttribute("form") User user, Model model) {
model.addAttribute("user", user);
return "success";
}
}
可以看到,为 UserController 添加了 @Controller,说明它是一个基于注解的控制器。
Spring 会使用扫描机制查找所有基于注解的控制器类。
2. @RequestMapping
@RequestMapping 注解用来处理请求地址映射,指示 Spring 用哪个类或方法来处理请求动作。 @RequestMapping 可用于类或方法上。
当 @RequestMapping 用于类上时,表示类中的所有响应方法都被映射到 value 属性所指示的路径下,如:
@Controller
@RequestMapping(value="/user")
public class UserController {
@RequestMapping(value="/register")
public String Register() {
return "register";
}
}
在这里,相关路径均要加上 /user
,Register() 映射的 URL 为:
http://localhost:8080/SpringMVCTest/user/register
若未用 @RequestMapping(value="/user")
注解类,该方法映射的 URL 为:
http://localhost:8080/SpringMVCTest/register
同样是上面的示例代码, @RequestMapping(value="/register")
映射一个请求和请求的方法,请求由 Register
方法进行处理。
2.1 @RequestMapping 常用属性
@RequestMapping 常用属性如下:
(1)value
指定请求的实际地址,即 value 属性将 URL 映射到方法上。
如下面的代码:
@Controller
public class UserController {
@RequestMapping(value="/register")
public String Register() {
return "register";
}
}
对应的 URL:
http://localhost:8080/SpringMVCTest/register
如果 @RequestMapping 只有唯一的属性,value 属性名可省略。
@RequestMapping(value="/register")
@RequestMapping("/register")
(2)method
指定请求的 method 类型,即该方法可以处理的 HTTP 请求方式,如 GET、POST 等。
@RequestMapping("/register",method=RequestMethod.POST)
注:如果未指定 method,则可以处理任意类型的 HTTP 请求。
(3)consumes
指定处理请求的提交内容类型(Content-Type),例如 application/json, text/html。
@RequestMapping("/register",method=RequestMethod.POST,consumes="application/json")
这里只处理 request Content-Type 为 application/json 的请求。
(4)produces
指定返回的内容类型,仅当 request 请求头中的(Accept)类型中包含该指定类型才返回。
@RequestMapping("/register",method=RequestMethod.POST,produces="application/json")
(5)params
指定 request 中必须包含某些参数值是,才让该方法处理。
@RequestMapping("/register",method=RequestMethod.POST,params="myParam=myValue")
这里只处理名为 “myParam”,值为 “myValue” 的请求。
(6)headers
指定 request 中必须包含某些指定的 header 值,才能让该方法处理请求。
@RequestMapping("/register",method=RequestMethod.POST,headers="Referer=http://www.gler.com")
这里只处理 request 的 header 中包含了指定 “Referer” 请求头和对应值为 “http://www.gler.com” 的请求。
2.2 请求处理方法的参数类型
先来看一个例子:
@RequestMapping(value="/register")
public String Register(@ModelAttribute("form") User user,Model model) {
model.addAttribute("user", user);
return "success";
}
在这里 Register 方法接受一个 Model 类型的参数。其实每个请求处理方法可以有多个不同类型的参数。
支持的方法参数类型:
- org.springframework.web.context.request.WebRequest 或 org.springframework.web.context.request.NativeWebRequest
- java.util.Locale
- java.util.TimeZone (Java 6+) / java.time.ZoneId (on Java 8)
- java.io.InputStream / java.io.Reader
- java.io.OutputStream / java.io.Writer
- org.springframework.http.HttpMethod
- java.security.Principal
- @PathVariable
- @MatrixVariable
- @RequestParam、@RequestHeader、@RequestBody、@RequestPart
- HttpEntity
2.3 请求处理方法可返回类型
支持的方法返回类型:
- ModelAndView
- Model
- Map
- View
- String
- void
- 如果该方法用 @ResponseBody 注解,则返回类型将写入响应 HTTP 主体
- HttpEntity
2.4 Model
Spring MVC 内部使用 Model 接口存储模型数据,功能类似于 Java 中的 Map,而 ModelMap 接口是实现了 Model 接口。因此, Model 和 ModelMap 的用法相近,如:
@RequestMapping(value="/register")
public String Register(@ModelAttribute("form") User user,Model model) { // jsp 页面传入的 form 表单
// 将 User 对象添加到 Model 中
model.addAttribute("user", user);
return "success";
}
在这里,可以将参数中的 Model model
改为 ModelMap modelMap
。
2.5 ModelAndView
ModelAndView 既包含模型数据信息又包含视图信息,它可用作 Controller 处理方法的返回值。Spring MVC 将包含的视图对模型数据进行渲染,模型数据可以看做 Java 中的 Map。
ModelAndView 的用法示例:
@RequestMapping(value="/register")
public ModelAndView Register(@ModelAttribute("form") User user,ModelAndView mv) {
// 将 User 对象添加到 ModelAndView 的 Model 中
mv.addObject("user", user);
// 设置返回视图的名称
mv.setViewName("/WEB-INF/views/success.jsp");
return mv;
}
3 参数绑定
3.1 @RequestParam
@RequestParam 主要用于在 Spring MVC 后台控制层获取参数,类似一种是 request.getParameter(“name”)。
支持的属性:
- name:指定请求头绑定的名称
- value:name 的别名
- required:通过 boolean 指定参数是否必须绑定
- defaultValue:设置默认值
例如一个登陆请求的处理方法。
@RequestMapping(value="/login")
public ModelAndView login(
@RequestParam("username") String username, @RequestParam("password") String password) {
return ...
}
请求如下:
http://localhost:8080/SpringMVCTest/login?username=tom&password=123456
上述代码会把 username 参数的值 “tom” 赋给 username 变量,把 password 参数的值 “123456” 赋给 password 变量。
3.2 @ResponseBody
@ResponseBody 用于将 Controller 方法返回的对象,通过适当的 HttpMessageConverter 转换为指定格式后,写入到 Response 对象的 body 数据区,如:
@RequestMapping(value="/something", method=RequestMethod.PUT)
public void doSomething(@RequestBody String body, Writer writer) throws IOException {
writer.write(body);
}
3.3 @PathVariable
@PathVariable 用来将请求 URL 中的模板变量映射到功能处理方法的参数上,如:
@RequestMapping(value="/something/{userId}")
public void doSomething(@PathVariable Integer userId){}
在这里假设请求的 URL 为 “http://localhost:8080/SpringMVCTest/something/1“,则将 {userId}
为1绑定到 @PathVariable 注解的同名参数上。
3.4 @RequestHeader
@RequestHeader 可以把请求的 header 部分的值映射到方法的参数上。
例如:
如下是一个请求的 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
@RequestHeader 示例代码:
@RequestMapping(value="/headerTest")
public void headerTest(
@RequestHeader("Accept-Encoding") String encoding, @RequestHeader("Keep-Alive") long keepAlive){
}
上述代码把请求 header 部分的 Accept-Encoding 的值绑定到参数 encoding 上, 把 Keep-Alive 的值绑定到参数 keepAlive 上。
3.5 @CookieValue
@CookieValue 可以把请求的 Cookie 数据映射到方法的参数上。它的属性与 @RequestParam 一样,示例如下:
@RequestMapping(value="/cookieTest")
public void cookieTest(
@CookieValue("JESSSIONID") String cookie){
}
上述代码把请求的 JSESSIONID 值绑定到参数 cookie 上。
3.6 @SessionAttributes
@SessionAttributes 允许有选择地指定 Model 中的哪些属性需要转存到 HttpSession 对象中。@SessionAttributes 只能用于类上,不能用于方法上。
可指定的属性:
- names:Model 中属性的名称
- value:names 的别名
- types:指定放入 HttpSession 当中的对象类型
以上一节的注册为例:
@Controller
@SessionAttributes(value="user",types={User.class})
public class SessionAttributesTest {
@RequestMapping(value="/register")
public String register(@ModelAttribute("form") User user, Model model) {
model.addAttribute("user", user);
return "success";
}
}
我们在 success.jsp 中的 body 添加代码 访问 HttpSession 中的 user 对象:${sessionScope.user.username} <br>
,然后访问 URL http://loaclhost:8080/SpringMVCTest
,填写信息后点击注册,能够访问到我们转存到 HttpSeesion 中的 user 对象。
3.7 @ModelAttribute
@ModelAttribute 将请求参数绑定到 Model 对象。@ModelAttribute 主要有两种使用方式,一种是注解在方法上,一种是注解在 Controller 方法参数上。
注:当 @ModelAttribute 注解在方法上时,该方法会在 Controller 每个方法执行前被执行。
举个登录的例子:
@Controller
public class ModelAttributeController {
@ModelAttribute("user")
public User userModel(
@RequestParam("username") String username, @RequestParam("password") String password){
User user = new User();
user.setUsername(username);
user.setPassword(password);
return user;
}
@RequestMapping(value="/login")
public String login(@ModelAttribute("user") User user{
return "success";
}
}
在 userModel
方法上有注解 @ModelAttribute("user")
,表示 userModel 方法会先于 login 方法调用。这里 model 属性名称是 value 只,由于只有一个属性所以省略了名称,即 “user”,model 属性对象是方法的返回值。
在 login
方法的参数 User user
使用了 @ModelAttribute("user")
,表示参数 user 的值是 userModel
方法中的 model 属性。
参考链接
- springmvc常用注解标签详解
- 《Spring+MyBatis 企业应用实战》