web-dev-qa-db-ja.com

Spring 3のすべてのコントローラーのモデルに属性を追加します

Spring 3アプリのすべてのビューには、信頼できる一連の属性があります。したがって、すべてのコントローラーの最初の行は次のようなものです。

ControllerHelper.addDefaultModel(model, personManager, request);

そこに追加します

  • ユーザーがログインしている場合、データベースから取得したユーザーオブジェクトと氏名
  • 通常1回設定される変数のセット(例:imagesHost
  • 訪問者が切り替えることができる言語のセット
  • 現在の言語
  • 一部の統計情報(例:システム内の合計人数)

これにより、各ビューはログインしたユーザーの名前を表示し、画像の場所、言語のリスト、およびサイトに関するいくつかの全体的な統計を簡単に参照できます。

質問は、コントローラーモデルオブジェクトがすべてのデータを保存するのに最適な場所であるか、ビューがこの情報に簡単にアクセスできるようにするより便利な場所がありますか?

そして第二に、すべてのコントローラーの最初の行として上記のControllerHelper行を持たないことが本当に好きです。実際には常に最初の行であるとは限りません。モデルを埋めるリソースを無駄に使いたくないので、そのコントローラーでリダイレクトする必要があるかどうかを最初に確認することがあります。フィルターや注釈、またはいくつかのSpringコールバックメカニズムにより、ControllerHelperコードが呼び出されることを確認できますafterコントローラーは終了しましたが、正しいbeforeリダイレクトが返された場合、これをスキップしますか?

52
at.

org.springframework.web.servlet.HandlerInterceptor 。 (またはその便利なサブクラス HandlerInterceptorAdapter

@See: Spring Reference章:15.4.1リクエストのインターセプト-HandlerInterceptorインターフェース

メソッドがあります:

void postHandle(HttpServletRequest request,
                HttpServletResponse response,
                Object handler,
                ModelAndView modelAndView) throws Exception;

このメソッドは、コントローラーが実行された後、ビューがレンダリングされる前に呼び出されます。使用して、いくつかのプロパティをModelMapに追加できます

例:

/**
 * Add the current version under name {@link #VERSION_MODEL_ATTRIBUTE_NAME}
 * to each model. 
 * @author Ralph
 */
public class VersionAddingHandlerInterceptor extends HandlerInterceptorAdapter {

    /**
     * The name under which the version is added to the model map.
     */
    public static final String VERSION_MODEL_ATTRIBUTE_NAME =
                "VersionAddingHandlerInterceptor_version";

    /**        
     *  it is my personal implmentation 
     *  I wanted to demonstrate something usefull
     */
    private VersionService versionService;

    public VersionAddingHandlerInterceptor(final VersionService versionService) {
        this.versionService = versionService;
    }

    @Override
    public void postHandle(final HttpServletRequest request,
            final HttpServletResponse response, final Object handler,
            final ModelAndView modelAndView) throws Exception {

        if (modelAndView != null) {
            modelAndView.getModelMap().
                  addAttribute(VERSION_MODEL_ATTRIBUTE_NAME,
                               versionService.getVersion());
        }
    }
}

webmvc-config.xml

<mvc:interceptors>
    <bean class="demo.VersionAddingHandlerInterceptor" autowire="constructor" />
</mvc:interceptors>
57
Ralph

メソッドで@ModelAttributeを使用することもできます。

@ModelAttribute("version")
public String getVersion() {
   return versionService.getVersion();
}

これにより、コントローラー内のすべての要求マッピングに追加されます。これをスーパークラスに入れると、それを拡張するすべてのコントローラーで使用できるようになります。

32
blank

@ControllerAdviceアノテーションが付けられたコントローラークラスを使用できます。

「@ControllerAdviceは、3.2でコントローラのすべてまたはサブセットで共有される@ ExceptionHandler、@ ModelAttribute、および@InitBinderメソッド用に導入されました。」

springOne2GX 2014で記録されたビデオのこの部分をご覧ください http://www.youtube.com/watch?v=yxKJsgNYDQI&t=6m33s

11
mickthompson

@blankのように私のためにこの仕事に答えます:

@ControllerAdvice(annotations = RestController.class)
public class AnnotationAdvice {

    @Autowired
    UserServiceImpl userService;

    @ModelAttribute("currentUser")
    public User getCurrentUser() {
       UserDetails userDetails = (UserDetails) 
       SecurityContextHolder.getContext().getAuthentication().getPrincipal();
       return userService.findUserByEmail(userDetails.getUsername());
}
}
4
badou

@ModelAttributeまたはHandlerInterceptorアプローチを使用すると、リダイレクトで発生する問題が1つあります。 ハンドラーがリダイレクトビューを返すと、この方法で追加されたモデル属性がクエリパラメーターとして追加されます。

この状況を処理する別の方法は、セッションスコープのBeanを作成することです。このBeanは、ベースアプリケーションコントローラーで自動配線するか、アクセスが必要なすべてのコントローラーで明示的に作成できます。

使用可能なスコープと使用法の詳細については、 こちら をご覧ください。

3
qza

すべてのビューがこれらの変数を解決できるグローバル変数を追加する必要がある場合、プロパティまたはマップに定義しないのはなぜですか。次にスプリングDIを使用します。ビューリゾルバーBeanを参照してください。静的検証可能など、非常に便利です。 resUrl

<property name="viewResolvers">
        <list>
            <bean
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
                <property name="viewClass"
                    value="org.springframework.web.servlet.view.JstlView" />
                <property name="attributes" ref="env" />
                <property name="exposeContextBeansAsAttributes" value="false" />
                <property name="prefix" value="${webmvc.view.prefix}" />
                <property name="suffix" value="${webmvc.view.suffix}" />
            </bean>
        </list>
    </property>
1
Arbore