2013-02-22 14 views
18

Spring MVCでは、リクエストパラメーターを要求を処理するメソッドパラメーターにバインドするのは簡単です。私はちょうど@RequestParameter("name")を使用します。しかし、私は要求属性で同じことをすることはできますか?現在、私が要求属性にアクセスしたいとき、私は次の操作を実行する必要があります。Spring MVC:コントローラーメソッドパラメーターへのバインド要求属性

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

しかし、私は本当に代わりに、このようなものを使用したいと思います:

@RequestAttribute("attr_name") MyClass obj 

は残念ながら、それはしていませんこのように働く。どういうわけかSpringの機能を拡張して、自分の "バインダー"を追加できますか?

EDIT(私が達成しようとしているものを):私は要求属性内で、現在ログインしているユーザーを格納します。ですから、現在ログに記録されているユーザー(すべてのメソッドのかなりの部分)にアクセスしたいときは、この余分な行を書く必要があります。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 
    } 
} 

@ModelAttribute注釈が付いgetUser()方法が自動的に@ModelAttributeでマークされたすべてのUser userのパラメータを移入します。したがって、HandleSomeUrlメソッドが呼び出されると、呼び出しはMyController.HandleSomeUrl(MyController.getUser(request))のようになります。少なくともこれは私がそれを想像する方法です。クールなことは、ユーザはJSPビューからさらにアクセスすることができます。

これは私の問題を解決しますが、それ以上の質問があります。私がこれらのコントローラをすべてのコントローラに共通するように、それらのメソッドを置くことができる共通の場所はありますか?インターセプタのメソッドpreHandle()の中からモデルの属性を追加することはできますか?

+0

これは完璧です!ありがとうございました。 – Raff

+0

パラメータ名がモデルオブジェクトのプロパティと一致する場合、追加のgetUserメソッドは必要ありません。春はこれらのプロパティを自動的に設定します – chrismarx

+1

この方法では、メソッドのUserオブジェクトはビューモデルから取得されるだけでなく、着信要求またはフォームのパラメータによってバインド(および上書き)されます。たとえば、Userオブジェクトに(多くのユーザーオブジェクトが持つ)idプロパティがあり、リクエストurlまたはフォームにも関連のないidパラメータがある場合、Userオブジェクトのidが上書きされます。これはかつて私のコードに厄介なバグを作りました。この特定のケースでは、@ModelAttributeのフォームバインドプロパティは必要ありません。代わりに 'User u =(User)model.get(" user ");'を使用しています。 – klausch

3

私はあなたが探しているものだと思う:

@ModelAttribute("attr_name") MyClass obj 

あなたは、コントローラのメソッドのパラメータにそれを使用することができます。ここで

もそれを使用してのいくつかの例で春のドキュメントへのリンクを問うことについての詳細What is @ModelAttribute in Spring MVC?

で質問するリンクAです。あなたは、私はあなたがあなたのページを設定しているかどうかはわかりません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はメソッドパラメータの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); 
} 
+0

おかげで、私は何かを達成しようとしていたが...多分私はそれを説明している必要があります。現在ログインしているユーザーを保存するためにrequest属性を使用します。 'User =(User)session.getAttribute(" user ");'私は 'user =(User)request.getAttribute(" user ");を呼び出します。しかし、すべての単一の方法でそれを書くのはかなり面倒です。私は可能な限り短くしたい、好ましくはメソッドのパラメータとしてそれを注入したいと思います。 – tobik

+0

この方法を使用してもこれを実行できます。モデルにUserオブジェクトを追加するだけです。その後、あなたはそれにアクセスすることができます。それを行うにはいくつかの方法があります。私は私の答えを更新します。 – ssn771

+0

私は '@ SessionAttributes'に精通していませんが、それもあなたのために働くかもしれません。ここには[link](http://static.springsource.org/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-ann-sessionattrib)のドキュメントがあります。 – ssn771

0

スプリング3.2から、スプリング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と考えてください。

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

}

その後

4
RequestMappingHandlerAdapterに登録:次に、あなただけの Principleがあなたの方法に注入することができ

使用(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 
} 
関連する問題