JSP / Servlets Avançado Andrio Spich Desenvolvedor Java & .NET Sun Certified Web Component Developer for J2EE 1.4
Servlets Definição: Servlet é um programa que estende a funcionalidade de um web server, gerando conteúdo dinâmico e interagindo com os clientes, utilizando o modelo request/response. Os servlets não são restritos ao modelo HTTP de request/response, onde na realidade são pequenas aplicações de servidores, mas o modelo HTTP é o modelo mais comumente utilizado.
Servlets - Arquitetura
Servlets - API HttpServlet: Esta classe estende a classe GenericServlet. Possui basicamente seis métodos que são chamados automaticamente de acordo com os métodos HTTP que são requisitados. Por exemplo se a solicitação do seu browser for feita pelo método GET, no servlet será chamado o método doGet(). Os seis métodos são: doPost(); doPut(); doGet(); doDelete(); doOption(); doTrave();
Servlet – GET e POST
Servlets - API HttpServletRequest: As solicitações HTTP que o browser envia pelo cliente ao servidor com informações importantes, tais como cookies e dados do formulário são tratadas a partir deste objeto, que é um dos dois argumentos dos métodos doGet ou doPost. Principal função: recuperar dados enviados ao servidor. getHeaderNames(); - pega todos os nomes dos cabeçalhos . getHeader (); - pega todos os valores do cabeçalho . getQueryString(); - pega a Query String completa. getParameterNames(); - pega todos os nomes dos parâmetros passados. getParameterValues(); - recuperação de parâmetros de múltiplos valores. getParameter(); - recuperação de parâmetros de acordo com o nome passado.
Servlets - API HttpServletResponse: Responsável por manipular a resposta dado a requisição, permitindo a escrita de conteúdo, seja HTML ou qualquer outro MIME. Esta interface é o outro argumento dos métodos doGet e doPost. addHeader(String nome, String valor) - adiciona cabeçalho HTTP setContentType(tipo MIME) - define o tipo MIME que será usado sendRedirect(String location) - envia informação de redirecionamento Writer getWriter() - obtém um Writer para gerar a saída. OutputStream getOutputStream() - obtém um OutputStream geralmente usada para gerar formatos diferentes de texto ( imagens, etc.) addCookie(Cookie c) - adiciona um novo cookie
Servlets - Exemplo import java.io.*; import javax.servlet.*; import javax.servlet.http.*; public class Teste extends HttpServlet { private PrintWriter out; public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException{ response.setContentType("text/html"); out = response.getWriter(); out.println("<HTML><HEAD><TITLE> Teste</TITLE></HEAD>"); out.println( "<BODY>"); out.println( “Parametro TESTE=“ + request.getParameter(“teste”)); out.println( "</BODY></HTML>"); } public void doPost(HttpServletRequest request, HttpServletResponse response)throws IOException, ServletException{ doGet(request,response);
Servlet - Registro Todo servlet deve ser registrado no descritor da aplicação (arquivo WEB-INF/WEB.XML). Exemplo <web-app> ... <servlet> <servlet-name>ApelidoDoServlet</servlet-name> <servlet-class>pacote.NomeDaClasse</servlet-class> <init-param> <param-name>algumParametro</param-name> <param-value> Algum Valor </param-value> </init-param> </servlet> </web-app>
ServletContext Permite ao Servlet buscar informações do seu servidor/container; Existe um único ServletContext para cada WebApplication; Utilizado para armazenar dados comuns a varios Servlets; Está contido em ServletConfig, que também permite ao servlet obter valores de inicialização;
Servlets - Inicializando Exemplo: public void init(ServletConfig config) throws ServletException { super.init(config); //always call super.init String driver = getInitParameter("driver"); String fURL = getInitParameter("url"); try { openDBConnection(driver, fURL); } catch (SQLException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();}
Servlets – Thread Model Multiple Thread model: existe apenas uma instância do Servlet, portanto qualquer campo do Servlet criado deve ter um mecanismo de sincronização para evitar erro de concorrência
Sessão – Manutenção de estado HTTP é um protocolo que não mantêm estado; Solução mais utilizada: Cookies, informações que são armazenadas no browser cliente, enviadas pelo servidor durante uma resposta de uma requisição; Solução alternativa: “Hidden Fields”, campos <input> que são passados tela a tela. Aumenta o trabalho da manutenção e o tempo de transferência da página;
Sessão em Servlets HttpSession: Interface que abstrai o envio de cookies, armazenando objetos da sessão de forma transparente. Métodos: Object getAttribute(“nomeDoAtributo”) ; void setAttibute(“nomeDoAtributo”, objetoPraGuardar) Acessada através da requisição: HttpSession request.getSession(boolean createNew)
JSP - Java Server Pages Nada mais é do que um HTML onde pode ser inserido código Java; Após ser compilado, é traduzido para um Servlet. Tem a mesma performance e ciclo de vida deste; Utiliza-se de Tags especiais para executar operações; API Simplificada: Simplifica o desenvolvimento e estimula o reuso; É recompilado automaticamente cada vez que é alterado;
JSP - Benefícios Separa a lógica de negócio da apresentação:
JSP - Exemplo <%@ page info=“teste" %> <html> <head><title>Wazaa!!!</title></head> <body bgcolor="#ffffff“ background="background.gif"> <%@ include file="banner.html" %> <table> <tr> <td width=150> <%= request.getParameter(“teste”)%> </td> </tr> </table> </body> </html>
JSP - Sintaxe Scripting Elements: código Java inserido entre os marcadores “<%” e “%>”; Diretivas: atirbuto de uma página definido entre os marcadores “<%@” e “%>”; Sintaxe XML: todas ações e diretivas podem ser descritas como tags, que iniciam com o prefixo “jsp”. Exemplo: <jsp:include file=”teste.htm”/> Comentários: <%-- Bah, sem comentário... --%>
JSP – Scripting Elements Declarações: Definição de variaveis e métodos do JSP; <%! String cliente; %> Scriptlets Fragmentos de código Java. <% cliente = request.getParameter(“cliente"); %> Expressões: Pega o resultado execução de uma expressão e escreve na saída do JSP; <br>Nome do Cliente <%= cliente %>
JSP - Diretivas Mensagens enviadas para o container, não produzem saída; Diretivas importantes: page: Comunica atributos da página para o JSP container. <%@ page import="java.util.*"%> include: Usado para incluir algum texto ou código durante o processo de tradução do JSP; <%@ include file="header.html" %> Taglib: Indica que o JSP utilizará a tag library descrita <%@ taglib uri="mytags" prefix=“tag" %>
JSP – Propósito das Diretivas Disponibilizar informações de alto nível para o processo de tradução do JSP para Servlet; Exemplo: Quais classes serão importadas <%@ page import="java.util.*" %> Que MIME type será gerado: <%@ page contentType=“text/plain" %> Qual o modelo de Threading usado <%@ page isThreadSafe="true" %> <%!--Default --%> Qual a página que manipulará possíveis exceções: <%@ page errorPage="errorpage.jsp" %>
JSP - Ações Tags especiais que modificam o estado do JSP: Exemplos: useBean, getProperty e setProperty: manipulação de JavaBeans; include: inclue um conteúdo estático durante o tempo de execução; forward: redireciona a requisição para um outro JSP ou servlet;
JSP - Objetos implícitos Por ser um Servlet, possue todos os recursos deste, com a vantagem de ter acesso a objetos instanciados automaticamente, sem ter que declará-los: request(HttpServletRequest): Contexto de uma requisição; response(HttpServletRepsonse); session(HttpSession): Contexto de sessão; application(ServletContext): Contexto Global; pageContext(HttpContext): Contexto de uma requisição em uma página; out(of type JspWriter): OutputStream do JSP config(ServletConfig);
JSP - Escopo Hierárquico:
JSP - Escopo Application e Session:
JSP - Escopo Session, Request e Page:
JavaBeans O que é: é um modelo de componente escrito em Java para criar componentes reutilizaveis; JSP utiliza as ações padrões para acessar, criar ou modificar JavaBeans; Modelo de componente = convenções: Construtor sem argumentos; Não deve ter campos publicos. Valores que necessitem ser expostos devem ser criados metodos getCampo() e setCampo(...) para acessá-lo; O escopo padrão de um JB é “page”;
JavaBeans - Exemplo package component; public class CounterBean { private int count; //use default constructor. public int getCount() { return count; } public int setCount(int value) { count = value; public void increaseCount() { count++;
Standard Actions ->JavaBeans <jsp:useBean>: especifica como encontrar ou criar um JB: se o bean existe no escopo atribuído, seu instância é retornada. Caso contrário, uma nova instância é criada; Formato: <jsp:useBean id="clock“ class=“calendar.JspCalendar” /> Equivalente a <%calendar.JspCalendar clock = new calendar.JspCalendar();%>
JSP / JavaBeans - Exemplo Este exemplo demonstra um JSP acessando um Bean que está no escopo de sessão, escrevendo o conteúdo da propriedade “username” na saída do JSP: <%@ page contentType="text/html;charset=UTF-8" %> <%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %> <jsp:useBean id="user" scope="session" type="org.apache.struts.webapp.example.User"/> <html:html> <body bgcolor="white"> <h3><jsp:getProperty name="user" property="username"/></h3> <ul> ...
Standard Actions ->JavaBeans <jsp:getProperty>: acessa uma propriedade do Bean, invocando o método “get...()” deste; Ex: <jsp:getProperty name=“customer” property=“name” /> <jsp:setProperty>: altera uma propriedade do Bean, invocando o método “set...()” deste; Ex: <jsp:setProperty name=“customer” property=“name” param=“username” /> Passando “*” para o parâmetro property, as propriedades que tiverem nome igual a algum parâmetro de request terão seu valor atribuído ao valor de request;
JSP – Manipulação de Erros Diretivas utilizadas: <%@ page errorPage="errorpage.jsp" %>: Indica qual página tratará uma exceção caso ocorra. Ao ocorrer qualquer exceção, o controle é passado para a página especificada em “errorPage”; <%@ page isErrorPage="true" %>: Indica que a página JSP é uma página utilizada para manipulação de exceções. Com isso, o objeto implícito “exception” será criado, podendo manipular a stackTrace, fazendo qualquer operação com a exceção enviada pelo JSP que a lançou.
JSP – Manipulação de Erros Exemplo de página manipuladora de erro (errorPage.jsp): <%@ page isErrorPage="true" %> <html> <body> <h1> Error Page </h1> <hr> <h2> Received the exception:<br> <font color=red> <%= exception.toString() %> </font> </h2> </body> </html>
Best Practices para JSP Evitar concatenação de Strings: String são Imutáveis; Concatenação de String cria múltiplas representações intermediárias; Solução: Utilizar a classe StringBuffer para esse tipo de situação: Exemplo String badStr = new String(); StringBuffer goodBuff = new StringBuffer(1000); for (int i=0; i<1000; i++) { badStr += myArray[i]; //crreates new Strings goodBuff.addpend(myArray[i]); //same buffer String goodStr = new String(goodBuff);
Best Practices para JSP Minimizar uso de System.out.println() System.out.println sincroniza o processamento do JSP com a operação I/O de escrita. Isto reduz drásticamente o processamento do JSP; Solução para depuração: Utilizar alguma API de Logging, como o Log4J, ou retirar qualquer chamada do código antes de enviar para produção
Best Practices para JSP Liberar o uso da sessão sempre que possível: Sessão mantêm os seus atributos carregados na memória; Utilizar HttpSession.removeAttribute() para liberar um atributo carregado na sessão; Utilizar HttpSession.invalidate() para liberar todos os recursos alocados da sessão;
Best Practices para JSP Evitar criação do objeto Session quando o JSP não necessita o uso deste: Por padrão, um objeto implícito “session” é criado; Caso o JSP não utilize session, incluir a diretiva <%@page session=“false”%>.;
Best Practices para JSP Utilizar HttpServlet.Init() para realizar operações de inicialização, que precisam ser executadas uma única vez; Este método é chamado uma única vez quando o Servlet é carregado; Exemplo: Recuperar parâmetros de inicialização, instanciar classes Helpers, etc...
Filtros Intercepta requisições e respostas de servlets de maneira transparente, sem dependência entre o filtro e o Servlet; Suportado desde a versão Servlet 2.3; Baseado em fluxo de corrente, onde é possível “plugar” varios filtros que atuarão de maneira sequencial em sua execução; Um mesmo filtro pode ser aplicado em vários servlets;
Filtros - Uso Tomar decisões: podem decidir se passam a requisição adiante para o próximo nó da corrente ou se redirecionam para um outro caminho; Manipular Request/Response: podem alterar conteúdo de ambos os objetos, extrair e inserir dados; Aplicações: Autenticação, criptografia, conversão de imagens, compressão, conversão de caracteres, etc.
Filtros - Fluxo
Filtros - API Interfaces envolvidas: javax.servlet.Filter void init(FilterConfig), void doFilter(ServletRequest, ServletResponse, FilterChain) void destroy() javax.servlet.FilterConfig String getFilterName() String getInitParameter(String name) Enumeration getInitParameterNames() ServletContext getServletContext() javax.servlet.FilterChain void doFilter(ServletRequest, ServletResponse)
Filtro - Exemplo package j550.filtros; import java.io.*; import javax.servlet.*; public class HelloFilter implements Filter { private String texto; public void init(FilterConfig config) { texto = config.getInitParameter("texto"); } public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws ServletException, IOException { PrintWriter out = response.getWriter(); out.println("<HTML><TITLE>Filter Response</TITLE>"); out.println("<BODY><P>" + texto); out.println("</BODY></HTML>"); out.close(); chain.doFilter(request,response);
Filtros - Configuração Configurado no WEB.XML na seção <filter>; Exemplo: <filter> <filter-name>umFiltro</filter-name> <filter-class> com.filtros.HelloFilter </filter-class> </filter> <filter-mapping> <url-pattern>/servlets/*</url-pattern> </filter-mapping>
Filtros - Corrente
Filtros - Wrapper
Filtros - Observações Para filtros usados com servlets HTTP, o request e response passados são HttpServletRequest e HttpServletResponse; Wrappers devem estender classes que implementam essas interfaces Filtros não são chamados quando o recurso que interceptam for chamado através de um RequestDispatcher (quando é feito um Forward) O recurso é acessado diretamente sem filtragem Isto ocorre para evitar loops infinitos Filtros associados a páginas de erro também não são chamados