两个问题说明WebArgumentResolver vs HandlerMethodArgumentResolver

在Spring MVC的Controller的方法中,可以直接使用 Model 这样的参数,这是因为在调用Controller方法之前已经对指定的参数进行预处理了,Spring MVC分别提供了WebArgumentResolverHandlerMethodArgumentResolver接口,具体的用法很容易查到,这里说两个遇到的问题。

第一个问题:在配置文件中自定义的argument只有第一个有效,后面的参数都无效。

相关的配置信息如下:

<mvc:annotation-driven>
    <mvc:argument-resolvers>
        <bean class="com.javatang.example.biz.interceptor.AccountArgumentResolver" />
        <bean class="com.javatang.example.biz.interceptor.DeviceTypeWebArgumentResolver" />
    </mvc:argument-resolvers>
</mvc:annotation-driven>

AccountArgumentResolver.java文件内容如下:

public class AccountArgumentResolver implements WebArgumentResolver {

    @Override
    public Object resolveArgument(MethodParameter param, NativeWebRequest request) throws Exception {
        if(Account.class.isAssignableFrom(param.getParameterType())) {
            return new Account();
        }

        return null;
    }
}

问题是 AccountArgumentResolver 可以执行,但下面的 DeviceTypeWebArgumentResolver 有时候无法执行,后来查阅了资料发现,在resolveArgument方法中当对象的类型不是指定的类型的时候,必须返回 WebArgumentResolver.UNRESOLVED而不是null,否则下一个参数解析器无法执行。

第二个问题:参数解析器在过滤器之前执行

如果参数解析器是通过实现WebArgumentResolver接口创建的话,其中的resolveArgument方法会在 <mvc:interceptors>...</mvc:interceptors> 中定义的过滤器之后执行。

Spring 3.1之后增加一个HandlerMethodArgumentResolver接口,该接口的方法是在过滤器之后执行的,并且resolveArgument方法可以返回null,不会造成上面的问题。

因此,后面可以使用 HandlerMethodArgumentResolver 完全替代 WebArgumentResolver 接口。

参考资料:
Spring mvc - implementation of WebArgumentResolver
spring mvc WebArgumentResolver不生效
Spring Web MVC 3.1.1 argument resolver called before interceptor

发表评论

电子邮件地址不会被公开。 必填项已用*标注