如何实现Spring 3.1 Mvc Annotation驱动?

时间:2011-03-20 20:30:53

标签: java spring spring-mvc spring-annotations spring-3

这是Spring 3.1中的代码示例Spring Source Blog: From XML to @Configuration我正在尝试在我的应用程序中实现(这在Spring 2.0中完成,而不是由我学习)。

@FeatureConfiguration
class MvcFeatures {

    @Feature
    public MvcAnnotationDriven annotationDriven(ConversionService conversionService) {
        return new MvcAnnotationDriven().conversionService(conversionService)
            .argumentResolvers(new CustomArgumentResolver());
    }

    // ...

}

但是,我无法理解 .argumentResolvers(new CustomArgumentResolver())和他们的CustomArgumentResolver看起来像吼叫。有什么意义呢?

public class CustomArgumentResolver implements WebArgumentResolver {

    @Override
    public Object resolveArgument(MethodParameter param, NativeWebRequest request) throws Exception {
        RequestAttribute attr = param.getParameterAnnotation(RequestAttribute.class);
        if (attr != null) {
            return request.getAttribute(attr.value(), WebRequest.SCOPE_REQUEST);
        } else {
            return WebArgumentResolver.UNRESOLVED;
        }
    }
}

2 个答案:

答案 0 :(得分:3)

为了添加@ GaryF的答案,并澄清一些观点,Spring 2.5引入了带注释的控制器,它取代了Spring 2.0的旧接口式控制器。这些新控制器的方法没有固定的参数 - 该方法声明了它完成工作所需的参数,仅此而已。

例如,假设一个控制器方法需要做一件事 - 一个包含数据库中对象ID的请求参数。在Spring 2.0中,您需要实现AbstractController.handleRequestInternal()之类的内容,例如

protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) {
   String id = request.getParameter("id");
   MyThing obj = getObjById(id);
   //... do stuff and return ModelAndView
}

Spring 2.5让这更容易:

@RequestMapping
public ModelAndView handle(String id) {
   MyThing obj = getObjById(id);
   //... do stuff and return ModelAndView
}

在这里,我们只为我们需要的东西声明参数。

到目前为止一切都很好,但这是自定义WebArgumentResolver的用武之地。我想要完全从控制器中删除getObjById,因为也许我认为它会使代码混乱,也许它用于许多其他控制器方法。相反,我想这样做:

@RequestMapping
public ModelAndView handle(MyThing id) {
   //... do stuff and return ModelAndView
}

它甚至更简单,并且只有最少的样板代码。可以使用识别WebArgumentResolver类型的参数的app-context注册自定义MyThing,并知道如何从请求中提取信息。 Spring调用解析器,并将结果传递给控制器​​方法。

自定义解析器不常用,但在适当的情况下可以非常方便。

您问题中的示例使用CustomArgumentResolver来解析示例的自定义RequestAttribute类。解析器提取请求属性并将它们绑定到RequestAttribute个对象,以便它们可以声明为控制器方法参数。

答案 1 :(得分:1)

WebArgumentResolver是一种指定如何解析MVC映射方法的参数的方法。如果您想使用自定义对象作为MVC映射方法的参数,Spring会尝试以自己的方式弄清楚如何理解它。通常这会通过绑定发生,您提交的某些http参数与对象的字段匹配,Spring会匹配它们并为您创建一个新对象。

如果您遇到的情况是提交的参数与方法参数不完全匹配,WebArgumentResolvers就会填补空白:您提供自定义逻辑,因此Spring无需弄清楚。

在您的示例中,param是一个匹配的参数。这段自定义代码首先检查参数是否具有@RequestAttribute注释。如果是,则自定义代码从该对象中提取值并将其作为http请求中的属性进行查找,并将其返回。它没有那个注释,那么该方法返回UNRESOLVED值,它只是表明这个WebArgumentResolver对这个特定参数一无所知,Spring应该尝试不同的方法(比如绑定)。