A partir de la Especificación JSP 1.2, se recomienda encarecidamente que se use la JSP Standard Tag Library (JSTL) en su aplicación web para ayudar reducir la necesidad de scriptlets JSP en tus páginas Las páginas que usan JSTL son, en general, más fáciles de leer y mantener.
...
Donde sea posible, evitar scriptlets JSP siempre que las bibliotecas de etiquetas brinden una funcionalidad equivalente. Esto hace que las páginas sean más fáciles de leer y mantener, ayuda a separar la lógica empresarial de la lógica de presentación, y facilitará que sus páginas evolucionen en páginas de estilo JSP 2.0 (la especificación JSP 2.0 admite, pero resta importancia al uso de scriptlets).
...
En 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 y la lógica comercial, Los scriptlets JSP no deberían ser usados para escribir lógica de negocios Por el contrario, los scriptlets JSP se utilizan si es necesario para transformar los datos (también denominados "objetos de valor") devueltos del procesamiento de las solicitudes del cliente en un formato adecuado preparado para el cliente. Incluso entonces, esto se haría mejor con un servlet de controlador frontal o una etiqueta personalizada.
Si quieres invocar el mismo Código Java en cada solicitud, menos o más, independientemente de la página solicitada, p. verificar si un usuario está conectado, luego implementar un filtrar y escribir el código en consecuencia en doFilter()
método. 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 mapea en un apropiado <url-pattern>
cubriendo las páginas de interés de JSP, entonces no es necesario copiar la misma pieza de código en todas las páginas JSP.
Si desea invocar algún código Java para preproceso una solicitud, p. precargar una lista de una base de datos para mostrarla en alguna tabla, si es necesario en función de algunos parámetros de consulta, luego implementar una servlet y escribir el código en consecuencia en doGet()
método. 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 forma, lidiar con excepciones es más fácil. No se accede a la base de datos en medio de la representación JSP, pero mucho antes de que se muestre la JSP. Aún tiene la posibilidad de cambiar la respuesta cada vez que el acceso a la base arroja una excepción. En el ejemplo anterior, se mostrará la página predeterminada de error 500 que de todos modos puede personalizar de <error-page>
en web.xml
.
Si desea invocar algún código Java para proceso después de una solicitud, p. procesar un formulario enviado, luego implementar un servlet y escribir el código en consecuencia en doPost()
método. 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 esta forma, es más fácil tratar con diferentes destinos de página 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 llevarlo a la página de destino deseada en caso de é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, luego implementar un servlet según el Patrón de controlador frontal 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 adopta un framework MVC como JSF, Spring MVC, Postigo, etc. para que termine con solo una página JSP / Facelets y una clase Javabean 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 necesitas tomar un taglib de control de flujo (existente) como Núcleo JSTL. P.ej. mostrando List<Product>
en una mesa:
<%@ 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 las etiquetas de estilo XML que se adaptan perfectamente a todo ese código HTML, el código es mejor legible (y, por lo tanto, mejor mantenible) que un grupo de scriptlets con varias llaves de apertura y cierre ("¿A 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 scriptlets todavía se usan 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 es parte de Java EE proporcionó el marco MVC JSF, ya es no posible de usar scriptlets. De esta manera, te obligan automáticamente a hacer las cosas "de la manera correcta".
Si desea invocar algún código Java para acceso y visualización datos de "back-end" dentro de una página JSP, entonces necesita usar EL (Expression Language), aquellos ${}
cosas. P.ej. volver a mostrar los valores de entrada enviados:
<input type="text" name="foo" value="${param.foo}" />
los ${param.foo}
muestra el resultado de request.getParameter("foo")
.
Si quieres invocar algunos utilidad Código Java directamente en la página JSP (típicamente public static
métodos), entonces necesita definirlos como funciones EL. Hay un estándar funciones taglib en JSTL, pero también puede crear fácilmente funciones usted mismo. Aquí hay un ejemplo de cómo JSTL fn:escapeXml
es útil para prevenir XSS ataques.
<%@ 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 XSS no está específicamente relacionada con Java / JSP / JSTL / EL / lo que sea, este problema debe tenerse en cuenta en cadawebapplication que desarrollas. El problema de scriptlets es que no proporciona ninguna forma de prevenciones incorporadas, al menos no utilizando la API estándar de Java. El sucesor de JSP, Facelets, ya tiene un escape de HTML implícito, por lo que no tiene que preocuparse por los agujeros XSS en Facelets.