scriptlet <%= - ¿Cómo evitar el código Java en archivos JSP?




español scriptlets (25)

También hay marcos basados ​​en componentes como Wicket que generan mucho HTML para ti. Las etiquetas que terminan en el HTML son extremadamente básicas y prácticamente no hay lógica que se mezcle. El resultado es páginas HTML casi vacías con elementos HTML típicos. La desventaja es que hay muchos componentes en la API de Wicket para aprender y algunas cosas pueden ser difíciles de lograr bajo esas restricciones.

Soy nuevo en Java EE y sé que algo así como las siguientes tres líneas

<%= x+1 %>
<%= request.getParameter("name") %>
<%! counter++; %>

es una forma de codificación de la vieja escuela y en la versión 2 de JSP existe un método para evitar el código Java en los archivos JSP. ¿Puede alguien decirme las líneas JSP 2 alternativas y cómo se llama esta técnica?


No importa cuánto intente evitar, cuando trabaje con otros desarrolladores, algunos de ellos seguirán prefiriendo scriptlet y luego insertarán el código malvado en el proyecto. Por lo tanto, la configuración del proyecto en el primer signo es muy importante si realmente desea reducir el código de scriptlet. Hay varias técnicas para superar esto (incluyendo varios marcos que otros mencionaron). Sin embargo, si prefiere la forma JSP pura, use el archivo de etiquetas JSTL. Lo bueno de esto es que también puede configurar páginas maestras para su proyecto, de modo que las otras páginas puedan heredar las páginas maestras.

Cree una página maestra llamada base.tag debajo de su WEB-INF / tags con el siguiente contenido

<%@tag description="Overall Page template" pageEncoding="UTF-8"%>

<%@attribute name="title" fragment="true" %>

<html>
  <head>
    <title>  
       <jsp:invoke fragment="title"></jsp:invoke>
    </title>

  </head>
  <body>
    <div id="page-header">
       ....
    </div>
    <div id="page-body">
      <jsp:doBody/>
    </div>
    <div id="page-footer">
      .....
    </div>
  </body>
</html>

En esta página de material, creé un fragmento llamado "título", de modo que en la página de niño, podría insertar más códigos en este lugar de la página maestra. Además, la etiqueta <jsp:doBody/> será reemplazada por el contenido de la página secundaria

Cree una página secundaria (child.jsp) en su carpeta WebContent:

<%@ taglib prefix="t" tagdir="/WEB-INF/tags" %>

<t:base>
    <jsp:attribute name="title"> 
        <bean:message key="hello.world" />
    </jsp:attribute>

    <jsp:body>
    [Put your content of the child here]
    </jsp:body>   
</t:base>

<t:base> se utiliza para especificar la página maestra que desea usar (que es base.tag en este momento). Todo el contenido dentro de la etiqueta <jsp:body> aquí reemplazará a <jsp:doBody/> en tu página maestra. Su página secundaria también puede incluir cualquier etiqueta lib y puede usarla normalmente como la otra mencionada. Sin embargo, si usa algún código de scriptlet aquí ( <%= request.getParameter("name") %> ...) e intenta ejecutar esta página, obtendrá una JasperException because Scripting elements ( &lt;%!, &lt;jsp:declaration, &lt;%=, &lt;jsp:expression, &lt;%, &lt;jsp:scriptlet ) are disallowed here . Por lo tanto, no hay forma de que otras personas puedan incluir el código malvado en el archivo jsp

Llamando a esta página desde su controlador:

Puede llamar fácilmente al archivo child.jsp desde su controlador. Esto también funciona bien con el framework struts.


Técnicamente, todos los JSP se convierten a Servlets durante el tiempo de ejecución . JSP se creó inicialmente con el propósito de desacoplar la lógica de negocios y la lógica de diseño, siguiendo el patrón MVC. Entonces, JSP son técnicamente todos los códigos Java durante el tiempo de ejecución. Pero para responder a la pregunta, las bibliotecas de etiquetas se suelen utilizar para aplicar la lógica (eliminar códigos Java) a las páginas JSP.


No estoy seguro si entiendo esto correctamente.

Deberías leer algo sobre MVC. Spring MVC & Struts 2 son las dos soluciones más comunes.


Si alguien está realmente en contra de la programación en más idiomas que uno , sugiero GWT, en teoría, puede evitar todos los elementos JS y HTML, porque Google Toolkit transforma todo el cliente y el código compartido a JS, por lo que no tendrá problemas con ellos. Usted tiene un servicio web sin codificación en ningún otro idioma. Incluso puedes usar algún CSS predeterminado de algún lugar, ya que está dado por extensiones (smartGWT o Vaadin). No necesitas aprender docenas de anotaciones.

Por supuesto, si lo desea, puede piratearse en las profundidades del código e inyectar JS y enriquecer su página HTML, pero realmente puede evitarlo si lo desea, y el resultado será bueno tal como estaba escrito en cualquier otro marco. Digo que vale la pena intentarlo, y el GWT básico está bien documentado.

Y, por supuesto, muchos compañeros programadores describieron o recomendaron otras soluciones. GWT es para personas que realmente no quieren tratar con el elemento web o para minimizarlo.


Hiciste una buena pregunta y, aunque obtuviste buenas respuestas, te sugiero que te deshagas de JSP. Es una tecnología obsoleta que eventualmente morirá. Usa un enfoque moderno, como los motores de plantillas. Tendrá una separación muy clara de las capas de presentación y de negocios, y ciertamente no habrá código Java en las plantillas, por lo que puede generar plantillas directamente desde el software de edición de presentaciones web, en la mayoría de los casos aprovechando WYSIWYG.

Y, por supuesto, manténgase alejado de los filtros y el procesamiento previo y posterior, de lo contrario, puede lidiar con las dificultades de soporte / depuración ya que siempre no sabe de dónde proviene la variable.


¿Cómo evitar el código Java en archivos JSP?

Puede usar etiquetas de biblioteca de pestañas como JSTL además de Expression Language ( EL ). Pero EL no funciona bien con JSP. Por lo tanto, es probable que sea mejor abandonar JSP completamente y usar Facelets .

Facelets es el primer lenguaje de declaración de páginas no JSP diseñado para JSF (Java Server Faces) que proporcionó un modelo de programación más simple y poderoso para los desarrolladores de JSF en comparación con JSP. Resuelve diferentes problemas que ocurren en JSP para el desarrollo de aplicaciones web.


Si utilizamos las siguientes cosas en una aplicación web java, el código java puede eliminarse del primer plano de la JSP.

  1. Usar la arquitectura MVC para aplicaciones web.

  2. Utilizar etiquetas JSP

    a. Etiquetas estándar

    segundo. Etiquetas personalizadas

  3. Lenguaje de expresion


Como dicen muchas respuestas, use JSTL o cree sus propias etiquetas personalizadas. Here hay una buena explicación sobre la creación de etiquetas personalizadas.


El uso de scriptlets (esas <% %> %% <% %> cosas) en JSP está muy desaconsejado desde el nacimiento de taglibs (como JSTL ) y EL ( EL , esas ${} cosas) en el año 2001.

Las principales desventajas de los scriptlets son:

  1. Reutilización: no se pueden reutilizar scriptlets.
  2. Reemplazo: no se pueden hacer abstractos los scriptlets.
  3. OO-habilidad: no puedes hacer uso de la herencia / composición.
  4. Debuggability: si scriptlet lanza una excepción a mitad de camino, todo lo que obtiene es una página en blanco.
  5. Probabilidad: los scriptlets no son verificables por unidad.
  6. Mantenimiento: por saldo se necesita más tiempo para mantener la lógica de código mezclado / desordenado / duplicado.

Sun Oracle también recomienda en las convenciones de codificación JSP evitar el uso de scriptlets siempre que la misma funcionalidad sea posible por las clases (etiqueta). Aquí hay varias citas de relevancia:

A partir de la especificación JSP 1.2, se recomienda encarecidamente que se utilice la biblioteca de etiquetas estándar (JSTL) de JSP en su aplicación web para ayudar a reducir la necesidad de scriptlets JSP en sus páginas. Las páginas que usan JSTL son, en general, más fáciles de leer y mantener.

...

Siempre que sea posible, evite los scriptlets JSP siempre que las bibliotecas de etiquetas proporcionen una funcionalidad equivalente. Esto hace que las páginas sean más fáciles de leer y mantener, ayuda a separar la lógica de negocios de la lógica de presentación y hará que sus páginas sean más fáciles de evolucionar hacia páginas de estilo JSP 2.0 (la especificación JSP 2.0 admite pero desestima el uso de scriplets).

...

Con el espíritu de adoptar el patrón de diseño modelo-vista-controlador (MVC) para reducir el acoplamiento entre el nivel de presentación de la lógica de negocios, los scriptlets de JSP no deben usarse para escribir la lógica de negocios. Más bien, las secuencias de comandos JSP se usan si es necesario para transformar los datos (también llamados "objetos de valor") devueltos al procesar las solicitudes del cliente en un formato adecuado listo para el cliente. Incluso entonces, esto se haría mejor con un servlet del controlador frontal o una etiqueta personalizada.

Cómo reemplazar los scriptlets depende completamente del único propósito del código / lógica. Más que a menudo este código se debe colocar en una clase de Java de plena capacidad:

  • Si desea invocar el mismo código Java en cada solicitud, menos o más independientemente de la página solicitada, por ejemplo, verificando si un usuario está conectado, entonces implemente un filter y escriba el código en consecuencia en el método doFilter() . P.ej:

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        if (((HttpServletRequest) request).getSession().getAttribute("user") == null) {
            ((HttpServletResponse) response).sendRedirect("login"); // Not logged in, redirect to login page.
        } else {
            chain.doFilter(request, response); // Logged in, just continue request.
        }
    }
    

    Cuando se asigna en un <url-pattern> apropiado <url-pattern> cubra las páginas JSP de interés, no es necesario copiar el mismo fragmento de código en todas las páginas JSP.

  • Si desea invocar algún código Java para preprocesar una solicitud, por ejemplo, precargar una lista de una base de datos para mostrar en alguna tabla, si es necesario en función de algunos parámetros de consulta, entonces implemente un servlet y escriba el código en consecuencia en el método doGet() . P.ej:

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        try {
            List<Product> products = productService.list(); // Obtain all products.
            request.setAttribute("products", products); // Store products in request scope.
            request.getRequestDispatcher("/WEB-INF/products.jsp").forward(request, response); // Forward to JSP page to display them in a HTML table.
        } catch (SQLException e) {
            throw new ServletException("Retrieving products failed!", e);
        }
    }
    

    De esta manera tratar con excepciones es más fácil. No se accede al DB en medio de la representación JSP, pero mucho antes de que se muestre el JSP. Aún tiene la posibilidad de cambiar la respuesta siempre que el acceso a la base de datos genere una excepción. En el ejemplo anterior, se mostrará la página de error 500 predeterminada que, de todos modos, puede personalizar mediante una <error-page> en web.xml .

  • Si desea invocar algún código Java para postprocesar una solicitud, por ejemplo, procesar un envío de formulario, implemente un servlet y escriba el código en consecuencia en el método doPost() . P.ej:

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        User user = userService.find(username, password);
    
        if (user != null) {
            request.getSession().setAttribute("user", user); // Login user.
            response.sendRedirect("home"); // Redirect to home page.
        } else {
            request.setAttribute("message", "Unknown username/password. Please retry."); // Store error message in request scope.
            request.getRequestDispatcher("/WEB-INF/login.jsp").forward(request, response); // Forward to JSP page to redisplay login form with error.
        }
    }
    

    De este modo, es más fácil tratar con diferentes destinos de páginas de resultados: volver a mostrar el formulario con errores de validación en caso de error (en este ejemplo en particular, puede volver a mostrarlo usando ${message} en EL ), o simplemente ir a la página de destino deseada en caso del éxito.

  • Si desea invocar algún código Java para controlar el plan de ejecución y / o el destino de la solicitud y la respuesta, entonces implemente un servlet acuerdo con el patrón del controlador frontal del MVC . P.ej:

    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        try {
            Action action = ActionFactory.getAction(request);
            String view = action.execute(request, response);
    
            if (view.equals(request.getPathInfo().substring(1)) {
                request.getRequestDispatcher("/WEB-INF/" + view + ".jsp").forward(request, response);
            } else {
                response.sendRedirect(view);
            }
        } catch (Exception e) {
            throw new ServletException("Executing action failed.", e);
        }
    }
    

    O simplemente adopte un marco MVC como JSF , Spring MVC , Wicket , etc. para que termine solo con una página JSP / Facelets y una clase de Java sin la necesidad de un servlet personalizado.

  • Si desea invocar algún código Java para controlar el flujo dentro de una página JSP, entonces necesita tomar un taglib de control de flujo (existente) como el núcleo JSTL . Ej. Desplegando List<Product> en una tabla:

    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
    ...
    <table>
        <c:forEach items="${products}" var="product">
            <tr>
                <td>${product.name}</td>
                <td>${product.description}</td>
                <td>${product.price}</td>
            </tr>
        </c:forEach>
    </table>
    

    Con etiquetas de estilo XML que encajan muy bien en todo ese HTML, el código se puede leer mejor (y, por lo tanto, es más fácil de mantener) que un montón de scriptlets con varias llaves de apertura y cierre ( "¿Dónde diablos pertenece esta llave de cierre?" ). Una ayuda fácil es configurar su aplicación web para lanzar una excepción cada vez que se utilicen scriptlets agregando la siguiente pieza a web.xml :

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

    En Facelets , el sucesor de JSP, que forma parte del marco JSF MVC proporcionado por Java EE, ya no es posible utilizar scriptlets . De esta manera te verás forzado a hacer las cosas "de la manera correcta".

  • Si desea invocar algún código Java para acceder y mostrar datos de "backend" dentro de una página JSP, entonces necesita usar EL (lenguaje de expresión), esas cosas ${} . Por ejemplo, volver a mostrar los valores de entrada enviados:

    <input type="text" name="foo" value="${param.foo}" />
    

    El ${param.foo} muestra el resultado de request.getParameter("foo") .

  • Si desea invocar algún código Java de utilidad directamente en la página JSP (por lo general, métodos public static ), debe definirlos como funciones EL. Hay una función estándar taglib en JSTL, pero también puede crear funciones fácilmente . Aquí hay un ejemplo de cómo JSTL fn:escapeXml es útil para prevenir attacks XSS .

    <%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
    ...
    <input type="text" name="foo" value="${fn:escapeXml(param.foo)}" />
    

    Tenga en cuenta que la sensibilidad de XSS no está relacionada de manera específica con Java / JSP / JSTL / EL / lo que sea, este problema debe tenerse en cuenta en cada aplicación web que desarrolle. El problema de los scriptlets es que no proporciona ninguna forma de prevención incorporada, al menos no utilizando la API de Java estándar. El sucesor de JSP, Facelets, ya tiene un escape HTML implícito, por lo que no tiene que preocuparse por los agujeros XSS en Facelets.

Ver también:


Utilice las JSTL Tag libraries en JSP, que funcionarán perfectamente.


Wicket también es una alternativa que separa completamente java de html, por lo que un diseñador y un programador pueden trabajar juntos y en diferentes conjuntos de códigos sin la menor comprensión entre ellos.

Mira a Wicket.


JSP 2.0 tiene una función llamada "Archivos de etiquetas" , puede escribir etiquetas sin javacódigo externo y tld. Debe crear un .tagarchivo y ponerlo, WEB-INF\tagsincluso puede crear una estructura de directorios para empaquetar sus etiquetas.

Por ejemplo:

/WEB-INF/tags/html/label.tag

<%@tag description="Rensders a label with required css class" pageEncoding="UTF-8"%>
<%@attribute name="name" required="true" description="The label"%>

<label class="control-label control-default"  id="${name}Label">${name}</label>

Utilízalo como

<%@ taglib prefix="h" tagdir="/WEB-INF/tags/html"%>
<h:label  name="customer name" />

También puedes leer el cuerpo de la etiqueta fácilmente.

/WEB-INF/tags/html/bold.tag
<%@tag description="Bold tag" pageEncoding="UTF-8"%>
<b>
  <jsp:doBody/>
</b>

Usalo

<%@ taglib prefix="h" tagdir="/WEB-INF/tags/bold"%>
<h:bold>Make me bold</h:bold>

Las muestras son muy simples pero puedes hacer muchas tareas complicadas aquí. Por favor, considere que puede utilizar otras etiquetas (por ejemplo: JSTLque tiene como etiquetas que controlan if/forEcah/chosenla manipulación de texto como format/contains/uppercase, o incluso etiquetas de SQL select/update), pasar todos los parámetros tipo, por ejemplo Hashmap, el acceso session, request... en el archivo de etiqueta también.

Los archivos de etiquetas son tan fáciles de desarrollar, ya que no era necesario reiniciar el servidor al cambiarlos, como los archivos jsp. Esto los hace fáciles para el desarrollo.

Incluso si usa un marco como struts 2, que tiene muchas etiquetas buenas, puede encontrar que tener sus propias etiquetas puede reducir mucho su código. Puede pasar sus parámetros de etiqueta a struts y de esta manera personalizar su etiqueta de marco.

Puede usar la etiqueta no solo para evitar Java, sino también para minimizar sus códigos HTML. Yo mismo intento revisar mucho los códigos HTML y crear etiquetas tan pronto como veo que los duplicados de código comienzan en mis páginas.

(Incluso si terminas usando el código java en tu código jsp, que espero que no, puedes encapsular ese código en una etiqueta)


Claro, reemplaza <%! counter++; %> <%! counter++; %> <%! counter++; %> por una arquitectura productor / consumidor de eventos, donde se notifica a la capa empresarial la necesidad de incrementar el contador, reacciona en consecuencia y notifica a los presentadores para que actualicen las vistas. Hay varias transacciones de base de datos involucradas, ya que en el futuro necesitaremos saber el valor nuevo y antiguo del contador, quién lo ha incrementado y con qué propósito en mente. Obviamente está implicada la serialización, ya que las capas están completamente desacopladas. Podrás incrementar tu contador sobre RMI, IIOP, SOAP. Pero solo se requiere HTML, que no implementas, ya que es un caso tan mundano. Su nuevo objetivo es alcanzar 250 incrementos por segundo en su nuevo servidor de memoria RAM brillante E7 de 64GB.

Tengo más de 20 años en la programación, la mayoría de los proyectos fracasan antes del sexteto: Reusabilidad Reemplazo OO-habilidad Debugability Testability La capacidad de mantenimiento es incluso necesaria. Otros proyectos, dirigidos por personas que solo se preocupaban por la funcionalidad, fueron extremadamente exitosos. Además, la estructura rígida de objetos, implementada demasiado pronto en el proyecto, hace que el código no pueda adaptarse a los cambios drásticos en las especificaciones (también conocido como ágil).

Por lo tanto, considero como dilación la actividad de definir "capas" o estructuras de datos redundantes ya sea al principio del proyecto o cuando no se requiere específicamente.


Como salvaguardia: deshabilite Scriptlets para siempre

Mientras se discute otra pregunta , puede y siempre debe desactivar los scriptlets en su descriptor de aplicación web web.xml .

Siempre lo haría para evitar que cualquier desarrollador agregue scriptlets, especialmente en compañías más grandes donde tarde o temprano perderá una visión general. La configuración de web.xml ve así:

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

Solo usa la etiqueta JSTL y la expresión EL.


para evitar el código java en los archivos JSP, java ahora proporciona bibliotecas de etiquetas como JSTL, java también ha creado JSF en la que puede escribir todas las estructuras de programación en forma de etiquetas



La experiencia ha demostrado que los JSP tienen algunas deficiencias, una de las cuales es difícil evitar mezclar el marcado con el código real.

Si puede, entonces considere usar una tecnología especializada para lo que necesita hacer. En Java EE 6 hay JSF 2.0, que proporciona muchas características interesantes, como pegar los beans Java junto con las páginas JSF a través del #{bean.method(argument)} .


JSTL ofrece etiquetas para condicionales, bucles, conjuntos, obtención, etc. Por ejemplo:

<c:if test="${someAttribute == 'something'}">
   ...
</c:if>

JSTL trabaja con atributos de solicitud; la mayoría de las veces se establecen en la solicitud por un Servlet, que se reenvía a la JSP.


Puede usar etiquetas JSTL junto con expresiones EL para evitar mezclar código Java y HTML:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<html>
    <head>
    </head>
    <body>

        <c:out value="${x + 1}" />
        <c:out value="${param.name}" />
        // and so on

    </body>
</html>

Usar Scriptlets es una forma muy antigua y no se recomienda. Si desea generar directamente algo en sus páginas JSP, utilice Expression Language (EL) junto con JSTL .

También hay otras opciones, como usar un motor de plantillas como Velocity, Freemarker, Thymeleaf, etc. Sin embargo, usar JSP simple con EL y JSTL cumple mi propósito la mayor parte del tiempo y también parece ser el más simple para un principiante.

Además, tenga en cuenta que no es una buena práctica hacer lógica de negocios en la capa de vista, debe realizar sus lógicas de negocios en la capa de Servicio y pasar el resultado de salida a sus vistas a través de un Controlador.


Nada de eso se usa más, amigo mío, mi consejo es desacoplar la vista (css, html, javascript, etc.) del servidor.

En mi caso, hago que mis sistemas manejen la vista con Angular y cualquier dato necesario es traído desde el servidor utilizando los servicios de descanso.

Créeme, esto cambiará la forma en que diseñas.


Una buena idea del mundo de Python son los idiomas de atributos de plantilla ; TAL fue introducido por Zope (por lo tanto, también conocido como "Plantillas de página de Zope", ZPT) y es un estándar, con implementaciones en PHP, XSLT y Java también (he usado las encarnaciones de Python / Zope y PHP). En esta clase de lenguajes de plantillas, un ejemplo de arriba podría verse así:

<table>
    <tr tal:repeat="product products">
        <td tal:content="product/name">Example product</td>
        <td tal:content="product/description">A nice description</td>
        <td tal:content="product/price">1.23</td>
    </tr>
</table>

El código se parece al HTML ordinario (o XHTML) más algunos atributos especiales en un espacio de nombres XML; puede verse con un navegador y ser ajustado con seguridad por un diseñador. Hay soporte para macros y para i18n también:

<h1 i18n:translate="">Our special offers</h1>
<table>
    <tr tal:repeat="product products">
        <td tal:content="product/name"
            i18n:translate="">Example product</td>
        <td tal:content="product/description"
            i18n:translate="">A nice description</td>
        <td tal:content="product/price">1.23</td>
    </tr>
</table>

Si las traducciones del contenido están disponibles, se utilizan.

Sin embargo, no sé mucho sobre la implementación de Java .


El marco de las colecciones de Google ofrece una forma buena y elegante de lograr el cheque nulo.

Hay un método en una clase de biblioteca como esta:

static <T> T checkNotNull(T e) {
   if (e == null) {
      throw new NullPointerException();
   }
   return e;
}

Y el uso es (con import static ):

...
void foo(int a, Person p) {
   if (checkNotNull(p).getAge() > a) {
      ...
   }
   else {
      ...
   }
}
...

O en tu ejemplo:

checkNotNull(someobject).doCalc();




java jsp scriptlet