2011-01-10 19 views
14

Ho un menu basato sui dati (memorizzato nella cache) ed è un componente globale. Voglio essere in grado di iniettare le voci del menu per ogni richiesta poiché ogni pagina lo userà. Qual è il posto migliore per metterlo? Sto usando l'annotazione basata su Spring3. La soluzione migliore che posso immaginare è l'utilizzo di OncePerRequestFilter e l'aggiunta di esso o la sottoclassificazione del controller, ma non sono sicuro di come farlo con l'annotazione @Controller.Quali sono le migliori pratiche in merito all'impostazione degli attributi del modello globale in Spring MVC?

risposta

13

posso pensare a due semplici opzioni:

Ogni classe @Controller espone i dati come un metodo annotato con @ModelAttribute , per esempio

@ModelAttribute 
public MyData getMyData() { 
    ... 
} 

Questo non è davvero bello se si hanno più controller, però. Inoltre, questo ha il fastidioso effetto collaterale della codifica dello myData sull'URL per ogni reindirizzamento

Suggerisco invece di implementare uno HandlerInterceptor e di esporre i dati ad ogni richiesta in questo modo. Non è possibile utilizzare alcuna annotazione-lovin, ma è meglio separato dalla logica aziendale in questo modo. Questo è simile alla tua idea OncePerRequestFilter, ma a più Spring-y.

+3

+1 per menzionare l'effetto collaterale di ModelAttribute. Vorrei che qualcuno me lo avesse detto prima :(Grazie per la direzione: –

7

Starting Spring 3.2, è possibile utilizzare @ControllerAdvice anziché utilizzare @ExceptionHandler, @InitBinder e @ModelAttribute in ciascun controller. Saranno applicati a tutti i bean @Controller.

import org.springframework.beans.propertyeditors.StringTrimmerEditor; 
import org.springframework.web.bind.WebDataBinder; 
import org.springframework.web.bind.annotation.ControllerAdvice; 
import org.springframework.web.bind.annotation.InitBinder; 
import org.springframework.web.context.request.WebRequest; 

@ControllerAdvice 
public class GlobalBindingInitializer { 
    @InitBinder 
    public void registerCustomEditors(WebDataBinder binder, WebRequest request) { 
    binder.registerCustomEditor(String.class, new StringTrimmerEditor(true)); 
    } 
} 

Se tu avessi iniziato con la Primavera Roo Codice generato, o limitare le annotazioni scanditi dal componente-scan utilizzando include-filtro, quindi aggiungere il filtro richiesto in webmvc-config.xml

<!-- The controllers are autodetected POJOs labeled with the @Controller annotation. --> 
<context:component-scan base-package="com.sensei.encore.maininterface" use-default-filters="false"> 
    <context:include-filter expression="org.springframework.stereotype.Controller" type="annotation"/> 
    <!-- ADD THE BELOW LINE --> 
    <context:include-filter expression="org.springframework.web.bind.annotation.ControllerAdvice" type="annotation"/> 
</context:component-scan> 
+0

Potrebbe anche essere utile link su '@ ControllerAdvice' in' Spring 4': http://blog.codeleak.pl/2013/11/controlleradvice- miglioramenti-in-spring.html – Andremoniy

0

Se è necessario aggiungere alcune variabili globali che ogni vista può risolvere queste variabili, perché non definire in una proprietà o mappa? Quindi utilizzare la molla DI, fare riferimento al bean resolver di visualizzazione. è molto utile, come veriable statico, ad es. 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> 
Problemi correlati