zoukankan      html  css  js  c++  java
  • <mvc:annotation-driven>新增标签

    以下为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接口中定义了两个方法 :
        1. supportsReturnType 方法用来确定此实现类是否支持对应返回类型。 
        2. 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以便于让用户更方便的实现自定义的实现类。

    转 : https://www.cnblogs.com/liaojie970/p/7736018.html

  • 相关阅读:
    Oracle EXP
    Using Spring in Web and WinForms
    System.ComponentModel(未完...)
    工作必须得到强势方的支持!
    book.Save()还是bookManager.Save(book)?
    C#中常用的Attribute搜集(刚开始...)
    领域模型是否能够屏蔽数据库?
    合格代码的最基本的标准
    关于配置系统的设计
    对象分类
  • 原文地址:https://www.cnblogs.com/fps2tao/p/12843858.html
Copyright © 2011-2022 走看看