您的位置:首页 > 移动开发

6、Spring MVC 之 定义@RequestMapping处理方法

2016-07-29 23:53 453 查看
@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文件来定制属性。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: