22

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

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

但我真的很想改用这样的东西:

@RequestAttribute("attr_name") MyClass obj

不幸的是,它不能以这种方式工作。我可以以某种方式扩展 Spring 功能并添加我自己的“绑定器”吗?

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

4

7 回答 7

36

好吧,我终于明白了一点模型的工作原理和@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
    }
}

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

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

于 2013-02-23T00:48:54.970 回答
14

使用(从 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
}
于 2016-10-07T15:45:16.733 回答
3

我认为您正在寻找的是:

@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对象上。

@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);
}
于 2013-02-22T20:02:57.803 回答
2

不是最优雅的,但至少可以工作......

@Controller
public class YourController {

    @RequestMapping("/xyz")
    public ModelAndView handle(
        @Value("#{request.getAttribute('key')}") SomeClass obj) {

        ...
        return new ModelAndView(...);
    }

}

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

于 2015-11-04T15:14:39.683 回答
1

从 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;
    }
}

现在我们只需要将此 customresolver 添加到配置中即可解决它:

<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
    <property name="customArgumentResolver">
        <bean class="com.sergialmar.customresolver.web.support.CustomWebArgumentResolver"/>
    </property>
</bean>

我们完成了!

于 2015-06-08T21:52:59.127 回答
0

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

或者,按照其他答案中的建议,将其绑定为 ModelAttribute。

由于它是您要传递到控制器的登录用户,因此您可能需要考虑Spring Security。然后您可以将Principle注入您的方法中:

@RequestMapping("/xyz")
public String index(Principal principle) {
    return "Hello, " + principle.getName() + "!";
}
于 2016-01-07T12:55:01.053 回答
0

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

于 2016-01-19T03:51:27.997 回答