Na Especificação JSP 1.2, é altamente recomendável que a JSTL (JSP Standard Tag Library) seja usada em seu aplicativo da web para ajudar reduzir a necessidade de scriptlets JSP em suas páginas. As páginas que usam JSTL são, em geral, mais fáceis de ler e manter.
...
Sempre que possível, evite scripts JSP sempre que as bibliotecas de tags fornecerem funcionalidade equivalente. Isso facilita a leitura e a manutenção das páginas, ajuda a separar a lógica de negócios da lógica de apresentação e facilita a evolução das páginas para páginas no estilo JSP 2.0 (a JSP 2.0 Specification suporta, mas não enfatiza o uso de scriptlets).
...
No espírito de adotar o padrão de design do MVC (Model-View-Controller) para reduzir o acoplamento entre a camada de apresentação da lógica de negócios, os scriptlets JSP não devem ser usados para escrever a lógica de negócios. Em vez disso, os scriptlets JSP são usados, se necessário, para transformar dados (também chamados de "objetos de valor") retornados do processamento das solicitações do cliente em um formato adequado para o cliente. Mesmo assim, isso seria melhor com um servlet do controlador frontal ou uma tag personalizada.
Se você deseja chamar o mesmo código Java em todas as solicitações, menos ou mais, independentemente da página solicitada, por exemplo, verificando se um usuário está logado, implemente um filtro e escreva o código de acordo com o doFilter()
método. Por exemplo:
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.
}
}
Quando mapeado em uma <url-pattern>
cobertura apropriada das páginas JSP de interesse, você não precisa copiar novamente o mesmo trecho de código nas páginas JSP gerais.
Se você deseja chamar algum código Java para pré - processar uma solicitação, por exemplo, pré-carregando alguma lista de um banco de dados para exibir em alguma tabela, se necessário com base em alguns parâmetros de consulta, implemente um servlet e escreva o código de acordo com o doGet()
método. Por exemplo:
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);
}
}
Dessa forma, lidar com exceções é mais fácil. O banco de dados não é acessado no meio da renderização JSP, mas muito antes da exibição do JSP. Você ainda tem a possibilidade de alterar a resposta sempre que o acesso ao banco de dados lança uma exceção. No exemplo acima, a página de erro padrão 500 será exibida e você poderá personalizar de qualquer maneira com um <error-page>
in web.xml
.
Se você deseja chamar algum código Java para pós - processar uma solicitação, por exemplo, processar uma submissão de formulário, implemente um servlet e escreva o código de acordo com o doPost()
método. Por exemplo:
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.
}
}
Desta forma, lidar com diferentes destinos página de resultados é mais fácil: reexibir o formulário com erros de validação no caso de um erro (neste exemplo em particular, você pode exibi-la novamente usando ${message}
em EL ), ou apenas tomar para a página de destino desejado em caso de sucesso.
Se você desejar chamar algum código Java para controlar o plano de execução e / ou o destino da solicitação e da resposta, implemente um servlet de acordo com o Front Controller Pattern do MVC . Por exemplo:
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);
}
}
Ou apenas adote uma estrutura MVC como JSF , Spring MVC , Wicket , etc, para que você acabe com apenas uma página JSP / Facelets e uma classe JavaBean sem a necessidade de um servlet personalizado.
Se você deseja chamar algum código Java para controlar o fluxo dentro de uma página JSP, precisará pegar um taglib de controle de fluxo (existente) como o núcleo JSTL . Por exemplo, exibindo List<Product>
em uma tabela:
<%@ 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>
Com tags no estilo XML que se encaixam perfeitamente em todo esse HTML, o código é melhor legível (e, portanto, melhor de manter) do que um monte de scriptlets com várias chaves de abertura e fechamento ( "Onde diabos essa chave de fechamento pertence?" ). Uma ajuda fácil é configurar seu aplicativo da web para gerar uma exceção sempre que scriptslet ainda forem usados, adicionando a seguinte parte a web.xml
:
<jsp-config>
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<scripting-invalid>true</scripting-invalid>
</jsp-property-group>
</jsp-config>
No Facelets , o sucessor do JSP, que faz parte do JSF da estrutura MVC fornecida pelo Java EE , já não é possível usar scripts . Dessa forma, você é automaticamente forçado a fazer as coisas "do jeito certo".
Se você desejar chamar algum código Java para acessar e exibir dados de "back-end" dentro de uma página JSP, precisará usar EL (Expression Language), essas ${}
coisas. Por exemplo, exibindo novamente os valores de entrada enviados:
<input type="text" name="foo" value="${param.foo}" />
O ${param.foo}
exibe o resultado de request.getParameter("foo")
.
Se você desejar chamar algum código Java utilitário diretamente na página JSP (normalmente public static
métodos), será necessário defini-los como funções EL. Há um taglib de funções padrão no JSTL, mas você também pode criar funções facilmente . Aqui está um exemplo de como o JSTL fn:escapeXml
é útil para evitar ataques XSS .
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
...
<input type="text" name="foo" value="${fn:escapeXml(param.foo)}" />
Observe que a sensibilidade do XSS não está de forma alguma especificamente relacionada a Java / JSP / JSTL / EL / qualquer que seja, esse problema precisa ser levado em consideração em todos os aplicativos da Web que você desenvolver. O problema dos scriptlets é que ele não fornece meios de prevenção interna, pelo menos não usando a API Java padrão. O Facelets sucessor do JSP já possui escape HTML implícito, portanto você não precisa se preocupar com os buracos XSS no Facelets.