mvc annotation-driven 新增标签

http://starscream.iteye.com/blog/1098880
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>

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>
</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的返回值

2、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>

3、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了

@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

URI Template 新增功能
@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
}

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}";
}

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
    // ...
}

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;
}













评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值