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中注册它