2010-05-17 10 views
19

In Spring MVC posso accedere ai miei bean in JSP utilizzando exposedContextBeanNames (o exposeContextBeansAsAttributes) di JstlView. Ad esempio, quindi, nel mio JSP posso scrivere ($ {properties.myProperty). Ma quando lo stesso JSP fa parte di una vista tessera, queste proprietà non sono accessibili. È possibile configurare correttamente Piastrelle o accedere a queste proprietà in un altro modo?Accesso ai bean Spring da una visualizzazione Tiles (JSP)

Sto utilizzando Spring MVC 3.0.2 e Tiles 2.2.1. Ecco un po 'della mia configurazione:

<bean id="tilesViewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver"> 
    <property name="order" value="1"/> 
    <property name="viewClass" value="org.springframework.web.servlet.view.tiles2.TilesView" /> 
</bean> 

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 
    <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/> 
    <property name="order" value="2"/> 
    <property name="prefix" value="/WEB-INF/views/"/> 
    <property name="suffix" value=".jsp"/> 
    <property name="exposedContextBeanNames"> 
     <list><value>properties</value></list> 
    </property> 
</bean> 

EDIT: Ho implementato la soluzione di Skaffman.

TilesExposingBeansViewResolver.java:

package es.kcsolutions.util.spring.servlet.view; 

import org.springframework.web.servlet.view.*; 

public class TilesExposingBeansViewResolver extends UrlBasedViewResolver { 

    private Boolean exposeContextBeansAsAttributes; 
    private String[] exposedContextBeanNames; 

    public void setExposeContextBeansAsAttributes(boolean exposeContextBeansAsAttributes) { 
     this.exposeContextBeansAsAttributes = exposeContextBeansAsAttributes; 
    } 

    public void setExposedContextBeanNames(String[] exposedContextBeanNames) { 
     this.exposedContextBeanNames = exposedContextBeanNames; 
    } 

    @Override 
    protected AbstractUrlBasedView buildView(String viewName) throws Exception { 
     AbstractUrlBasedView superView = super.buildView(viewName); 
     if (superView instanceof TilesExposingBeansView) { 
      TilesExposingBeansView view = (TilesExposingBeansView) superView; 
      if (this.exposeContextBeansAsAttributes != null) view.setExposeContextBeansAsAttributes(this.exposeContextBeansAsAttributes); 
      if (this.exposedContextBeanNames != null) view.setExposedContextBeanNames(this.exposedContextBeanNames); 
     } 
     return superView; 
    } 

} 

TilesExposingBeansView.java: configurazione

package es.kcsolutions.util.spring.servlet.view; 

import java.util.*; 
import javax.servlet.http.*; 
import org.springframework.web.context.support.ContextExposingHttpServletRequest; 
import org.springframework.web.servlet.view.tiles2.TilesView; 

public class TilesExposingBeansView extends TilesView { 

    private boolean exposeContextBeansAsAttributes = false; 
    private Set<String> exposedContextBeanNames; 

    public void setExposeContextBeansAsAttributes(boolean exposeContextBeansAsAttributes) { 
     this.exposeContextBeansAsAttributes = exposeContextBeansAsAttributes; 
    } 

    public void setExposedContextBeanNames(String[] exposedContextBeanNames) { 
     this.exposedContextBeanNames = new HashSet<String>(Arrays.asList(exposedContextBeanNames)); 
    } 

    protected HttpServletRequest getRequestToExpose(HttpServletRequest originalRequest) { 
     if (this.exposeContextBeansAsAttributes || this.exposedContextBeanNames != null) 
     return new ContextExposingHttpServletRequest(originalRequest, getWebApplicationContext(), this.exposedContextBeanNames); 
     return originalRequest; 
    } 

    @Override 
    protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception { 
     HttpServletRequest requestToExpose = getRequestToExpose(request); 
     exposeModelAsRequestAttributes(model, requestToExpose); 
     super.renderMergedOutputModel(model, requestToExpose, response); 
    } 

} 

Primavera:

<bean id="tilesViewResolver" class="es.kcsolutions.util.spring.servlet.view.TilesExposingBeansViewResolver"> 
     <property name="order" value="1"/> 
     <property name="viewClass" value="es.kcsolutions.util.spring.servlet.view.TilesExposingBeansView"/> 
     <property name="exposedContextBeanNames"> 
      <list><value>properties</value></list> 
     </property> 
    </bean> 

Se avete qualche problema, dare un'occhiata a TilesExposingBeansView.renderMergedOutputModel. Ho fatto alcuni test, ma forse è necessario fare molto di più.

+0

google per l'integrazione con le tessere primaverili? – Bozho

+0

Sì, ho cercato su Google. Ho alcuni problemi con le versioni precedenti, ma ora era tutto ok, tranne per questo problema. L'ho cercato ma non ho trovato nulla :( – sinuhepop

+2

l'uomo, la primavera e l'apache devono scriverti un assegno per questo;) ottimo lavoro – Ricardo

risposta

12

Come avete notato, questa funzionalità fa parte di InternalResourceViewResolver e InternalResourceView, mentre la roba Tiles eredita direttamente da UrlBasedViewResolver e AbstractUrlBasedView, quindi non si può fare uso di esso.

Guardando il codice, non c'è motivo per cui questa roba non possa essere stata inserita in AbstractUrlBasedView. La magia avviene in InternalResourceView.getRequestToExpose e sembra perfettamente applicabile anche a AbstractUrlBasedView.

A breve termine, suggerisco sottoclassi UrlBasedViewResolver e TilesView, copiando la roba getRequestToExpose da InternalResourceView. A lungo termine, ti incoraggio a presentare un problema con SpringSource chiedendo loro di spostare questa funzionalità nella gerarchia delle classi in AbstractUrlBasedView, rendendola più ampiamente disponibile.

+0

Ho provato qualcosa di simile, ma non funziona. Ho sottoclasse JstlView, sovrascrivendo initServletContext, checkResource e renderMergedOutputModel. Proverò la tua idea ora. – sinuhepop

+0

@Sinuhe: 'JstlView' non sarà compatibile con Piastrelle, i meccanismi sono fondamentalmente diversi. – skaffman

+0

Bene, la soluzione ha funzionato! Mentre lo stavo facendo, ho notato che la mia precedente idea non era corretta. Ho provato un po 'di più prima di presentare un problema a SpringSource. Grazie! – sinuhepop

1

A partire dalla primavera 3.0 c'è ora un TilesViewResolver.

Convenienza sottoclasse di UrlBasedViewResolver che supporta TilesView (cioè le definizioni piastrelle) e sottoclassi personalizzate di esso.

La classe di visualizzazione per tutte le viste generate da questo resolver può essere specificata tramite la proprietà "viewClass". Vedi UrlBasedViewResolver's javadoc per i dettagli.

Nota: quando il concatenamento ViewResolvers, un TilesViewResolver controllerà per l'esistenza delle risorse modello specificato e restituire solo un non-null oggetto View se il modello è stato effettivamente trovato.

Da: 3.0 Autore: Juergen Hoeller

+1

TilesViewResolver non risolve il problema poiché sottoclasse UrlBasedViewResolver senza aggiungere la proprietà exposedContextBeanNames. Il post originale e la risposta accettata sono ancora il modo migliore per andare su AFAIK. – azpublic

13

Hai provato a utilizzare ServletContextAttributeExporter nel file di configurazione XML?

<bean 
    class="org.springframework.web.context.support.ServletContextAttributeExporter"> 
    <property name="attributes"> 
     <map> 
      <entry key="<bean key here>"> 
       <ref bean="<bean name here" /> 
      </entry> 
     </map> 
    </property> 
</bean> 
+2

Lo uso perché è più semplice da implementare. – msangel

+0

Certamente questo è il metodo più elegante e discreto di aggiungere i bean di sessione! Stavo per estendere le Spring Classes, la tua soluzione mi ha salvato diversi giorni di lavoro! GRAZIE ! –

+0

Questo è ** fantastico. ** – user3120173