2010-08-08 8 views
5

Una delle cose che mi ha sempre infastidito su <jsp:include..> è che non è possibile passare valori non String nella pagina inclusa come input distinti alla pagina. Ad esempio, vorrei essere in grado di effettuare le seguenti operazioni:jsp Enchanced: include implementazione

<c:forEach var="item" items="${listOfItems}"> 
    <jsp:include page="mypage.jsp"> 
     <jsp:attribute name="item" value="${item}/> 
    </jsp:include> 
</c:forEach> 

L'idea è che, dichiarando l'elemento essendo passata come attributo all'interno della jsp: include nodo, il codice sta rendendo chiaro quale era l'intento ... di fornire quel parametro alla pagina inclusa.

L'unico meccanismo attualmente disponibile per farlo è definire l'attributo "globalmente", quindi lasciare che la pagina inclusa lo legga dallo spazio globale. Sfortunatamente, questo perde lo stesso "intento" che utilizza il jsp <: il parametro > fornisce. Inoltre, rende il codice più difficile da eseguire il debug, per la stessa ragione per cui sono presenti globals in qualsiasi ambiente di programmazione.

Qualcuno sa di un'implementazione di un meccanismo di inclusione che esegue le funzioni di jsp: include, ma consente di passare valori non stringa? O, in caso contrario, sarei aperto a idee alternative che preservino lo stesso obiettivo di intento e facilità di debug.

Come nota a margine, mi piacerebbe vedere un meccanismo integrato "catturare" per quando il pagina inclusa genera un errore:

<abc:include page="mypage"> 
    <abc:param name="something" value="some string value"/> 
    <abc:attribute name="somethingelse" value="${nonStringValue}"/> 
    <abc:catch var="ex"> 
     The page failed, so the content it generated will not be sent to the output 
     stream. Instead, we can collapse the part of the page that it's content 
     would be... possibly putting a comment in the page with 
     <!-- There was an exception generating this module: 
      <c:out value="${ex.getMessage}/> 
      --> 
    </abc:catch> 
</abc:include> 

risposta

1

Dopo aver letto le risposte qui, oltre a fare ulteriori ricerche su questo argomento, mi è venuta in mente la seguente:

  • È possibile serializzare gli oggetti poi deserializzare in JSP incluso.Non ne è un fan perché rende il codice più complesso (ogni oggetto che si passa deve essere serializzabile, ecc.)
  • È possibile utilizzare taglibs. Non ne sono un fan, dal momento che ritengo che abbiano un ruolo diverso rispetto ai file JSP inclusi
  • È possibile definire le variabili nell'ambito della richiesta, che le renderà disponibili per il JSP incluso. Non è un grande fan di questo dato che non mostra l'intento del programmatore (passando i valori alla pagina inclusa, perché è solo un uso).
  • Non c'è davvero (che potrei trovare) un'implementazione che ottenga quello che sto cercando, ma è possibile costruire qualcosa che si avvicini tramite tag personalizzati.

Ho fatto un po 'di lavoro e messo insieme il codice per ottenere quello che stavo cercando, e quindi threw it up on sourceforge. Esso consente di specificare gli ingressi nel modo in cui mi descrivevo:

<inc:include page="normal.jsp"> 
    <inc:param name="param1" value="param1value" /> 
    <inc:param name="param2" value="param2value" /> 
    <inc:attrib name="attrib1" value="${attrib1value}" /> 
    <inc:attrib name="attrib2" value="${attrib2value}" /> 
    <inc:catch var="ex"> 
     This block was not rolled up because there wasn't an error. 
     Should never see this, but just in case, the exception was: ${ex.message} 
    </inc:catch> 
</inc:include> 

L'unico problema con esso (in questo momento) è che aggiungo gli attributi per la portata richiesta prima che la pagina è incluso, quindi rimuoverli dopo (o ripristinarli se esistessero già). Quello che mi piacerebbe fare, invece, è di avvolgere l'oggetto richiesta e sovrascrivere i metodi degli attributi per includere automaticamente i valori passati in ... Ci sto ancora lavorando.

+0

Quindi, mi sento male segnando la mia risposta come "la risposta", ma davvero non ho ottenuto quello che cercavo altrove. Sono state fornite informazioni utili, ma ho finito per doverle combinare e usarlo per sviluppare la mia implementazione. – RHSeeger

1

allows for passing in non-String values?

Quando si sono limitati a passare le stringhe in giro, un soluzione comune è serializzare i tuoi oggetti.

4

Dalla specifica JSTL:

Nested scoped variables are only visible within the body of the action and are stored in "page" scope.

è possibile passare i riferimenti agli oggetti tramite richiesta portata.

standardInclude.jsp:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> 
<c:out value="${foo}" /> 

standardAction.jsp:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> 
<% 
    //evil scriptlet 
    request.setAttribute("mylist", java.util.Arrays.asList("bar", "baz")); 
%> 
<c:forEach items="${mylist}" var="foo"> 
    <c:set var="foo" scope="request" value="${foo}" /> 
    <jsp:include page="standardInclude.jsp" /> 
    <c:set var="foo" scope="request" value="${null}" /> 
</c:forEach> 

È possibile utilizzare il tag catch per intercettare le eccezioni.

thrower.jsp:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> 
<c:out value="OK: ${foo}" /> 
<% 
    //evil scriptlet 
    if ("bar".equals(request.getAttribute("foo"))) 
    throw new java.io.IOException("oops"); 
%> 

catcher.jsp:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> 
<% 
    //evil scriptlet 
    request.setAttribute("mylist", java.util.Arrays.asList("bar", "baz")); 
%> 
<c:forEach items="${mylist}" var="foo"> 
    <br /> 
    <c:set var="foo" scope="request" value="${foo}" /> 
    <c:catch var="ex"> 
     <jsp:include page="thrower.jsp" /> 
    </c:catch> 
    <c:if test="${ex ne null}"> 
     <c:out value="Error for ${foo}" /> 
    </c:if> 
    <c:set var="foo" scope="request" value="${null}" /> 
</c:forEach> 

Questo emetterà:

Error for bar 
OK: baz 
+0

Mentre concordo sul fatto che l'ambito della richiesta si muove in parte verso "ambito globale meno", rende comunque la variabile disponibile ad un ambito più ampio di quello che deve essere (cioè, il livello di pagina corrente piuttosto che la pagina inclusa livello). Inoltre, risolve il problema di intenti ... non mostra che stai specificatamente passando la variabile nella pagina inclusa. Sul fronte delle catture, sono d'accordo che è un'opzione, ma è brutto è tutto. L'intero meccanismo di cattura in jsp, sebbene utile, è in qualche modo meno che pulito. – RHSeeger

+0

Impostando il binding dello scope di richiesta su null dopo l'inclusione, si limita la sua visibilità. Quello che stai chiedendo è di espandere l'ambito di una variabile da una pagina all'altra. I JSP definiscono un numero finito di ambiti: pagina, param, richiesta, sessione e applicazione. A meno che non vogliate entrare in 'ThreadLocal's (un'altra lattina di worm), questo è il massimo. Un'esecuzione personalizzata per Ogni implementazione dovrebbe scegliere una di queste opzioni. Raccomando di guardare il codice Java generato dai traduttori JSP. Ti darà un'idea migliore del problema che stai cercando di affrontare. – McDowell

+0

Quello che mi interessa è uno scope che rende visibile la variabile per (dove X include Y) in Y ma non in X. Tuttavia, voglio che X dica "questo sarà visibile in Y", come fa per params quando include Y. "sembra" come dovrebbe essere possibile, dal momento che il meccanismo di inclusione deve creare un contesto per Y (il JSP incluso) da eseguire. Il problema è che lo "standard" include-> requestdispatch doesn permettere questo. Come tale, speravo ci fosse un tag di inclusione personalizzato (usando un RequestDispatcher personalizzato) che lo facesse. – RHSeeger

0

Questo può essere achived con tag jsp file invece che include. Vedere la mia risposta a una domanda simile a JSP Component Creation per i dettagli.

+0

Mentre è vero che i file di tag possono avere oggetti passati come attributi, hanno uno scopo diverso dai file JSP. Specialmente quando il JSP che viene incluso diventa più grande, spostarlo in un tag sembra sconfiggere l'obiettivo originale di trasmettere l'intento del programmatore. – RHSeeger

+0

@RHSeger, il tuo commento non mi è del tutto chiaro, ma penso che in questo tuo primo esempio un file di tag sarebbe una soluzione migliore. Io uso include per il contenuto prevalentemente statico che viene utilizzato in più pagine. I file di tag d'altra parte sono utili per il contenuto variabile in base ai loro parametri, che vengono poi utilizzati anche più volte sulla stessa pagina. –

+0

Ignora l'esempio che ho posto in modo specifico e suppongo che stia chiamando a un JSP e che debba passare oggetti reali anziché stringhe. Da lì, il JSP incluso potrebbe includere altri JSP, ecc. Un file di tag, a mio avviso, è usato di più per componenti piccoli e modulari che sono autonomi. C'è qualche possibilità che tu possa indicarmi un articolo/descrizione dei file di tag in modo più dettagliato? – RHSeeger