SpringMVC 官方文档的部分翻译
本文有选择地翻译了 Spring framework 官方文档第21章 SpringMVC.
参见21. Web MVC framework
0. 引论
待续...
1. 通过 @Controller 注解一个控制器
@Controller: 注解一个类,表明其作为控制器.Spring 并不会强制要求继承其他类或者引用Servlet API.当然有必要的话,你依然可以使用 Servlet API.
有时控制器需要被 AOP 代理修饰,例如 @Transactional.此时,建议用基于类(class-based)的代理,默认设置就是如此,但如果控制器实现一个不是由 Spring Context 回调的接口,你就要明确指定类级别的代理:
<tx:annotation-driven proxy-target-class="true"/>
2. 通过 @RequestMapping 映射请求
@RequestMapping :注解方法或者类,表明其用来映射 URL.方法级别的映射还可以通过设定属性来缩小范围,指定更具体的 URL.@RequestMapping 可拥有的属性有:
- path String[]:指定 URL;
- method RequestMethod[]:指定 HTTP 方法,RequestMethod.GET 或 .POST 等;
- value String[] :在 Servlet 中等同于 path;
- header String[] :指定 HTTP 首部,例如,header="jsessionid=123";
- params String[] :指定 URL 参数,例如,param="id=1";
- name String :指定方法或类的名称;
- consumes String[]:指定消费级媒体类型(consumable media type),text/plain,application/*;
- produces String[]:指定生产级媒体类型(producible media type)
从 Spring 3.1 开始,默认的映射处理器变为 RequestMappingHandlerMapping.它把控制器的方法作为唯一的映射终点,这些方法会取得类级别和方法级别的 @RequestMapping 信息,而之前的过程是类和方法分开处理.
一个例子:
@Controller
public class MappingController {
// 访问 http://www.abc.com/mapping/path 会被映射到此处
@RequestMapping(value = "/mapping/path")
public @ResponseBody String byPath() {
return "Mapped by Path";
}
// http://www.abc.com/mapping/path/asd
@RequestMapping(value = "/mapping/path/*", method = RequestMethod.GET)
public @ResponseBody String byPathPattern(HttpServletRequest request) {
return "Mapped by pathpattern " + request.getRequestURI();
}
@RequestMapping(value = "/mapping/method", method = RequestMethod.GET)
public @ResponseBody String byMethod() {
return "Mapped by path and HTTPmethod";
}
// http://www.abc.com/mapping/parameter?foo=something
@RequestMapping(value = "/mapping/parameter", params = "foo")
public @ResponseBody String byParams() {
return "Mapped by Params";
}
@RequestMapping(value = "/mapping/parameter", params = "!foo")
public @ResponseBody String byNotParams() {
return "Mapped by path and method ,not presence of query parameters";
}
@RequestMapping(value = "/mapping/header", method=RequestMethod.GET,headers="FooHeader=foo")
public @ResponseBody String byHeaders(HttpServletRequest request) {
return "Mapped by header's presence "+request.getHeader("FooHeader");
}
@RequestMapping(value = "/mapping/header", method=RequestMethod.GET,headers="!FooHeader")
public @ResponseBody String byNotHeaders(HttpServletRequest request) {
return "Mapped by header's absence ";
}
}
3. URI Template Patterns
一个 URI Template 定义了如何将 URI 参数化,例如:
http://www.example.com/user/{userId}
可以通过注解 @PathVariable 来取得 URI 中参数的值,当 URI 参数和方法参数名称不一致时,需指定@PathVariable 的 value.如: @PathVariable("ownerId")
如下,当访问 www.abc.com/owners/zhang
时,方法参数 ownerId 会被赋值为 'zhang'.
@RequestMapping(path="/owners/{ownerId}",method=RequestMethod.GET)
public String find(@PathVariable String ownerId,Model model){
Owner owner = ownerService.find(ownerId);
model.addAttribute("owner",owner);
return "success";
}
还支持正则表达式,待续..
4. 定义 @RequestMapping 注解的方法
@RequestMapping 注解的方法支持的方法参数类型和返回值类型非常多.
支持的方法参数类型:
Request
和Response
(Servlet API)
Session
(Servlet API).注: Session 并不是线程安全的/当多个请求可以同步访问 session 时,考虑设置 RequestMappingHandlerAdapter 的 synchronizeOnSession = true;
org.springframework.web.context.request.WebRequest
ororg.springframework.web.context.reqeust.NativeWebRequest
. 允许泛型化 Request 的参数访问以及 reqeust/session 属性访问,不必再捆绑到原生 Servlet.
java.util.Locale
for the current request locale,在 MVC 中由 LocaleResolver/LocaleContextResolver 配置.
java.util.TimeZone(java6+)/java.time.ZoneId(java8)
java.io.OutputStream/java.io.writer
用来生成响应内容.This value is the raw OutputStream/Writer as exposed by the Servlet API.
org.springframework.http.HttpMethod
用于 HTTP 请求方法.
java.security.Principal
@PathVariable
@MatrixVariable
@RequestParam
可以获得 url 中的参数,例如:/find?id=123
中的 id
@RequestHeader
@RequestBody
@ReqeustPart
HttpEntity<?>
可以通过它访问 request 和 reponse 的 body/header 等.
java.util.Map
ororg.springframework.ui.Model
ororg.springframework.ui.ModelMap
保存属性,传递给视图层.
org.springframework.web.servlet.mvc.suppot.RedirectAttributes
用于保存重定向时需要的属性.
- Command 或 表单对象. ...
org.springframework.validation.Errors / org.springframework.validation.BindingResult
代表了先前 command 或表单对象的验证结果.
org.springframework.web.bind.support.SessionStatus
用于标记表单处理完成的标识.它会触发 session 属性的清理.
org.springframework.web.util.UriComponentsBuilder
注:当方法参数有多个时, BingdingResult/Error 参数必须紧跟在模型对象之后.
注2:java.util.Optional
可作为方法参数,用于那些拥有 required 属性的注解(@RequestParam,@RequestHeader,etc).
支持的方法返回类型
返回 Sring 能满足大部分需求.
待续..
5. 使用 @ModelAttribute 注解方法
使用 @ModelAttribute 注解方法表明此方法要向 model 中添加属性.此方法会在 @RequestMapping 方法之前执行.一个例子:
@ModelAttribute
public Account add(@RequestParam String number){
return accountService.find(number);
}
@ModelAttribute
public void populateModel(@RequestParam String number,Model model){
model.addAttribute(accountService.find(number));
model.addAttribute("something","something");
//add more...
}
@ModelAttribute 还可以用在 @ControllerAdivce-annotated class.
@ModelAttribute 还可以用在 @RequestMapping 方法上,此时,返回值会被放进 model,视图名称通过约定(convention),就好像返回值是 void 的方法一样.
6. 在方法参数中使用 @ModelAttribute
被 @ModelAttribute 注解的方法参数表明参数应该从模型中取出.如果模型中不存在此对象,则首先实例化,然后添加到模型中,并且对象的实例域如果与请求参数匹配,则自动被赋值.这就是 SpringMVC 中的数据绑定.一个例子:
当访问 www.abc.com/test?name=piqiu
时,pro 会被添加到 model 中,且 name 属性会被自动赋值,可以在随后使用.
public class Product{
private String name;
//省略 get/set...
}
.....
@RequestMapping(value="/test")
public String test(@ModelAttribute Product pro){
productService.update(pro);
//操作 pro..
return "success";
}
7. 通过 @InitBinder 定制数据绑定
待续..