mvc annotation-driven 新增标签

http://starscream.iteye.com/blog/1098880
mvc annotation-driven 新增标签
以下为spring mvc 3.1中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
我们增加以下配置

   
       
    

    
实现类
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进行解析

    
        
    


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 {
    @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 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的相应配置如下

    


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.的话,可以这么来做


新增messageCodeResolver 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;
}













你可能感兴趣的:(mvc annotation-driven 新增标签)