2013-02-22 70 views
18

在Spring MVC中,很容易將請求參數綁定到處理請求的方法參數。我只是使用@RequestParameter("name")。但是,我可以做同樣的請求屬性?目前,當我想訪問請求屬性,我必須做以下幾點:Spring MVC:將請求屬性綁定到控制器方法參數

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

但我真的想用這樣的事情,而不是:

@RequestAttribute("attr_name") MyClass obj 

不幸的是,它不這樣工作。我可以以某種方式擴展Spring功能並添加我自己的「活頁夾」?

編輯(我想要實現):我存儲當前登錄請求屬性內的用戶。所以,無論何時我想訪問當前登錄的用戶(這在每種方法中都很常見),我必須寫出這個額外的行user = (User) request.getAttribute("user");。我希望儘可能縮短它,最好將它作爲方法參數注入。或者,如果您知道如何通過攔截器和控制器傳遞某些信息,我很樂意聽到。

回答

29

那麼,我終於明白了一點,模型是如何工作的,什麼是@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將自動填充標記@ModelAttribute所有User user參數。所以當HandleSomeUrl方法被調用時,調用看起來像MyController.HandleSomeUrl(MyController.getUser(request))。至少這是我的想法。很酷的是,用戶也可以從JSP視圖中訪問,而無需進一步的努力。

這解決了我的問題,但我還有其他問題。是否有一個共同的地方,我可以把這些@ModelAttribute方法,所以他們是我的所有控制器通用?我能以某種方式添加攔截器的preHandle()方法內部的模型屬性嗎?

+0

這是完美的!謝謝。 – Raff 2013-05-24 14:01:53

+0

如果參數名稱與模型對象上的屬性匹配,則不需要額外的getUser方法,spring將自動設置這些屬性 – chrismarx 2014-02-07 21:33:53

+1

這樣,您的方法中的User對象不僅可以從視圖模型中檢索,還可以從其視圖模型中檢索將被傳入的請求或表單參數綁定(並覆蓋)。例如,如果User對象具有一個id屬性(許多用戶對象將擁有該屬性),並且請求url或表單也具有不相關的id參數,則它將覆蓋User對象的id。這曾經在我的代碼中創建了一個令人討厭的錯誤。在這種特殊情況下,您不需要@ModelAttribute的表單綁定屬性。另一種方法是使用User u =(User)model.get(「user」);' – klausch 2015-11-03 10:06:51

3

我知道你在尋找的是:

@ModelAttribute("attr_name") MyClass obj 

您可以使用的參數在控制器的方法。

這裏是一個鏈接,上面有What is @ModelAttribute in Spring MVC?

這個問題的鏈接使用太的一些例子Spring文檔細節質疑。你可以看到,here

更新

我不知道你是如何設置您的網頁,但你可以將用戶添加爲一個模型屬性幾種不同的方法。我在這裏設置一個簡單的例子。

@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會將用戶屬性綁定到方法參數中的用戶對象。

@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); 
} 
+0

謝謝,但我想別的實現的東西..也許我應該解釋說。我使用請求屬性來存儲當前登錄的用戶。所以就像你調用'User user =(User)session.getAttribute(「user」);'我調用'user =(User)request.getAttribute(「user」);'。但是用每一種方法寫這個都很麻煩。我想盡可能縮短這個時間,最好把它作爲方法參數注入。 – tobik 2013-02-22 20:39:13

+0

你仍然可以使用這種方法來做到這一點。您只需將User對象添加到模型中即可。然後你可以訪問它。有幾種方法可以做到這一點。我會更新我的答案。 – ssn771 2013-02-22 23:06:46

+0

我不熟悉'@SessionAttributes',但這也可能適用於你。這裏是關於它的文檔[鏈接](http://static.springsource.org/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-ann-sessionattrib)。 – ssn771 2013-02-22 23:28:39

0

從spring 3.2開始,使用Springs ControllerAdvice註解可以做得更好。 然後,這將允許您有一個建議,將@ModelAttributes添加到單獨的類中,然後將其應用於所有控制器。

爲了完整性,還可以實際製作@RequestAttribute(「attr-name」)。 (以下從this article修改,以適應我們的要求)

首先,我們必須定義註釋:

@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> 

我們完成了!

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

0

是的,你可以在自己的「粘合劑」添加到請求屬性 - 見spring-mvc-3-showcase,或使用@Peter Szanto的解決方案。

或者,按照其他答案中的建議將其綁定爲ModelAttribute。

由於它是登錄用戶,您想要傳入您的控制器,您可能需要考慮Spring Security。然後,你可以有Principle注入到你的方法:

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

在春天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

4
註冊它

使用(截至春季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 
} 
相關問題