@RequestMapping处理器方法可以非常灵活的签名。支持的方法参数和返回值在以下部分中描述。大多数参数可用于任意顺序除了BindingResult这个唯一的参数例外。下一节中将会描述。
note:Spring 3.1引入了一套新的@RequestMapping方法的支持类.分别是RequestMappingHandlerMapping和RequestMappingHandlerAdapter。它们被推荐使用,甚至你在使用Spring MVC的新特性时必须使用它们。在MVC命名空间与MVC的Java配置这些新的支持类是默认启用的。如果不使用新特性必须明确的配置。
1、支持的方法参数类型
下面是是支持的方法参数:
1. Servlet API中的Request或者Response对象。选择一些特殊的request或者response类型。例如:ServletRequest
或者HttpServletRequest
。
2. Servlet API中的Session对象:HttpSession
对象。论证这种类型的执行存在相应的会话。因此,这个参数永远不会为Null
。
note : 在Servlet环境中使用session对象可能不会线程安全。如果多个request被允许使用同一个session可以考虑把RequestMappingHandlerAdapter的synchronizeOnSession属性设置为true。
3. org.springframework.web.context.request.WebRequest
或者org.springframework.web.context.request.NativeWebRequest
.如果没有依赖本地Servlet / Portlet API,允许使用通用请求参数访问request/session属性。
4. java.util.Locale
.当前请求的locale。在Spring MVC中可以通过配置LocaleResolver
/LocaleContextResolver
,来决定使用可用的具体的语言环境解析器。
5. java.util.TimeZone
(Java 6+) / java.time.ZoneId
(on Java 8): 与当前请求相关联的时区,通过LocaleContextResolver
来决定。
6. java.io.InputStream
/ java.io.Reader
.访问request的内容.这个值是Servlet API暴露的原始的InputStream /Reader.
7. java.io.OutputStream
/ java.io.Writer
.生成reponse的内容.这个值是Servlet API暴露的原始的OutputStream/Writer.
8. org.springframework.http.HttpMethod.HTTP
请求的方法。
9. java.security.Principal
.包含当前身份验证的用户。
10. @PathVariable
.被注释的参数用于获取URI模板变量。
11. @MatrixVariable
.注解的参数访问位于URI路径段名称-值对。
12. @RequestParam
.注解的参数访问特定的Servlet请求参数。参数值转换为声明的方法参数类型。
13. @RequestHeader
.注解的参数访问Servlet的HTTP请求中特殊的headers。参数值转换为声明的方法参数类型。
14. @RequestBody
.注解的参数访问HTTP请求的body.参数值使用HttpMessageConverters转换为声明的方法参数类型。
15. @RequestPart
.注解的参数获取的content中的”multipart/form-data”要求的部分。主要用于Spring MVC支持文件上传。
16. HttpEntity
. 用于访问Servlet中的HTTP请求headers与content中的属性.request流将使用HttpMessageConverters被转换成entity的body.
17. java.util.Map
/ org.springframework.ui.Model
/ org.springframework.ui.ModelMap
.装饰web视图暴露的的隐式模型.
18. org.springframework.web.servlet.mvc.support.RedirectAttributes
.指定的精确的属性用于如果发生重定向并添加flash属性。(把属性临时的储存在服务端,当进行重定向的时候,可以从request里面获取它)
19. Command或者form对象来绑定请求参数到bean(通过setters)或者通过字段。通过@InitBinder
注解方法或者HandlerAdapter配置,我们也可以自定义类型转换。可以参考RequestMappingHandlerAdapter
的webBindingInitializer
这个属性。这样的命令对象及其验证结果将会默认以model的属性暴露.使用command类的类名 – 例如.一个command对象的的类型为”some.package.OrderAddress”对应的model属性就是”orderAddress”.@ModelAttribute
注释可用于自定义一个方法参数模型属性名称使用。
20. org.springframework.validation.Errors
/ org.springframework.validation.BindingResult
.前命令之前或表单对象验证结果.(方法参数的前面)
21. org.springframework.web.bind.support.SessionStatus
.状态处理用于将表单处理标记为完成.如果在处理类(Controller)上面声明@SessionAttributes
这个注解,就会引用清除session属性。
22. org.springframework.web.util.UriComponentsBuilder
.一个builder用于准备一个URL相对于当前请求的host,port,scheme,context path和servlet映射的文字部分。
注意:
Errors
或者BindingResult
必须作为Model对象的参数。Model对象是与方法绑定在一起的。Spring MVC会给写个Model创建一个单独的BindingResult
的对象。下面这个例子是错误的,不会运行:
BindingResult与@ModelAttribute的顺序不正确.
@RequestMapping(method = RequestMethod.POST)
public String processSubmit(@ModelAttribute("pet") Pet pet, Model model, BindingResult result) { ... }
注意
如果在Pet
与BindingResult
中有Model
对象。如果你想这段逻辑工作,需要把这些参数像下面进行重新排序。
@RequestMapping(method = RequestMethod.POST)
public String processSubmit(@ModelAttribute("pet") Pet pet, BindingResult result, Model model) { ... }
2、方法支持的返回值类型
下面的是方法支持的返回值类型:
1. A ModelAndView
object,这个model隐含command对象和@ModelAttribute
注释的结果.
2. A Model
object,返回一个Model对象来表示模型,而视图名则利用RequestToViewNameTranslator
把请求转换为视图名称。这个model隐含command对象和@ModelAttribute
注释的结果.
3. A Map
object,返回一个Map对象来表示模型,而视图名则利用RequestToViewNameTranslator
把请求转换为视图名称。这个model隐含command对象和@ModelAttribute
注释的结果.
4. A View
object,这个model隐含command对象和@ModelAttribute
注释的结果.处理方法通过声明的Model
类型的参数来编程填充这个模型。
5. A String
value,这个String值被Spring MVC解读为合理的页面name.这个model隐含command对象和@ModelAttribute
注释的结果.处理方法通过声明的Model
类型的参数来编程填充这个模型。
6. void
,返回空void表示方法自己处理响应,一种办法是:通过声明一个ServletResponse
或HttpServletResponse
类型的参数来直接输出响应内容,第二种是:通过RequestToViewNameTranslator
把请求转化为视图名,此方法不用在处理方法中声明一个response参数,不过这种方法是能在Servlet环境下使用。
7. 如果方法使用@ResponseBody
,返回值将会被写入到response的HTTP的body中。将通过HttpMessageConverters把返回值转换为声明方法参数类型.
8. An HttpEntity<?>
or ResponseEntity<?>
object,用来提供使用Servlet中HTTP中response中的headers和contents.通过HttpMessageConverters把entity的body转换成response流.
9. An HttpHeaders
object,返回reponse没有body.
10. A Callable<?>
object,当Spring MVC管理的一个应用想要通过异常的形式返回参数。
11. A DeferredResult<?>
,当应用想要通过它选择的线程来产生返回值,可以使用这个参数。
12. A ListenableFuture<?>
,当应用想要通过它选择的线程来产生返回值,可以使用这个参数。
13. A ResponseBodyEmitter
,使用异步的方法写多个对象到response中可以返回这个类型;同样也支持作为ResponseEntity
的body.
14. An SseEmitter
,可以返回用于写异步服务器发送的事件给response;同样也支持作为ResponseEntity
的body.
15. A StreamingResponseBody
,可以返回用于异步的写入response的OutputStream;同样也支持作为ResponseEntity
的body.
16. Any other return type,被认为是做为是暴露的view中的model属性。可以在方法级别使用@ModelAttribute
用来指定属性名称.(默认的属性名称是返回类型的class name).这个model隐含command对象和@ModelAttribute
注释的结果.
3、@RequestParam – Binding request parameters to method parameters
在Controller中可以使用@RequestParam
绑定请求参数到方法的参数。
下面的代码片段展现它的用法:
@Controller
@RequestMapping("/pets")
@SessionAttributes("pet")
public class EditPetForm {
// ...
@RequestMapping(method = RequestMethod.GET)
public String setupForm(@RequestParam("petId") int petId, ModelMap model) {
Pet pet = this.clinic.loadPet(petId);
model.addAttribute("pet", pet);
return "petForm";
}
// ...
}
如果方法中参数使用了这个@RequestParam,那么request中必须有对应的参数.当然你也可以通过设置@RequestParam的required
属性是false
来指定这个参数不是强制request需要传递这个参数。(e.g., @RequestParam(path="id", required=false)
)如果方法中的参数不是String
类型,Spring MVC会进行自动转换。
当@RequestParam
注解使用到Map[String, String]
或者MultiValueMap[String, String]
类型时,这个map会用request中的所有参数来填充。
4、@RequestBody – Mapping the request body
方法参数中使用@RequestBody
表明,这个方法中的参数是使用HTTP请求中的request中的body中的值。(当你使用传json给后面的时候,可以使用这个注解把这个json转换成被注解的对象).例如:
@RequestMapping(path = "/something", method = RequestMethod.PUT)
public void handle(@RequestBody String body, Writer writer) throws IOException {
writer.write(body);
}
你使用一种HttpMessageConverter
把HTTP的request中的body转换成方法参数。HttpMessageConverter
的作用是把HTTP的request中的信息转换成一个对象和把一个对象转换成HTTP的response中的body.Spring MVC中的RequestMappingHandlerAdapter
默认支持@RequestBody
使用下面的HttpMessageConverters
:
1. ByteArrayHttpMessageConverter
converts byte arrays.
2. StringHttpMessageConverter
converts strings.
3. FormHttpMessageConverter
converts form data to/from a MultiValueMap[String, String>.
4. SourceHttpMessageConverter
converts to/from a javax.xml.transform.Source.
如果你想使用Spring MVC中更多的信息转换,可以使用Spring MVC中的namespace与Spring MVC的Java config来进行注册。如果你打算读/写XML,你需要配置MarshallingHttpMessageConverter
通过org.springframework.oxm
包下面的Marshaller
与Unmarshaller
的实现类。下面的就是使用Spring MVC的namespace的例子:
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<util:list id="beanList">
<ref bean="stringHttpMessageConverter"/>
<ref bean="marshallingHttpMessageConverter"/>
</util:list>
</property
</bean>
<bean id="stringHttpMessageConverter"
class="org.springframework.http.converter.StringHttpMessageConverter"/>
<bean id="marshallingHttpMessageConverter"
class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter">
<property name="marshaller" ref="castorMarshaller"/>
<property name="unmarshaller" ref="castorMarshaller"/>
</bean>
<bean id="castorMarshaller" class="org.springframework.oxm.castor.CastorMarshaller"/>
当你在方法参数上使用@RequsetBody
时还可以使用@Valid
来注解它。在这种情况下,它将会使用配置了的Validator
的实例来验证这个对象。当使用Spring MVC的namespace或者使用java config的时候,JSR-303 validator会自动检测classpath中的JSR-303的实现是可用的。
与注解了@ModelAttribute
的参数一样,Errors
可以用来检查errors.如果这样的argument没有声明,就会报MethodArgumentNotValidException
异常。这个异常会被DefaultHandlerExceptionResolver处理
,将会发送400
错误给客户端。
5、@ResponseBody – Mapping the response body
@ResponseBody
注解的用法与@RequestBody
相似,这个注解可以用在一个方法上,用来表明这个方法的返回值将会直接写到HTTP的response的body中。(不会被放在Model或者被认为是一个页面名称).例如:
@RequestMapping(path = "/something", method = RequestMethod.PUT)
@ResponseBody
public String helloWorld() {
return "Hello World";
}
上面的例子将会导致"Hello Word"
被写入HTTP的response流中。说得通俗一点就是返回一个Json格式给client.与@RequestBody
一样,Spring MVC能够使用HttpMessageConverter
把方法的返回对象转换成HTTP的response的body。
6、@RestController – Creating REST Controllers
这是一个非常常见的用例用于Controller实现一个REST API,因此只为JSON、XML或自定义MediaType。你现在不需要在你的所有注解了@RequestMapping
的方法上使用@ResponseBody
,你只需要在你的Controller类上面使用@RestController
代替使用Controller
。
@RestController
是@ResponseBody
与@Controller
结合体的模板注解.不仅如此,它还使得controller具有更多的意义。也可能在将来的框架版本中携带额外的语义。与常规的@Controllers一样,@RestController
也可以通过@ControllerAdvice
来协助.
7、Using HttpEntity
HttpEntity
与@RequestBody
和@ResponseBody
类似。除了有权使用request和response的body之外,HttpEntity
(与response特殊实现类ResponseEntity)同样允许有权使用request与response的headers,例如:
@RequestMapping("/something")
public ResponseEntity<String> handle(HttpEntity<byte[]> requestEntity) throws UnsupportedEncodingException {
String requestHeader = requestEntity.getHeaders().getFirst("MyRequestHeader"));
byte[] requestBody = requestEntity.getBody();
// do something with request header and body
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.set("MyResponseHeader", "MyValue");
return new ResponseEntity<String>("Hello World", responseHeaders, HttpStatus.CREATED);
}
在上面的例子中,获取request header中MyRequestHeader
的值,并且读取读取request的bosy作为一个byte array.它添加MyResponseHeader
到response中,把"Hello World"
写入到response流中,并且设置response的status code为201(Created).
与@RequestBody
和@ResponseBody
一样,Spring使用HttpMessageConverter
把输入数据转换到request与response的流当中.
8、@ModelAttribute on a method
注解@ModelAttribute
可以应用到方法上也可以应用在方法参数上。这个章节将介绍它在方法上的用法,下个章节将会介绍它在方法参数上的用法。
当@ModelAttribute
用在方法上时表明这个方法目的是添加一个或者多个model属性。这种方法支持相同的参数类型作为@RequestMapping
方法但不能直接映射到请求。反而在一个Controller中注解了@ModelAttribute
的方法会比同一个controller中@RequestMapping
方法早调用.下面有两个例子:
// Add one attribute
// The return value of the method is added to the model under the name "account"
// You can customize the name via @ModelAttribute("myAccount")
@ModelAttribute
public Account addAccount(@RequestParam String number) {
return accountManager.findAccount(number);
}
// Add multiple attributes
@ModelAttribute
public void populateModel(@RequestParam String number, Model model) {
model.addAttribute(accountManager.findAccount(number));
// add more ...
}
@ModelAttribute
方法用于填充Modle通常需要的属性,例如填充下拉状态或pet类型,检索一个像帐户的命令对象为了使用它来代表一个HTML表单上的数据.在下一节中进一步讨论后一种情况。
注意@ModelAttribute
方法的两种风格.首先,添加一个属性的方法隐式返回它.第二,该方法接受一个Model
并为这个Modle添加任意数量的属性。你可以根据你的需求任意的选择这两种风格。
在一个Controller中可以有许多个@ModelAttribute
方法。在同一个Controller中,这些方法总是比@RequestMapping
方法先被调用。
@ModelAttribute
方法同样也可定义在一个标注了@ControllerAdvice
的类上。这些方法可以应用于多个Controller上。你可以看"@ControllerAdvice -- Advising controllers"
章节获取更多信息.
@ModelAttribute
注解也能够使用到@RequestMapping
方法上.在这种情况下,@RequestMapping
方法的返回值被解释为一个Model的属性而不是视图名称。视图名称来源于视图名称转换相反就像方法返回void. – Section 21.13.3, “The View - RequestToViewNameTranslator”. // TODO
9、@ModelAttribute – on a method argument(bathPath,casInfo)
在上一个章节中@ModelAttribute
可以被应用到方法与方法参数上.这个章节将介绍它在方法参数上的用法.一个@ModelAttribute
方法参数表明参数可以从Model中重新取回。如果没有从Model中取出,这个内容将会第一时间初始化并且添加到Model中.一旦出现在模型中,参数的字段应该填充所有请求参数匹配的名称。在Spring MVC中这被称为数据绑定.一个非常用有的机制,节省你不必逐个解析每个表单字段。
@RequestMapping(path = "/owners/{ownerId}/pets/{petId}/edit", method = RequestMethod.POST)
public String processSubmit(@ModelAttribute Pet pet) { }
鉴于上面的例子可以Pet实例从何而来?有下面几种可能:
1. 由于@SessionAttributes
的使用,它可能已经在Model中. – 看下面的章节,叫做"@SessionAttributes -- store model attributes in the HTTP session between requests."
2. 在同一个Controller中由于使用了@ModelAttribute
方法,可能已经在Model中. – 在上面的章节中已经解释过了.
3. 它可能已经在URI模板变量或者type转换中获取到了.
4. 它可以已经使用它的默认constructor初始化好了。
一个@ModelAttribute
方法是一种通常的方法用来从database获取属性。通过使用@SessionAttributes
这可以被存储在这个请求之间.大多数情况下,它可以很方便的从URI模板变量或者type转换中获取这个属性.下面就是一个例子:
@RequestMapping(path = "/accounts/{account}", method = RequestMethod.PUT)
public String save(@ModelAttribute("account") Account account) {
}
在这个例子中,model属性的名称(“account”)与URI模板变量的名称相匹配.如果你注册Converter[String, Account]
,那么就可以把字符串类型类型account值转换成一个Account
实例,然后上面的例子将会在不需要@ModelAttribute
方法前提下运行.
下一步就是数据绑定,WebDataBinder
这个类匹配request参数名 – 包含query的String类型的参数以及form字段 – model属性字段名.匹配字段在必须的类型转换(String类型到目标fiedl类型)之后进行填充.Controller级别的自定义数据绑定将会在"Customizing WebDataBinder initialization."
章节中细说。
当进行数据绑定的时候可能会有一些错误,比如说:缺少必须的fields或者类型转换errors。你如果需要check这个errors,可以再@ModelAttribute
参数后面添加一个BindingResult
参数:
@RequestMapping(path = "/owners/{ownerId}/pets/{petId}/edit", method = RequestMethod.POST)
public String processSubmit(@ModelAttribute("pet") Pet pet, BindingResult result) {
if (result.hasErrors()) {
return "petForm";
}
// ...
}
在上面的例子中,你可以使用BindingResult
来check在渲染同个一表单的时候是否出错了.而且你可以使用Spring的<errors>
form标签来展现错误.除了数据绑定你也可以通过BindingResult
来使用自己的自定义验证器.这个对象被用来记录数据绑定发生的错误.它允许数据绑定与验证数据的错误被放置在同一个地方,然后报告给用户.
@RequestMapping(path = "/owners/{ownerId}/pets/{petId}/edit", method = RequestMethod.POST)
public String processSubmit(@ModelAttribute("pet") Pet pet, BindingResult result) {
new PetValidator().validate(pet, result);
if (result.hasErrors()) {
return "petForm";
}
// ...
}
或者你可以自动调用验证通过添加JSR-303中的@Valid
注解:
@RequestMapping(path = "/owners/{ownerId}/pets/{petId}/edit", method = RequestMethod.POST)
public String processSubmit(@Valid @ModelAttribute("pet") Pet pet, BindingResult result) {
if (result.hasErrors()) {
return "petForm";
}
// ...
}
10、@SessionAttributes – store model attributes in the HTTP session between requests
类级别的注解@SessionAttributes
声明session属性被一个特殊的handler使用.代表的用法是遍历model属性的name,或者model属性的类型.它们将会被储存在session中或者进行会话储存.主要用于后续请求的form表单需要的bean.
下面的代码片段展示了这个注解的用法,并且指明了model属性的名称:
@Controller
@RequestMapping("/editPet.do")
@SessionAttributes("pet")
public class EditPetForm {
// ...
}
11、Working with “application/x-www-form-urlencoded” data
前一节介绍了从浏览器客户端使用@ModelAttribute
支持表单提交请求.这个注释同样也推荐用来处理自非浏览器客户端的请求。然而当使用HTTP的PUT请求时,会有一个显著的不同.浏览器可以通过HTTP的GET或者POST来提交表单数据.非浏览器客户端还能够通过HTTP的PUT请求来提交表单数据.这提出了一个挑战,因为在Servlet规范要求ServletRequest.getParameter*()
的一系列方法只支持HTTP的POST请求来储存表单字段,而不是HTTP的PUT请求.
为了支持HTTP的PUT请求或者PATCH请求,spring-web
模块提供了filter – HttpPutFormContentFilter
.你可以在web.xml
中做以下配置:
<filter>
<filter-name>httpPutFormFilter</filter-name>
<filter-class>org.springframework.web.filter.HttpPutFormContentFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>httpPutFormFilter</filter-name>
<servlet-name>dispatcherServlet</servlet-name>
</filter-mapping>
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
上面的filter会拦截HTTP中的PUT与PATCH请求通过在content的类型为"application/x-www-form-urlencoded"
,读取表单request的body中的表单数据.并且包装ServletRequest
类,为了表单数据可以通过ServletRequest.getParameter*()系列方法来获取.
注意:因为HttpPutFormContentFilter
需要消费request的body,它不应该为"application/x-www-form-urlencoded"
被配置PUT或PATCH依赖其他转换器的url.其中包括@RequestBody ````MultiValueMap[String, String>
和HttpEntity[MultiValueMap[String, String>>
.
12、@CookieValue – Mapping cookie values
@CookieValue
注解被来用方法参数绑定HTTP中的cookie值.让我们来看一下下面这个被request接收的cookie.
JSESSIONID=415A4AC178C59DACE0B2C9CA727CDD84
下面的例子是如何获取JSESSIONID
这个cookie值:
@RequestMapping("/displayHeaderInfo.do")
public void displayHeaderInfo(@CookieValue("JSESSIONID") String cookie) {
//...
}
如果方法参数不是String类型,Spring会自动进行类型转换.具体可以看”Method Parameters And Type Conversion”.这个标签支持Servlet与Portlet环境下的handler方法.
13、@RequestHeader – Mapping request header attributes
@RequestHeader
注解允许方法参数绑定request中的header.
下面是一个简单的request的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
下面的代码就是简单的展示如何获取headers中Accept-Encoding
与Keep-Alive
的值:
@RequestMapping("/displayHeaderInfo.do")
public void displayHeaderInfo(@RequestHeader("Accept-Encoding") String encoding,
@RequestHeader("Keep-Alive") long keepAlive) {
//...
}
如果方法参数不是String
类型,Spring会自动进行类型转换.具体可以看"Method Parameters And Type Conversion"
.当@RequestHeader
注解的方法参数是Map[String, String>
, MultiValueMap[String, String>
,或者HttpHeaders
时,这个map会被request中header的所有值自己填充.
注意:Spring MVC内嵌的支持以逗号分隔的String转换成String类型的array/collection或者其它转换系统能够识别的类型.这个标签支持Servlet与Portlet环境下的handler方法.
14、Method Parameters And Type Conversion
从request中取出的String类型的值request参数,path变量,request headers和cookie值可以被用来转换成方法参数或者field(e.g.,使用在@ModelAttribute
绑定一个request参数到一个field)的目标类型。如果目标类型不是String
,Spring会自动转换成相应的类型.所有简单的数据类型,比如说int,long,Date等等都是支持的.你甚至可以使用WebDataBinder
来自定义转换处理.(看下面的章节,称为"Customizing WebDataBinder initialization"
)或者通过FormattingConversionService
注册Formatters
。
15、Customizing WebDataBinder initialization
可以通过Spring的WebDataBinder
来自己请求参数绑定的自定义属性操作.你可以使用@InitBinder
注解在你的Controller中的方法中,在@ControllerAdvice
注解的类上使用@InitBinder
方法,或者提供自定义的WebBindingInitializer
。更多细节可以看看下面的章节,"@ControllerAdvice -- Advising controllers"
.
init-binder方法支持所有的@RequestMapper
支持的参数,除了command/form对象和相应的验证结果对象.init-binder方法必须有返回值.但是它们通常被声明为void
。典型的参数包括WebDataBinder
与WebRequest
或者java.util.Locale
的结合,允许代码注册特殊的上下文来编辑.
下面就是一个简单的例子用来表示@InitBinder
为所有的java.util.Date
类型的表单对象配置一个CustomDateEditor
:
@Controller
public class MyFormController {
@InitBinder
public void initBinder(WebDataBinder binder) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
dateFormat.setLenient(false);
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false));
}
// ...
}
在Spring4.2中,一般考虑使用addCustomFormatter
来指定Formatter
的实现来代替PropertyEditor
的实例.这个特别的重要如果你碰巧有一个基本的Formatter
需要设置在一个共享FormattingConversionService
,用同样的方法来重用特殊的controller调整的绑定规则。
@Controller
public class MyFormController {
@InitBinder
public void initBinder(WebDataBinder binder) {
binder.addCustomFormatter(new DateFormatter("yyyy-MM-dd"));
}
// ...
}
16、Configuring a custom WebBindingInitializer
在进行数据绑定的时候,你可以提供一个自定义的WebBindingInitializer
实例的实例.你可以通过配置WebBindingInitializer
来实现.但是这样会覆盖默认的配置.
下面的例子是来自于PetClinic应用,展示了使用自定义的WebBindingInitializer
实现的实例.org.springframework.samples.petclinic.web.ClinicBindingInitializer
,通过几个PetClinic的Controller配置必须的属性编辑器。
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="cacheSeconds" value="0"/>
<property name="webBindingInitializer">
<bean class="org.springframework.samples.petclinic.web.ClinicBindingInitializer"/>
</property>
</bean>
@InitBinder
方法同样能够定义在注解了@Controller
的类上面,它就会适用于匹配的controllers。Spring提供使用WebBindingInitializer
.具体细节可以看下一个章节,叫做"@ControllerAdvice -- Advising controllers"
.
17、@ControllerAdvice – Advising controllers
@ControllerAdvice
注解是一个component的注解,它允许应用类被classpath自动扫描到.它也能够使用MVC namespace或者MVC Java config。
一个类如果被@ControllerAdvice
注解,那么它可以包含@ExceptionHandler
, @InitBinder
和@ModelAttribute
注解的方法。并且这些方法将应用到所有的Controller级别的@RequestMapping
方法中。而不是在他们宣布控制器层次结构。
@ControllerAdvice
注解同样可以用它的属性来指定一个controlers的一个子集.
// Target all Controllers annotated with @RestController
@ControllerAdvice(annotations = RestController.class)
public class AnnotationAdvice {}
// Target all Controllers within specific packages
@ControllerAdvice("org.example.controllers")
public class BasePackageAdvice {}
// Target all Controllers assignable to specific classes
@ControllerAdvice(assignableTypes = {ControllerInterface.class, AbstractController.class})
public class AssignableTypesAdvice {}
Check out the @ControllerAdvice documentation for more details.
18、Jackson Serialization View Support
有时候需要过滤的将序列化的对象上下文到HTTP中的resonse的body。实了提供这个功能,Spring MVC已经内置了 Jackson’s Serialization Views翻译。
在controller的方法中使用@RequestBody
或者controller的方法返回ResponseEntity
,添加@JsonView
注解到class上表明表明这个view类或者interface已经使用了.
@RestController
public class UserController {
@RequestMapping(path = "/user", method = RequestMethod.GET)
@JsonView(User.WithoutPasswordView.class)
public User getUser() {
return new User("eric", "7!jd#h23");
}
}
public class User {
public interface WithoutPasswordView {};
public interface WithPasswordView extends WithoutPasswordView {};
private String username;
private String password;
public User() {
}
public User(String username, String password) {
this.username = username;
this.password = password;
}
@JsonView(WithoutPasswordView.class)
public String getUsername() {
return this.username;
}
@JsonView(WithPasswordView.class)
public String getPassword() {
return this.password;
}
}
注意:@JsonView
允许多个类被指定,但是使用到controller方法上只能支持一个class。考虑使用一个复合interface,如果需要支持多个视图。
Controller依赖视图解析,只需序列化视图类添加然后添加到模型:
@Controller
public class UserController extends AbstractController {
@RequestMapping(path = "/user", method = RequestMethod.GET)
public String getUser(Model model) {
model.addAttribute("user", new User("eric", "7!jd#h23"));
model.addAttribute(JsonView.class.getName(), User.WithoutPasswordView.class);
return "userView";
}
}
19、Jackson JSONP Support
为了使@ResponseBody
和ResponseEntity
方法支持JSONP,声明@ControllerAdvice
bean继承AbstractJsonpResponseBodyAdvice
.如下所示的构造函数参数表明JSONP查询参数名称(s):
@ControllerAdvice
public class JsonpAdvice extends AbstractJsonpResponseBodyAdvice {
public JsonpAdvice() {
super("callback");
}
}
controllers依赖view解析,当request的请求参数中有一个叫做"jsonp"
或者"callback"
的时候JSONP
会自动激活。这些名称可以通过jsonpParameterNames
的property文件来定制属性。