1

这是来自 Spring 3.1 Spring Source 博客的代码示例:从 XML 到 @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;
        }
    }
}
4

2 回答 2

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对象,以便可以将它们声明为控制器方法参数。

于 2011-03-20T22:13:06.517 回答
1

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

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

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

于 2011-03-20T21:32:33.680 回答