【问题标题】:Upgrading to spring-3.1 seems to break my CustomWebArgumentResolver升级到 spring-3.1 似乎打破了我的 CustomWebArgumentResolver
【发布时间】:2012-09-10 18:58:32
【问题描述】:

我正在尝试将 Spring MVC 应用程序从 3.0.6 升级到 3.1.2,并且一些过去可以工作的控制器似乎不再工作了。我已经阅读了 spring 文档,但我对什么与什么兼容感到困惑。

我们有一个 CustomWebArgumentResolver,它查找任何名为“asOf”的请求参数并将其值转换为日期。我们称其为“AsOfDateConverter”。升级到 spring-3.1.2 时,我利用了新的命名空间功能并将其添加到我的 applicationContext:

<mvc:annotation-driven conversion-service="conversionService">
    <mvc:argument-resolvers>
        <bean id="customWebArgumentResolver" class="my.converters.CustomWebArgumentResolver">
        </bean>            
    </mvc:argument-resolvers>
</mvc:annotation-driven>

CustomWebArgumentResolver 很简单:

public class CustomWebArgumentResolver implements WebArgumentResolver {
    private AsOfDateConverter asOfDateConverter;

    @Override
    public Object resolveArgument(MethodParameter methodParameter, NativeWebRequest webRequest) throws Exception {
        if (isAsOfDateParameter(methodParameter)) {
            return asOfDateConverter.convert(webRequest.getParameter("asOf"));
        }

        return UNRESOLVED;
    }

然后一个示例控制器可能看起来像这样:

@Controller
@Secured({BaseController.ROLE_LOGGED_IN})
@org.springframework.transaction.annotation.Transactional
public class DashboardController extends BaseController {
    public static final String URL = "/dashboard";

    @RequestMapping(value=URL, method=RequestMethod.GET)
    public ModelAndView get(@RequestParam(required=false) String requestedMeterType, @AsOf Date asOf) {
        debug(log, "Rendering dashboard asOf %s", asOf);
etc etc

“asOf”参数为空,我确定我遗漏了一些明显的东西。如果有人深入了解最新的 MVC 3.1 内容,可以为我指明正确的方向,我将不胜感激。

谢谢! 汤姆

编辑: AsOf 注释:

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface AsOf {
}

更多我的applicationContext:

<mvc:annotation-driven conversion-service="conversionService">
    <mvc:argument-resolvers>
        <bean class="[blah].AsOfDateHandlerMethodArgumentResolver">
            <property name="asOfDateConverter">
                <bean class="[blah].AsOfDateConverter"/>
            </property>
        </bean> 
    </mvc:argument-resolvers>
</mvc:annotation-driven>

<!-- Added to re-support @Controller annotation scanning after upgrading to spring-3.1. -->
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>


<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
    <property name="converters">
        <set>
            <bean class="[blah].converters.CustomerConverter"/>
            <bean class="[blah].converters.AccountConverter"/>
            <bean class="[blah].converters.DateConverter"/>
            <bean class="[blah].converters.CustomerCommunicationInstanceConverter"/>
            <bean class="[blah].converters.MeterTypeConverter"/>
            <bean class="[blah].converters.AreaAmountConverter" p:precision="0"/>
            <bean class="[blah].converters.LengthAmountConverter" p:precision="1"/>
        </set>
    </property>
</bean>

【问题讨论】:

    标签: spring spring-mvc


    【解决方案1】:

    API 在 Spring 3.1 中发生了变化 - 用于解析控制器参数的接口是 HandlerMethodArgumentResolver。你可以继续使用CustomWebArgumentResolver,通过adapting它到一个HandlerMethodArgumentResolver

    不过更改代码以使用 HandlerMethodArgumentResolver 也很容易:

    public class CustomWebArgumentResolver implements HandlerMethodArgumentResolver {
        private AsOfDateConverter asOfDateConverter;
    
        @Override
        public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) {
            if (isAsOfDateParameter(methodParameter)) {
                return asOfDateConverter.convert(webRequest.getParameter("asOf"));
            }
    
            return UNRESOLVED;
    
        }
    
    
        @Override
        public boolean supportsParameter(MethodParameter parameter) {
            return (methodParameter.getParameterAnnotation(AsOf.class)!=null)
        }
    

    编辑

    在查看了您的 cmets 之后,我想我知道可能出了什么问题。请检查您的@AsOf 注释,您可能没有声明 Runtime 的保留,这可能是 WebArgumentResolver 没有生效的原因:

    @Retention(RetentionPolicy.RUNTIME)
    public @interface AsOf {
    
    }
    

    无论如何,这里是一个完整的工作测试的要点:

    https://gist.github.com/3703430

    【讨论】:

    • 感谢您指出 API 更改。我已将我的 CustomWebArgumentResolver 从 WebArgumentResolver 的实现转换为 HandlerMethodArgumentResolver 的实现(如您的)。添加大量日志记录后,似乎它的工作正常,但控制器仍然设置为空日期(!)。这就像参数被正确映射到处理程序,但没有被设置回控制器上。所以这方面的一些东西仍然不起作用......
    • 实际上,进一步认为 CustomWebArgumentResolver 根本没有传递任何日期字符串......只是空值。我是否需要在控制器的 get() 方法上使用 ParamMappings,就在 AsOf 注释之前?
    • 但是您正在从请求参数中获取asOf,因此您遇到的问题是存在 asOf 参数并且似乎也进入了 resolveArgument 方法,但是在方法中它本身是 null 是吗
    • 记录语句告诉我(1)resolveArgument 方法得到一个空值,(2)resolveArgument 方法看到空值并决定返回一个“新日期()”,(3)控制器注入null。所以不知何故,控制器和 HandlerMethodArgumentResolver 之间的输入/输出管道正在清空数据。
    • 我添加了一个对我有用的完整测试的要点 - gist.github.com/3703430,你能检查一下。您是否还可以检查您的注释是否具有运行时保留
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-11-04
    • 1970-01-01
    • 2020-12-04
    • 1970-01-01
    • 2015-03-15
    • 2020-03-18
    • 2019-02-26
    相关资源
    最近更新 更多