2010-08-08 43 views
5

Una de las cosas que siempre me ha molestado acerca de <jsp:include..> es que no es posible pasar valores que no sean cadenas a la página incluida como entradas distintas a la página. Por ejemplo, me gustaría ser capaz de hacer lo siguiente:jsp modificado: incluir implementación

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

La idea es que, al declarar el elemento que se pasa como un atributo dentro de la jsp: include nodo, el código está haciendo más clara cuál era el intento ... de suministrar ese parámetro a la página incluida.

El único mecanismo actualmente disponible para hacer esto es definir el atributo "globalmente" y luego dejar que la página incluida lo lea desde el espacio global. Desafortunadamente, esto pierde el mismo "intento" que el que proporciona < jsp: param >. Además, hace que el código sea más difícil de depurar, por la misma razón que lo hacen los globales en cualquier entorno de programación.

¿Alguien sabe de una implementación de un mecanismo de inclusión que realiza las funciones de jsp: incluir, pero permite pasar en valores que no sean cadenas? O, si no, estaría abierto a ideas alternativas que conserven el mismo objetivo de intento y facilidad de depuración.

Como nota al margen, me gustaría ver un mecanismo incorporado "captura" para cuando la página incluida genera un error:

<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> 

Respuesta

1

Después de leer las respuestas aquí, además de hacer la investigación adicional sobre el tema, se me ha ocurrido con lo siguiente:

  • Puede serializar los objetos a continuación, deserializar en la JSP incluido.No es un fanático de esto porque hace que el código sea más complejo (cada objeto que pasa debe ser serializable, etc.)
  • Puede usar taglibs. No soy partidario de esto, ya que creo que cumplen una función diferente a JSP. Incluir archivos
  • Puede definir las variables en el alcance de la solicitud, lo que las pondrá a disposición del JSP incluido. No es un gran admirador de esto ya que no muestra la intención del programador (al pasar los valores a la página incluida, ya que solo se usa).
  • Realmente no hay (que pude encontrar) una implementación que logre lo que estoy buscando, pero es posible construir algo que se aproxime a través de etiquetas personalizadas.

Hice un poco de trabajo y armé el código para lograr lo que estaba buscando, y luego threw it up on sourceforge. Se le permite especificar las entradas en la forma en que estaba describiendo:

<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> 

El único problema con él (en este momento) es que agrego los atributos para el ámbito de la petición antes de que se incluyó a la página, luego eliminarlos después (o reinícielos si ya existían). Lo que me gustaría hacer, en cambio, es ajustar el objeto de solicitud en su lugar y anular los métodos de atributo para incluir automáticamente los valores pasados ​​... Todavía estoy trabajando en eso.

+0

Entonces, me siento mal al marcar mi propia respuesta como "la respuesta", pero realmente no obtuve lo que estaba buscando en otro lado. Se proporcionó información útil, pero terminé teniendo que combinarla y usarla para desarrollar mi propia implementación. – RHSeeger

1

allows for passing in non-String values?

Cuando usted está restringido a pasar las cadenas alrededor, una La solución común es serializar sus objetos.

4

De la especificación JSTL:

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

se puede pasar a través de referencias a objetos solicitud ámbito de aplicación.

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> 

Usted puede utilizar la etiqueta catch capturar excepciones.

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> 

Esta emitirá:

Error for bar 
OK: baz 
+0

Aunque estoy de acuerdo en que el alcance de la solicitud se mueve hacia un "alcance menos global", todavía hace que la variable esté disponible en un ámbito mayor del necesario (es decir, el nivel de página actual en lugar de la página incluida nivel). Además, aborda el problema del intento ... no muestra que está pasando específicamente la variable a la página incluida. En el frente de la captura, estoy de acuerdo en que es una opción, pero es feo, eso es todo. Todo el mecanismo de captura en jsp, aunque es útil, es algo menos que limpio. – RHSeeger

+0

Al establecer el enlace del alcance de la solicitud de nuevo a nulo después de la inclusión, está limitando su visibilidad. Lo que está pidiendo es ampliar el alcance de una variable de una página a otra. Las JSP definen un número finito de ámbitos: página, parámetro, solicitud, sesión y aplicación. A menos que quieras entrar en 'ThreadLocal's (otra lata de gusanos), esto es lo mejor posible. Una costumbre para cada implementación debería elegir una de estas opciones. Recomiendo ver el código Java generado por los traductores JSP. Te dará una mejor idea del problema que intentas abordar. – McDowell

+0

Lo que me interesa es un alcance que haga que la variable sea visible para (donde X incluye Y) en Y pero no en X. Sin embargo, quiero que X diga "esto será visible en Y", del mismo modo que lo hace para los parámetros cuando incluye Y. "Parece" que esto debería ser posible, ya que el mecanismo de inclusión necesita crear un contexto para Y (el JSP incluido) para ejecutar. El problema es que el "estándar" incluye-> requestdispatch doesn no permitas esto Como tal, esperaba que hubiera una etiqueta de inclusión personalizada (utilizando un RequestDispatcher personalizado) que hiciera esto. – RHSeeger

0

Esto se puede achived con etiquetas JSP archivos en lugar de incluye. Vea mi respuesta a una pregunta similar en JSP Component Creation para más detalles.

+0

Si bien es cierto que los archivos de etiquetas pueden tener objetos pasados ​​como atributos, tienen un propósito diferente al de los archivos JSP. Especialmente a medida que el JSP que se incluye se hace más grande, moverlo a una etiqueta parece frustrar el objetivo original de transmitir la intención del programador. – RHSeeger

+0

@RHSeger, su comentario no está del todo claro para mí, pero creo que en este su primer ejemplo, un archivo de etiqueta sería una mejor solución. Uso inclusiones para contenido principalmente estático que se usa en varias páginas. Los archivos de etiquetas, por otro lado, son útiles para el contenido variable en función de sus parámetros, que luego también se usan varias veces en la misma página. –

+0

Ignore el ejemplo que planteé específicamente y suponga que estoy llamando a un JSP y necesito pasar objetos reales en lugar de cadenas. A partir de ahí, el JSP incluido puede incluir otros JSP, etc. Un archivo de etiqueta, desde mi punto de vista, se usa más para componentes pequeños y modulares que son autónomos. ¿Hay alguna posibilidad de que pueda señalarme un artículo/descripción de los archivos de etiquetas con más detalle? – RHSeeger

Cuestiones relacionadas