2010-02-02 20 views
32

Me han dicho que el uso de scriptlets (<% = ...%>) en mis páginas JSP no es una gran idea.¿Cómo evitar el uso de scriptlets en mi página JSP?

¿Alguien con un poco más de experiencia java/jsp por favor dame algunos consejos sobre cómo cambiar este código para que sea más 'mejor práctica', sea lo que sea?

Esta JSP es en realidad mi página de decorador principal de sitemesh. Básicamente, mi diseño web tiene una pestaña y un submenú, y deseo resaltar de algún modo la pestaña actual y mostrar el submenú correcto mirando el URI de solicitud actual.

<%@ taglib uri="http://www.opensymphony.com/sitemesh/decorator" prefix="decorator" %> 

<html> 
<head> 
    <title>My Events - <decorator:title /></title> 
    <link href="<%= request.getContextPath() %>/assets/styles.css" rel="stylesheet" type="text/css" /> 
</head> 
<body> 

<div class="tabs"> 
    <a 
    <%= request.getRequestURI().contains("/events/") ? "class='selected'" : "" %> 
    href='<%= request.getContextPath() %>/events/Listing.action'>Events</a> 
    <a 
    <%= request.getRequestURI().contains("/people/") ? "class='selected'" : "" %> 
    href='<%= request.getContextPath() %>/people/Listing.action'>People</a> 
</div> 

<div class="submenu"> 
    <% if(request.getRequestURI().contains("/events/")) { %> 
    <a href="Listing.action">List of Events</a> 
    |<a href="New.action">New Event</a> 
    <% } %> 
    <% if(request.getRequestURI().contains("/people/")) { %> 
    <a href="Listing.action">List of People</a> 
    |<a href="New.action">New Person</a> 
    <% } %> 
    &nbsp; 
</div> 

<div class="body"> 
    <decorator:body /> 
</div> 

</body> 
</html> 

Gracias todos

+0

Como un aparte, es '<% = request.getContextPath()%>' un uso aceptable de scriptlets que no está mal visto tanto? – Chris

+0

Deberías comenzar a usar facelets para crear plantillas. Te obliga a codificar correctamente. –

+0

¿Estás diciendo usar facelets en lugar de sitemesh? – Chris

Respuesta

40

Creo que ayuda más si se ve con su propio Ojos que en realidad se puede hacer por completo sin scriptlets.

Aquí es una reescritura 1 a 1 con ayuda de, entre otros JSTL (simplemente introduce jstl-1.2.jar en /WEB-INF/lib) core y functions taglib:

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> 
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %> 

<html> 
<head> 
    <title>My Events - <decorator:title /></title> 
    <link href="${pageContext.request.contextPath}/assets/styles.css" rel="stylesheet" type="text/css" /> 
</head> 
<body> 

<div class="tabs"> 
    <a 
    ${fn:contains(pageContext.request.requestURI, '/events/') ? 'class="selected"' : ''} 
    href="${pageContext.request.contextPath}/events/Listing.action">Events</a> 
    <a 
    ${fn:contains(pageContext.request.requestURI, '/people/') ? 'class="selected"' : ''} 
    href="${pageContext.request.contextPath}/people/Listing.action">People</a> 
</div> 

<div class="submenu"> 
    <c:if test="${fn:contains(pageContext.request.requestURI, '/events/')}"> 
    <a href="Listing.action">List of Events</a> 
    |<a href="New.action">New Event</a> 
    </c:if> 
    <c:if test="${fn:contains(pageContext.request.requestURI, '/people/')}"> 
    <a href="Listing.action">List of People</a> 
    |<a href="New.action">New Person</a> 
    </c:if> 
    &nbsp; 
</div> 

Aquí es una reescritura más optimizada, tenga en cuenta que he usado c:set a "caché" resultados de expresión para reutilizar y que utilizo la etiqueta HTML <base> para evitar poner la ruta de contexto en cada enlace (basta con hacer todas las direcciones URL relativas en su página web sin la barra inclinada):

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> 
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %> 

<c:set var="isEvents" value="${fn:contains(pageContext.request.requestURI, '/events/')}" /> 
<c:set var="isPeople" value="${fn:contains(pageContext.request.requestURI, '/people/')}" /> 

<html> 
<head> 
    <title>My Events - <decorator:title /></title> 
    <base href="${pageContext.request.contextPath}"> 
    <link href="assets/styles.css" rel="stylesheet" type="text/css" /> 
</head> 
<body> 

<div class="tabs"> 
    <a ${isEvents ? 'class="selected"' : ''} href="events/Listing.action">Events</a> 
    <a ${isPeople ? 'class="selected"' : ''} href="people/Listing.action">People</a> 
</div> 

<div class="submenu"> 
    <c:if test="${isEvents}"> 
    <a href="Listing.action">List of Events</a>|<a href="New.action">New Event</a> 
    </c:if> 
    <c:if test="${isPeople}"> 
    <a href="Listing.action">List of People</a>|<a href="New.action">New Person</a> 
    </c:if> 
    &nbsp; 
</div> 

En realidad, se puede optimizar más si recoja todos esos valores "codificados" como events y people y vincular los textos en un Map en el ámbito de la aplicación y el uso de cada uno bajo la JSTL <c:forEach> para mostrar las fichas.

En cuanto a su pregunta real , se puede desactivar scriptles (y obtener los errores de ejecución acerca de su uso), añadiendo la siguiente entrada en aplicación web de web.xml. Puede ayudar a detectar los scriptlets supervisados.

<jsp-config> 
    <jsp-property-group> 
     <url-pattern>*.jsp</url-pattern> 
     <scripting-invalid>true</scripting-invalid> 
    </jsp-property-group> 
</jsp-config> 

Para obtener más información sobre EL, comprobar el Java EE tutorial part II chapter 5. Los objetos EL implícitos, como ${pageContext} se describen here. Para obtener más información sobre JSTL, consulte el Java EE tutorial part II chapter 7. Tenga en cuenta que JSTL y EL son dos cosas separadas. JSTL es taglib estándar y EL solo permite acceder a los datos de back-end mediante programación. Aunque normalmente se usa en taglibs como JSTL, también se puede usar de forma independiente en el texto de la plantilla.

+5

Si compara las plantillas "antes" y "después", verá que son prácticamente iguales. No veo cómo este último es automáticamente mejor que el anterior (además de verse un poco más limpio). – Ree

+3

@Ree - Honestamente, creo que el mayor activo de JSTL es que no le da la libertad de escribir cualquier código que le venga a la mente en su JSP. JSTL le brinda la mayoría de las herramientas que necesita para escribir plantillas, no controladores, gerentes de lógica de negocios u objetos de acceso a datos. – RustyTheBoyRobot

2

Tendrá que utilizar algún framework de desarrollo web. O al menos algún taglib conveniente. O un enginge de plantillas como FreeMarker.

marcos del anuncio:

Si te gusta la forma en JSP de codificación, a continuación, me gustaría sugerir Struts 2.

<s:if test="%{false}"> 
    <div>Will Not Be Executed</div> 
</s:if> 
<s:elseif test="%{true}"> 
    <div>Will Be Executed</div> 
</s:elseif> 
<s:else> 
    <div>Will Not Be Executed</div> 
</s:else> 

Luego está JSF orientado a componentes.

Si te gusta la programación orientada a objetos y la codificación todo en Java, intente Apache Wicket (mi favorito) o Google Web Toolkit.

+0

Estoy usando struts2 si eso ayuda. – Chris

+0

Bueno, ahora combínelo con las bibliotecas de etiquetas como JSTL sugeridas por Vincent, y no tiene scriptlets. Vea aquí: http://struts.apache.org/2.1.8.1/docs/tag-reference.html y allí encontrará, entre otros, http://struts.apache.org/2.1.8.1/docs /text.html –

3

Es posible que desee comenzar utilizando bibliotecas de etiquetas. Puede usar la biblioteca de etiquetas estándar JSTL para hacer la mayoría de las cosas comunes para las que necesita los scriplets. Hay muchas otras bibliotecas de etiquetas más ricas que se utilizan como en el marco struts2 o de apache.

p. Ej.

<c:if test="${your condition}"> 
     Your Content 
    </c:if> 

reemplazará sus declaraciones if.

3

La alternativa preferida a los scriptlets es el lenguaje de expresión JSTL; here es una buena descripción. Tendrá que añadir el taglib de este modo:

<%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c' %> 

A modo de ejemplo, JSTL proporciona un montón de objetos implícitos que le dan las cosas que necesita; el que quiere es pageContext.request.

Para que pueda reemplazar <%request.getRequestURI%> con ${pageContext.request.requestURI}.

Puede hacer condicionales usando etiquetas <c:if>.

+0

JSTL! = Lenguaje de expresión. JSTL es un taglib estándar http://java.sun.com/products/jsp/jstl/1.1/docs/tlddocs/ Expression Language son esas cosas '$ {}' http://java.sun.com/javaee/5 /docs/tutorial/doc/bnahq.html – BalusC

+1

Para referencia futura: he tenido más suerte con 'http://java.sun.com/jsp/jstl/core' en mi taglib uri (en lugar de http: // java.sun.com/jstl/core) – Chris

+0

El/jsp/-less uri es de hecho parte de una década de antigüedad JSTL 1.0. No lo uses – BalusC

9

Como un lado, ¿es <%= request.getContextPath() %> un uso aceptable de scriptlets que no está mal visto tanto?

Esto puede ser una opinión impopular, pero si todo lo que haces son simples condicionales e inserciones de texto, no puedo encontrar muchas fallas en el uso de scriptlets.(Tenga en cuenta el si)

probablemente me utilizo JSTL y el lenguaje de expresión, pero sobre todo porque puede ser inferior a escribir, y el apoyo IDE puede ser mejor (pero un buen JSP IDE también puede encontrar falta de cierre y soportes cosas como esas).

Pero fundamentalmente (como en "mantener la lógica de las plantillas") no veo ninguna diferencia entre

<% if(request.getRequestURI().contains("/events/")) { %> 

y

${fn:contains(pageContext.request.requestURI, '/events/') 
+3

Ok genial! ¡Pensé que era el único con esta opinión! – Chris

+0

Creo que el contexto aquí es una de las mejores prácticas que entra en juego más cuando no eres el único que desarrolla o mantiene una plantilla. Aunque funcionalmente, no hay diferencia en su ejemplo, ha establecido la prioridad de usar scriptlets y alguien que no sabe mejor puede incluir algún código de Java que cambie el estado de un modelo. Solo algo a considerar. Me gusta la idea de deshabilitarlos como BalusC mencionado anteriormente. –

6

Esta no es una respuesta directa a su pregunta (y ya hay varios buenos, así que no voy a tratar de añadir a ella), pero se hizo mención:

¿Puede alguien con una un poco más de experiencia java/jsp por favor dame algunos punteros en cuanto a cómo cambiar este código así que es más 'mejor práctica', cualquiera sea que puede ser?

En mi opinión, las mejores prácticas, con respecto a JSP, es que debe utilizarse estrictamente como un motor de plantillas , y no más (es decir, sin la lógica de negocio en ese país).Usar JSTL, como muchos señalaron, definitivamente te ayuda a llegar, pero incluso con JSTL, es fácil hacer mucho en un JSP.

Personalmente me gusta seguir las reglas establecidas en Enforcing Strict Model-View Separation in Templating Engines por Terence Parr cuando desarrollo en JSP. El documento menciona el propósito de las plantillas de motores (separando el modelo y la vista) y las características de un buen motor de plantillas. Da un buen vistazo a JSP y señala formas en que no es un buen motor de plantillas. No es sorprendente que JSP sea básicamente demasiado poderoso y permita a los desarrolladores hacer demasiado. Recomiendo leer este documento, y lo ayudará a restringirse a las partes "buenas" de JSP.

Si leen sólo una sección en ese documento, lea el Capítulo 7, que incluye las siguientes reglas:

  1. la vista no puede modificar el modelo, ya sea mediante la alteración directa modelo objetos de datos o invocando métodos en el modelo que causa efectos secundarios. Es decir, una plantilla puede acceder a los datos desde el modelo e invocar métodos, pero tales referencias deben ser de efecto secundario gratuitas. Esta regla surge parcialmente porque las referencias de datos deben ser insensibles a la orden. Ver la Sección 7.1.
  2. la vista no puede realizar cálculos en los datos dependientes valores porque los cálculos puede cambio en el futuro y deben pueden encapsular de forma ordenada en el modelo en cualquier caso. Por ejemplo, la vista no puede calcular los precios de venta de libros como "$ price * .90". Para ser independiente del modelo , la vista no puede hacer suposiciones sobre el significado de los datos.
  3. la vista no se puede comparar valores de datos dependiente de, pero puede probar la propiedades de los datos tales como presencia/ausencia o la longitud de un valor datos de valores múltiples. Las pruebas como $ bloodPressure < 120 deben trasladarse al modelo , ya que a los médicos les gusta mantener reduciendo la presión sistólica máxima con nosotros. Las expresiones en la vista deben ser reemplazados con una prueba para detectar la presencia de un valor simulat- ing un booleano como $ bloodPressureOk! = Salida de plantilla nulo puede estar condicionada a los datos del modelo y computaciones, el condicional solo tiene para ser computado en el modelo. Incluso pruebas simples que hacen que los valores negativos rojo se computen en el modelo; el nivel adecuado de abstracción es no baja de aliado algo más alto nivel, como “x departamento está perdiendo dinero.”
  4. la vista no puede hacer suposiciones de tipos de datos. Algunos supuestos de tipos son obvia cuando el punto de vista asume un valor de datos es una fecha, por ejemplo, pero más sutiles supuestos de tipo pera AP: Si una plantilla asume $ ID de usuario es un número entero , la gramática pro no puede cambie este valor para que sea no numérico en el modelo sin romper la plantilla .Esta regla prohíbe la matriz indexing como colorCode [$ topic] y $ name [$ ID] La vista no puede llamar a métodos de llamada con argumentos porque (estática o dinámicamente) hay un tipo de argumento supuesto, a menos uno podría garantizar que el método modelo simplemente los trata como objetos. Además de los diseñadores gráficos no son programadores; esperando que invoquen los métodos y sepan qué pasar es poco realista.
  5. los datos del modelo no deben contener información de visualización o diseño. El modelo no puede pasar ninguna información de la pantalla a la vista disfrazada como valores de datos. Esto incluye no pasar el nombre de una plantilla para aplicar a otros valores de datos.

Por cierto, Terence ha creado su propio motor de plantillas llamado String Template que supuestamente hace un muy buen trabajo de hacer cumplir estas normas. No tengo experiencia personal con él, pero me encantaría verificarlo en mi próximo proyecto.

6

Los scriptlets no son lo peor del mundo. Una consideración importante es pensar quién mantendrá el código. Si sus diseñadores web no tienen mucha experiencia en Java, probablemente sea mejor que vaya con las bibliotecas de etiquetas. Sin embargo, si los desarrolladores de Java están haciendo el mantenimiento, puede ser más fácil para ellos ir con scriptlets.

Si termina usando una biblioteca de etiquetas y JSTL, espera que el mantenedor también aprenda la biblioteca de etiquetas y conozca JSTL. Algunos desarrolladores estarán de acuerdo con esto, ya que es una habilidad que quieren o ya tienen, pero para algunos desarrolladores que solo tienen que lidiar con JSP cada pocos meses más o menos, puede ser mucho menos doloroso trabajar con scriptlets escritos claramente escritos en , familiar de Java.

Cuestiones relacionadas