Spring MVC:将请求属性绑定到控制器方法参数

在Spring MVC中,很容易将请求参数绑定到处理请求的方法参数。 我只是使用@RequestParameter("name") 。 但是我可以对请求属性执行相同的操作吗? 目前,当我想访问请求属性时 ,我必须执行以下操作:

 MyClass obj = (MyClass) request.getAttribute("attr_name"); 

但我真的想用这样的东西代替:

 @RequestAttribute("attr_name") MyClass obj 

不幸的是,它没有这种方式。 我可以以某种方式扩展Springfunction并添加我自己的“绑定器”吗?

编辑 (我想要实现的目标) :我将当前登录的用户存储在请求属性中。 因此,每当我想访问当前登录的用户(这几乎都在每个方法内)时,我必须写这个额外的行user = (User) request.getAttribute("user"); 。 我想尽量缩短它,最好将它作为方法参数注入。 或者如果你知道如何通过拦截器和控制器传递某些东西,我会很高兴听到它。

好吧,我终于理解了模型的工作原理以及@ModelAttribute用途。 这是我的解决方案。

 @Controller class MyController { @ModelAttribute("user") public User getUser(HttpServletRequest request) { return (User) request.getAttribute("user"); } @RequestMapping(value = "someurl", method = RequestMethod.GET) public String HandleSomeUrl(@ModelAttribute("user") User user) { // ... do some stuff } } 

标有@ModelAttribute批注的getUser()方法将自动填充用@ModelAttribute标记的所有User user参数。 因此,当调用HandleSomeUrl方法时,调用看起来像MyController.HandleSomeUrl(MyController.getUser(request)) 。 至少这是我的想象。 很酷的是,用户也可以从JSP视图中访问而无需任何进一步的努力。

这解决了我的问题,但我还有其他问题。 是否有一个共同的地方,我可以把那些@ModelAttribute方法,所以他们是我的所有控制器共同的? 我可以以某种方式从拦截器的preHandle()方法内部添加模型属性吗?

使用(截至Spring 4.3) @RequestAttribute :

 @RequestMapping(value = "someurl", method = RequestMethod.GET) public String handleSomeUrl(@RequestAttribute User user) { // ... do some stuff } 

或者如果请求属性名称与方法参数名称不匹配:

 @RequestMapping(value = "someurl", method = RequestMethod.GET) public String handleSomeUrl(@RequestAttribute(name="userAttributeName") User user) { // ... do some stuff } 

我认为你在寻找的是:

 @ModelAttribute("attr_name") MyClass obj 

您可以在控制器中方法的参数中使用它。

这是一个问题的链接,有关它的详细信息什么是Spring MVC中的@ModelAttribute?

该问题链接到Spring文档,并提供了一些使用它的示例。 你可以在这看到

更新

我不确定您是如何设置页面的,但您可以通过几种不同的方式将用户添加为模型属性。 我在这里设置了一个简单的例子。

 @RequestMapping(value = "/account", method = RequestMethod.GET) public ModelAndView displayAccountPage() { User user = new User(); //most likely you've done some kind of login step this is just for simplicity return new ModelAndView("account", "user", user); //return view, model attribute name, model attribute } 

然后,当用户提交请求时,Spring会将user属性绑定到方法参数中的User对象。

 @RequestMapping(value = "/account/delivery", method = RequestMethod.POST) public ModelAndView updateDeliverySchedule(@ModelAttribute("user") User user) { user = accountService.updateDeliverySchedule(user); //do something with the user return new ModelAndView("account", "user", user); } 

不是最优雅,但至少起作用……

 @Controller public class YourController { @RequestMapping("/xyz") public ModelAndView handle( @Value("#{request.getAttribute('key')}") SomeClass obj) { ... return new ModelAndView(...); } } 

资料来源: http : //blog.crisp.se/tag/requestattribute

从Spring 3.2开始,使用Springs ControllerAdvice注释可以更好地完成。 然后,这将允许您有一个建议,将@ModelAttributes添加到一个单独的类中,然后将其应用于所有控制器。

为了完整起见,还可以实际生成@RequestAttribute(“attr-name”)。 (以下修改以符合我们的要求)

首先,我们必须定义注释:

 @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.PARAMETER) public @interface RequestAttribute { String value(); } 

然后我们需要一个[WebArgumentResolver]来处理绑定属性时需要做的事情

 public class RequestAttributeWebArgumentResolver implements WebArgumentResolver { public Object resolveArgument(MethodParameter methodParameter, NativeWebRequest nativeWebRequest) throws Exception { // Get the annotation RequestAttribute requestAttributeAnnotation = methodParameter.getParameterAnnotation(RequestAttribute.class); if(requestAttributeAnnotation != null) { HttpServletRequest request = (HttpServletRequest) nativeWebRequest.getNativeRequest(); return request.getAttribute(requestAttributeAnnotation.value); } return UNRESOLVED; } } 

现在我们需要的是将这个自定义解析器添加到配置中以解决它:

      

我们完成了!

是的,您可以将自己的“绑定器”添加到请求属性中 – 请参阅spring-mvc-3-showcase ,或使用@Peter Szanto的解决方案。

或者,将其绑定为ModelAttribute,如其他答案中所建议的那样。

因为它是您想要传递到控制器的登录用户,所以您可能需要考虑Spring Security 。 然后你可以将原理注入到你的方法中:

 @RequestMapping("/xyz") public String index(Principal principle) { return "Hello, " + principle.getName() + "!"; } 

在Spring WebMVC 4.x中,它更喜欢实现HandlerMethodArgumentResolver

 @Override public boolean supportsParameter(MethodParameter parameter) { return parameter.getParameterAnnotation(RequestAttribute.class) != null; } @Override public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { return webRequest.getAttribute(parameter.getParameterAnnotation(RequestAttribute.class).value(), NativeWebRequest.SCOPE_REQUEST); } 

}

然后在RequestMappingHandlerAdapter中注册它