java - print - scriptlets que es




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

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?


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.


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:


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.


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)} .


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.


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>

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


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


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 .


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.


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.


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.


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


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>

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.


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.


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.


Mediante el uso de etiquetas JSTL junto con la expresión EL puede evitar esto. Pon las siguientes cosas en tu página jsp:

<%@ 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" %>

Use backbone, angular como javascript framework para el diseño de la interfaz de usuario y obtenga los datos con la API de resto. Esto eliminará completamente la dependencia de Java de la interfaz de usuario.





scriptlet