分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 软件开发

<mvc:annotation-driven>新增标签

发布时间:2023-09-06 01:20责任编辑:苏小强关键词:暂无标签

以下为spring mvc 3.1中annotation-driven所支持的全部配置

<mvc:annotation-driven ?message-codes-resolver ="bean ref" validator="" conversion-service=""> ???????????<mvc:return-value-handlers> ?????????<bean></bean> ?????</mvc:return-value-handlers> ???????????<mvc:argument-resolvers> ?????</mvc:argument-resolvers> ???????????<mvc:message-converters> ?????</mvc:message-converters></mvc:annotation-driven> 

其中3.1新增部分如下    
return-value-handlers 
允许注册实现了HandlerMethodReturnValueHandler接口的bean,来对handler method的特定的返回类型做处理。 
HandlerMethodReturnValueHandler接口中定义了两个方法 
supportsReturnType 方法用来确定此实现类是否支持对应返回类型。 
handleReturnValue 则用来处理具体的返回类型。 

例如以下的handlerMethod 

@RequestMapping("/testReturnHandlers") ?public User testHandlerReturnMethod(){ ?????User u ?= new User(); ?????u.setUserName("test"); ?????return u; ?} ?

所返回的类型为一个pojo,正常情况下spring mvc无法解析,将转由DefaultRequestToViewNameTranslator 解析出一个缺省的view name,转到 testReturnHandlers.jsp, 
我们增加以下配置 

<mvc:annotation-driven validator="validator"><mvc:return-value-handlers> ?????????<bean ?class="net.zhepu.web.handlers.returnHandler.UserHandlers"></bean> ??????</mvc:return-value-handlers>[/color] ?</mvc:annotation-driven> 

及如下实现类 

public class UserHandlers implements HandlerMethodReturnValueHandler { ?????Logger logger = LoggerFactory.getLogger(this.getClass()); ?????@Override ?????public boolean supportsReturnType(MethodParameter returnType) { ?????????Class<?> type = returnType.getParameterType(); ?????????if(User.class.equals(type)) ?????????{ ?????????????return true; ?????????} ?????????return false; ?????} ???????@Override ?????public void handleReturnValue(Object returnValue, ?????????????MethodParameter returnType, ModelAndViewContainer mavContainer, ?????????????NativeWebRequest webRequest) throws Exception { ?????????logger.info("handler ?for return type users "); ?????????mavContainer.setViewName("helloworld"); ?????} ???} ?

此时再访问 http://localhost:8080/springmvc/testReturnHandlers ,将交由 UserHandlers来处理返回类型为User的返回值。 

argument-resolvers 
允许注册实现了WebArgumentResolver接口的bean,来对handlerMethod中的用户自定义的参数或annotation进行解析 
例如 

<mvc:annotation-driven validator="validator"> ?????<mvc:argument-resolvers> ?????????<bean ?class="net.zhepu.web.handlers.argumentHandler.MyCustomerWebArgumentHandler" /> ?????</mvc:argument-resolvers> ?</mvc:annotation-driven> ?

对应java代码如下 

public class MyCustomerWebArgumentHandler implements WebArgumentResolver { ???????@Override ?????public Object resolveArgument(MethodParameter methodParameter, ?????????????NativeWebRequest webRequest) throws Exception { ?????????if (methodParameter.getParameterType().equals(MyArgument.class)) { ?????????????MyArgument argu = new MyArgument(); ?????????????argu.setArgumentName("winzip"); ?????????????argu.setArgumentValue("123456"); ?????????????return argu; ?????????} ?????????return UNRESOLVED; ?????} ???} ?

这里我们定义了一个 customer webArgumentHandler,当handler method中参数类型为 MyArgument时生成对参数的类型绑定操作。 
注意新注册的webArgumentHandler的优先级最低,即如果系统缺省注册的ArgumentHandler已经可以解析对应的参数类型时,就不会再调用到新注册的customer ArgumentHandler了。 

message-converters 
允许注册实现了HttpMessageConverter接口的bean,来对requestbody 或responsebody中的数据进行解析 
例如 
假设我们使用 text/plain格式发送一串字符串来表示User对象,各个属性值使用”|”来分隔。例如 winzip|123456|13818888888,期望转为user对象,各属性内容为user.username = winzip,user.password=123456;user.mobileNO = 13818888888 
以下代码中supports表示此httpmessageConverter实现类针对 User类进行解析。 
构造函数中调用 super(new MediaType("text", "plain"));以表示支持 text/plain格式的输入。

public class MyCustomerMessageConverter extends ?????????AbstractHttpMessageConverter<Object> { ?????@Override ?????protected boolean supports(Class<?> clazz) { ?????????if (clazz.equals(User.class)) { ?????????????return true; ?????????} ?????????return false; ?????} ???????public MyCustomerMessageConverter() { ?????????super(new MediaType("text", "plain")); ?????} ???????@Override ?????protected Object readInternal(Class<? extends Object> clazz, ?????????????HttpInputMessage inputMessage) throws IOException, ?????????????HttpMessageNotReadableException { ?????????Charset charset; ?????????MediaType contentType = inputMessage.getHeaders().getContentType(); ?????????if (contentType != null && contentType.getCharSet() != null) { ?????????????charset = contentType.getCharSet(); ?????????} else { ?????????????charset = Charset.forName("UTF-8"); ?????????} ?????????String input = FileCopyUtils.copyToString(new InputStreamReader( ?????????????????inputMessage.getBody(), charset)); ?????????logger.info(input); ?????????String[] s = input.split("\\|"); ?????????User u = new User(); ?????????u.setUserName(s[0]); ?????????u.setPassword(s[1]); ?????????u.setMobileNO(s[2]); ?????????return u; ?????} ???????@Override ?????protected void writeInternal(Object t, HttpOutputMessage outputMessage) ?????????????throws IOException, HttpMessageNotWritableException { ???????} ?

修改servlet context xml配置文件,增加message-converters的相应配置如下

<mvc:message-converters> ?????<bean class="net.zhepu.web.handlers.messageConverterHandler.MyCustomerMessageConverter"></bean> ?</mvc:message-converters> ?

message-codes-resolver 
先看看spring mvc中对于messageCodeResolver的用法。 
spring mvc中使用DefaultMessageCodesResolver作为缺省的MessageCodesResolver的实现类,其作用是对valid errors中的errorcode进行解析。其解析方式如下 
当解析error global object注册的errorcode时,errorcode的查找顺序为 
1:errorcode.validationobjectname 
2:errorcode 
例如 
以下声明中 

public String helloWorld2(@ModelAttribute("user") User u, ?BindingResult result) ?

当使用 result.reject("testFlag");来注册一个globat error object时,spring mvc将在messageSource中先查找 testFlag.user这个errorcode,当找不到时再查找testFlag这个errorcode。 

当解析fields error时,将按以下顺序生成error code 
1.: code + "." + object name + "." + field 
2.: code + "." + field 
3.: code + "." + field type 
4.: code 

还是以上面的代码为例,当使用 result.rejectValue("userName", "testFlag");来注册一个针对user.UserName属性的错误描述时,errors对象中将生成以下的error code list, 
1.: testFlag.user.userName 
2.: testFlag.userName 
3.: testFlag.java.lang.String 
4.: testFlag 

而mvc:annotation-driven新增的属性message-codes-resolver则提供了注册自定义的MessageCodesResolver的手段。 
例如上面想要在所有的error code前增加前缀validation.的话,可以这么来做 

<mvc:annotation-driven validator="validator" message-codes-resolver="messageCodeResolver"> ?</mvc:annotation-driven> ?

新增messageCodeResolver bean定义如下 

<bean id="messageCodeResolver" class="org.springframework.validation.DefaultMessageCodesResolver"> ?????<property name="prefix" value="validation."></property> ?</bean> ?

此时,所有的errorcode都会生成缺省前缀 validation. 
例如前面的 result.reject("testFlag"); 生成的error code list就变为了 
validation.testFlag.user 和 validation.testFlag了

2: @RequestMapping 新增参数Consumes 和Produces 
前面介绍过@RequestMapping的参数中有一个header的参数,来指定handler method能接受的http request 请求的header内容。 
而consumes和produces则更进一步,直接指定所能接受或产生的request请求的content type。 
例如

@RequestMapping(value="/testMsgConverter",consumes="text/plain",produces="application/json") 

表示handlermethod接受的请求的header中的 Content-Type为text/plain; 
Accept为application/json 

3: URI Template 新增功能 
这部分的例子直接照抄Spring 3.1 M2: Spring MVC Enhancements中的示例 

1: @PathVariable 声明的参数可自动加入到model中。 
    例如 

@RequestMapping("/develop/apps/edit/{slug}") ?public String editForm(@PathVariable String slug, Model model) { ?????model.addAttribute("slug", slug); ?????// ... ?} ?

现在可以写为 

@RequestMapping("/develop/apps/edit/{slug}") ?public String editForm(@PathVariable String slug, Model model) { ?????// model contains "slug" variable ?} ?

2:handler method中的redirect string可支持url template了 
例如 

@RequestMapping( ?????value="/groups/{group}/events/{year}/{month}/{slug}/rooms", ?????method=RequestMethod.POST) ?public String createRoom( ?????@PathVariable String group, @PathVariable Integer year, ?????@PathVariable Integer month, @PathVariable String slug) { ?????// ... ?????return "redirect:/groups/" + group + "/events/" + year + "/" + month + "/" + slug; ?} ?

现在可写为 

@RequestMapping( ?????value="/groups/{group}/events/{year}/{month}/{slug}/rooms", ?????method=RequestMethod.POST) ?public String createRoom( ?????@PathVariable String group, @PathVariable Integer year, ?????@PathVariable Integer month, @PathVariable String slug) { ?????// ... ?????return "redirect:/groups/{group}/events/{year}/{month}/{slug}"; ?} ?

3:url template中可支持databinding 了 
例如 

@RequestMapping("/people/{firstName}/{lastName}/SSN") ?public String find(Person person, ????????????????????@PathVariable String firstName, ????????????????????@PathVariable String lastName) { ?????person.setFirstName(firstName); ?????person.setLastName(lastName); ?????// ... ?} ?

现在可以写成 

@RequestMapping("/people/{firstName}/{lastName}/SSN") ?public String search(Person person) { ?????// person.getFirstName() and person.getLastName() are populated ?????// ... ?} ?

4: Validation For @RequestBody 

@RequestBody现在直接支持@valid标注了,如果validation失败,将抛出 
RequestBodyNotValidException。 
具体处理逻辑可见 spring 中的RequestResponseBodyMethodProcessor中的以下代码。

public Object resolveArgument(MethodParameter parameter, ???????????????????????????????????ModelAndViewContainer mavContainer, ???????????????????????????????????NativeWebRequest webRequest, ???????????????????????????????????WebDataBinderFactory binderFactory) throws Exception { ?????????Object arg = readWithMessageConverters(webRequest, parameter, parameter.getParameterType()); ?????????if (shouldValidate(parameter, arg)) { ?????????????String argName = Conventions.getVariableNameForParameter(parameter); ?????????????WebDataBinder binder = binderFactory.createBinder(webRequest, arg, argName); ?????????????binder.validate(); ?????????????Errors errors = binder.getBindingResult(); ?????????????if (errors.hasErrors()) { ?????????????????throw new RequestBodyNotValidException(errors); ?????????????} ?????????} ?????????return arg; ?????} ?

5:annotation-driven缺省注册类的改变 

Spring 3.0.x中使用了annotation-driven后,缺省使用DefaultAnnotationHandlerMapping 来注册handler method和request的mapping关系。 

AnnotationMethodHandlerAdapter来在实际调用handlermethod前对其参数进行处理。 

并在dispatcherServlet中,当用户未注册自定义的ExceptionResolver时,注册AnnotationMethodHandlerExceptionResolver来对使用@ExceptionHandler标注的异常处理函数进行解析处理(这也导致当用户注册了自定义的exeptionResolver时将可能导致无法处理@ExceptionHandler)。 

在spring mvc 3.1中,对应变更为 
DefaultAnnotationHandlerMapping -> RequestMappingHandlerMapping 
AnnotationMethodHandlerAdapter -> RequestMappingHandlerAdapter 
AnnotationMethodHandlerExceptionResolver -> ExceptionHandlerExceptionResolver 

以上都在使用了annotation-driven后自动注册。 
  而且对应分别提供了AbstractHandlerMethodMapping , AbstractHandlerMethodAdapter和 AbstractHandlerMethodExceptionResolver以便于让用户更方便的实现自定义的实现类。

<mvc:annotation-driven>新增标签

原文地址:http://www.cnblogs.com/liaojie970/p/7736018.html

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved