如何实现Spring的3.1 MvcAnnotationDriven?
这是 Spring 3.1 Spring 源码博客:从 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;
}
}
}
This is the code example from Spring 3.1 Spring Source Blog: From XML to @Configuration I'm trying to implement in my application (which was done in Spring 2.0 not by me so it's lot of learning).
@FeatureConfiguration
class MvcFeatures {
@Feature
public MvcAnnotationDriven annotationDriven(ConversionService conversionService) {
return new MvcAnnotationDriven().conversionService(conversionService)
.argumentResolvers(new CustomArgumentResolver());
}
// ...
}
However, I can't understand the point of .argumentResolvers(new CustomArgumentResolver()) and their CustomArgumentResolver looks like bellow. What's the point of it?
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;
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
为了补充 @GaryF 的答案,并澄清一些观点,Spring 2.5 引入了带注释的控制器,它取代了 Spring 2.0 的旧界面风格控制器。这些新控制器具有没有固定参数的方法 - 该方法声明其完成其工作所需的参数,仅此而已。
例如,假设控制器方法需要一件事来完成其工作 - 包含数据库中对象的 ID 的请求参数。在 Spring 2.0 中,您需要实现类似
AbstractController.handleRequestInternal()
的东西,例如Spring 2.5 使这变得更容易:
在这里,我们只声明我们需要的参数。
到目前为止一切顺利,但这就是自定义
WebArgumentResolver
的用武之地。假设我想从我的控制器中完全删除getObjById
,因为也许我认为它会使代码变得混乱,也许它可以在许多其他控制器方法中使用。相反,我想这样做:它更简单,并且具有最少的样板代码。自定义
WebArgumentResolver
可以在应用程序上下文中注册,该应用程序上下文可识别MyThing
类型的参数,并知道如何从请求中提取信息。 Spring 调用该解析器,并将结果传递给控制器方法。自定义解析器并不常用,但在适当的情况下会非常方便。
您问题中的示例使用
CustomArgumentResolver
来解析示例的自定义RequestAttribute
类。解析器提取请求属性并将它们绑定到RequestAttribute
对象,以便它们可以被声明为控制器方法参数。To add to @GaryF's answer, and to clarify some points, Spring 2.5 introduced annotated controllers, which replaced the old interface-style controllers of Spring 2.0. These new controllers have methods with no fixed parameters - the method declares the parameters that it needs to do its job, and nothing more.
For example, say a controller method needed one thing to do its job - a request parameter that contains the ID of an object from the database. In Spring 2.0, you would need to implement something like
AbstractController.handleRequestInternal()
, e.gSpring 2.5 made that easier:
Here, we only declare parameters for the stuff we need.
So far so good, but this is where a custom
WebArgumentResolver
comes in. Say I want to remove thegetObjById
from my controller altogether, because maybe I think it clutters up the code, and maybe it's used across many other controller methods. Instead, I want to do this:It's even simpler, and has a bare minimum of boilerplate code. A custom
WebArgumentResolver
can be registered with the app-context which recognises parameters of typeMyThing
, and knows how to extract the information from the request. Spring invokes that resolver, and passes the result to the controller method.Custom resolvers aren't commonly used, but can be very handy in the right situation.
The example in your question uses
CustomArgumentResolver
to resolve the example's customRequestAttribute
class. The resolver pulls out request attributes and binds them toRequestAttribute
objects, so that they can be declared as controller method parameters.WebArgumentResolver
是一种指定如何解析 MVC 映射方法的参数的方法。如果您想使用自定义对象作为 MVC 映射方法的参数,Spring 会尝试以自己的方式弄清楚如何理解它。通常这会通过绑定发生,您提交的一些 http 参数与对象的字段匹配,Spring 匹配它们并为您创建一个新对象。如果您遇到提交的参数与方法参数不完全匹配的情况,WebArgumentResolvers 可以填补这个空白:您提供自定义逻辑,这样 Spring 就不必弄清楚它。
在您的示例中, param 是要匹配的此类参数之一。这段自定义代码首先检查参数是否有@RequestAttribute注释。如果是,则自定义代码从该对象中提取值,并将其作为 http 请求上的属性进行查找,然后将其返回。如果它没有该注释,则该方法返回 UNRESOLVED 值,这仅表明此 WebArgumentResolver 不知道有关此特定参数的任何信息,并且 Spring 应该尝试不同的方法(例如绑定)。
WebArgumentResolver
s are a way for you to specify how the parameters of MVC-mapped methods should be resolved. If you'd like to use a custom object as a parameter for an MVC-mapped method, Spring tries to figure out how make sense of it in it's own way. Typically this would happen through binding, where some http parameters you submit match up with the fields of the object and Spring matches them up and creates a new object for you.If you ever have a situation where the submitted parameters don't match up quite so neatly with your method parameters, WebArgumentResolvers are there to fill in the gap: you provide custom logic so Spring doesn't have to figure it out.
In your example, param is one such parameter to be matched up. This piece of custom code first checks if the parameter has an @RequestAttribute annotation. If it does, then the custom code pulls the value from that object and looks it up as an attribute on the http request, returning it. It it does not have that annotation, then the method returns the UNRESOLVED value, which simply indicates that this WebArgumentResolver doesn't know anything about this particular parameter and Spring should try a different method (such as binding).