Baixe o app para aproveitar ainda mais
Prévia do material em texto
Desenvolvimento de Software para WEB Fundamentos de Servlets Prof. Regis Pires Magalhães regispires@lia.ufc.br Agradecimentos • Agradecemos ao Prof. Fábio Dias (UFC Quixadá) por ter gentilmente cedido seus slides para adaptação e uso nesta disciplina. Integração Eclipse Tomcat Tomcat • Baixe e use a versão multiplataforma (zip ou tar.gz) do Tomcat 7 em: ▫ http://tomcat.apache.org/download-70.cgi Eclipse • Baixe e use a versão Java EE do Eclipse em: ▫ http://www.eclipse.org/downloads/ Integração Eclipse Tomcat • Window Show View Other... • Na janela Show View, selecione a opção Servers. Integração Eclipse Tomcat • Na visão Servers, clique no link new server wizard ou clique com o botão direito do mouse e selecione a opção New Server. Integração Eclipse Tomcat • Na janela New Server, selecione Apache Tomcat v7.0 Server. • Depois clique em Next. Integração Eclipse Tomcat • Na Janela New Server, indique o local da instalação do Tomcat 7 • Depois clique no botão Finish. Criando Projeto Web no Eclipse Criando Projeto Web no Eclipse • File -> New -> Dynamic Web Project • Ou File -> New -> Project Criando Projeto Web no Eclipse Digite o nome do Projeto Selecione Tomcat 7 Finish Executando a aplicação • Clique com o botão direito do mouse sobre o projeto e selecione Run As Run on Server Estrutura do Projeto EE Eclipse • src - código fonte Java (.java) • build - onde o Eclipse compila as classes java (.class) • WebContent - content directory (páginas, imagens, css etc estão aqui) • WebContent/WEB-INF/ - pasta oculta com configurações e recursos do projeto • WebContent/WEB-INF/lib/ - bibliotecas .jar • WebContent/WEB-INF/classes/ - arquivos compilados são copiados para cá. Os Servlets compilados ficam aqui. Configurando o servidor Tomcat no Eclipse Configurando a aplicação do servidor Tomcat no Eclipse Caminho que define como a aplicação deverá ser executada a partir do Browser do cliente O que são Servlets? • Eles são programas que rodam em um servidor Web, agindo como uma camada intermediária entre uma requisição feita por um browser, ou outro cliente (em geral, chamadas HTTP), com outras aplicações e banco de dados. Servlet • O nome “servlet” vem da ideia de um pequeno servidor (servidorzinho, em inglês) cujo objetivo é receber chamadas HTTP, processá-las e devolver uma resposta ao cliente. import java.io.IOException ; import java.io.PrintWriter ; import javax.servlet. ServletException ; import javax.servlet.annotation.WebServlet ; import javax.servlet.http.HttpServlet ; import javax.servlet.http.HttpServletRequest ; import javax.servlet.http.HttpServletResponse ; @WebServlet ("/hello") public class HelloWorldServlet extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException , IOException { PrintWriter writer = resp.getWriter (); writer.println ("<html><body><h1>Olá Mundo</h1></body></html>"); } } Exemplo de Servlet Visão geral sobre Servlets import java.io.*; import javax.servlet.*; import javax.servlet.http.*; @WebServlet("/oi") public class HelloServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType(“text/html”); PrintWriter out = response.getWriter(); out.println("<HTML> <TITLE>Hello Page</TITLE><BODY><br>"); out.println("<h1>Hello World!</h1>"); out.println("</BODY></HTML>"); } } Mapeamento do Servlets no web.xml • A anotação @WebServlet existe a partir da API de Servlets 3.0, lançada em Dez/2009 com o Java EE 6. • Se a anotação @WebServlet não for usada, será necessário um outro tipo de mapeamento... Mapeamento de uma URL específica para um servlet através do arquivo web.xml, que fica dentro do WEB-INF: <servlet> <servlet-name>oiServlet</servlet-name> <servlet-class>HelloServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>oiServlet</servlet-name> <url-pattern>/oi</url-pattern> </servlet-mapping> Mapeamento do Servlet no web.xml • Portanto, são necessários dois passos para mapear uma servlet para uma url: ▫ 1) Definir o nome e classe do servlet; ▫ 2) Usando o nome do servlet, definir a url; • Agora o servlet pode ser acessado através da seguinte URL: http://localhost:8080/aulaServlet/oi Uma única instância de cada servlet • Existe uma única instância de cada servlet. • Ao chegar uma requisição para o servlet, uma nova Thread é aberta sobre aquela instância que já existe. • Compartilhar variáveis entre múltiplas threads pode nos trazer problemas graves de concorrência. ▫ Conclusão: evite usar atributos compartilhados. Exercícios • Implemente um Servlet Alô Mundo, faça o mapeamento usando a anotação @WebServlet. Cliclo de Vida de um Servlet Ciclo de vida do Servlet Fonte: www.argonavis.com.br Ciclo de vida do Servlet • O ciclo de vida de um servlet é controlado pelo container; • Quando o servidor recebe uma requisição, ela é repassada para o container que a delega a um servlet. O container: 1. Carrega a classe na memória; 2. Cria uma instância da classe do servlet; 3. Inicializa a instância chamando o método init() • Depois que o servlet foi inicializado, cada requisição é executado em um método service() • O container cria um objeto de requisição (ServletRequest) e de resposta (ServletResponse) e depois chama service() passando os objetos como parâmetros; • Quando a resposta é enviada, os objetos são destruídos. • Quando o container decidir remover o servlet da memória, ele o finaliza chamando o método destroy() Ciclo de vida do Servlet Parâmetros Chamando o servlet via html • Vamos criar uma página html: <html><head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Minha primeira página</title> </head> <body> <form action="oi" method=“get"> <input type="submit" value="Gravar" /> </form></body></html> Para onde (Servlet) o formulário será submetido. Como o formulário será submetido. Parâmetros • O que são? – São dados submetidos ao servlet por uma requisição HTTP (GET ou POST). • Como obtê-los? – São obtidos do objeto HttpServletRequest via método getParameter(String). • Qual o tipo do dado retornado? – São sempre String. Enviando parâmetros na requisição • Caixa de entrada de texto: • Caixa combo: • Botões de rádio: • Botões de envio: • Lista (simples e múltipla): • Caixa de checagem: Enviando parâmetros de valores simples Nome: <input type="text" name="nome"> Senha: <input type="password" name="pw"> <input type="radio" name="sexo" value="M"> Masculino <input type="radio" name="sexo" value="F"> Feminino <select name="diasemana"> <option value="1" >Domingo</option> <option value="2">Segunda</option> <option value="3" selected >Terça</option> <option value="4">Quarta</option> <option value="5">Quinta</option> <option value="6">Sexta</option> <option value="7">Sábado</option> </select> Enviando parâmetros de valores múltiplos <input type="checkbox" name="opcoes" value="A" checked> Confirmar apagar <input type="checkbox" name="opcoes" value="C"> Enviar copia <input type="checkbox" name="opcoes" value="S"> Lembrar senha <selectname="diasemana“ multiple> <option value="1" >Domingo</option> <option value="2">Segunda</option> <option value="3" selected >Terça</option> <option value="4">Quarta</option> <option value="5">Quinta</option> <option value="6">Sexta</option> <option value="7">Sábado</option> </select> Enviando parâmetros na requisição • Vamos criar uma página html: <html><head> <title>Servlet</title> </head> <body> <form action="oi" method="get"> Nome: <input type="text" name="nomePessoa"/> <br /><br /><br /> <input type="submit" value="Gravar" /> </form></body></html> Nome do parâmetro. Obtendo parâmetros da requisição • Para buscarmos o nome, precisamos utilizar o parâmetro request chamando o método getParameter(“nomeDoParametro”), aonde o nome do parâmetro é o mesmo nome do input que você quer buscar o valor. String nome = request.getParameter("nomePessoa"); Obtendo parâmetros da requisição import java.io.*; import javax.servlet.*; import javax.servlet.http.*; public class HelloServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String nome = request.getParameter("nomePessoa"); PrintWriter out = response.getWriter(); out.println("<html><title>Hello Page</title><body><br/>"); out.println("<h1>Hello World! " + nome + "</h1>"); out.println("</body></html>"); out.close(); } } A Interface HttpServletRequest • A instância de HttpServletRequest passada como parâmetro para o método doGet encapsula os dados vindos da requisição; • Através dela poderemos saber todos os dados relativos a requisição; • A interface HttpServletRequest herda de ServletRequest. A Interface HttpServletRequest Principais métodos: • getParameter(String nomeParametro): – Retorna o valor relativo a um determinado parâmetro passado; – Esse parâmetro pode ser um dado de um formulário submetido ou um dado passado na URL; – O retorno de getParameter sempre é String. – O nome do parâmetro é case sensitive. – Se o parâmetro não existir na requisição, getParameter retorna null. A Interface HttpServletRequest Principais métodos: • getParameterValues(String nomeParametro): – Retorna os valores relativos a um determinado parâmetro passado; – Use esse método quando um dado de um formulário tiver mais de um valor (um “select”, por exemplo) – O retorno de getParameterValues é um array de Strings. A Interface HttpServletRequest Principais métodos: • getMethod(): – Retorna o método utilizado para submeter os dados (GET, POST ou PUT). • getParameterNames(): – Retorna um Enumeration de Strings contendo o nome de todos os parâmetros passados na requisição. Enviando parâmetros múltiplos <html><head> <title>Minha primeira página</title></head> <body> <form action="oi" method="get"> <p>Nome:</p><input type="text" size="40" maxlength="40" name="nome"/> <p>Interesses:</p> <select name="preferencias" multiple> <option value="Musica"> Musica </option > <option value="Computadores"> Computadores </option > <option value="Jogos"> Jogos </option > </select> <input type="submit" value="Submit"> </form></body></html> Obtendo parâmetros da requisição private final String[] preferencias = {"Musica", "Computadores", "Jogos"}; public class HelloServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { PrintWriter out = response.getWriter(); response.setContentType("text/html"); out.println("<html> <title>Hello Page</TITLE><body><br>"); String nome = request.getParameter("nome"); out.println("<h1><p>Nome --> " + nome + "</p></h1>"); String[] dados = request.getParameterValues("preferencias"); if(dados == null) out.println("Sem informação"); else for (String d : dados) out.println(d); out.println("</body></html>"); out.close(); } } Exercício Faça um formulário em uma página html com todas as tags de formulário contidas nesta apresentação. Essa página irá enviar uma requisição para um Servlet. Implemente esse Servlet para que ele exiba todos os parâmetros passados. Sessões Motivação • O protocolo HTTP não mantém estado, chama-se isso de stateless; • Isso causa um grande problema – cada requisição de um usuário é uma nova requisição; • Isso é ótimo para escalabilidade; • Mais péssimo quando se deseja saber “quem” é o usuário. Motivação • E em que situação necessita-se saber “quem” é o usuário? • Imagine, um carrinho de compras como o da Amazon... • Se a cada requisição, temos um novo e desconhecido usuário, como iríamos manter os dados do carrinho de compras? Sessões • Para esse tipo de situação os containers criaram a possibilidade de gerenciar sessões; • Entenda uma sessão como uma área de memória, reservada para um cliente(Browser) no container; • Nessa área de memória, você pode colocar qualquer objeto Java. Sessões • Sessões são representadas por objetos HttpSession e são obtidas a partir de uma requisição; • Sessões representam um cliente ▫ São únicas para cada cliente e persistem entre requisições. Sessões • Para obter uma sessão: HttpSession session = request.getSession(true); • getSession(), sem parâmetros, sempre cria uma sessão, caso ela não exista. • Um parâmetro boolean indica se deve criar ou não sessão caso ela não exista. Principais Métodos de HttpSession • setAttribute(String name, Object o): Guarda um objeto na sessão. • Object getAttribute(String name): Obtém um determinado objeto armazenado na sessão. Caso ela não exista, o método retorna null. • removeAttribute(String name): Remove o atributo da sessão. • getId(): Retorna o número da sessão. Toda sessão tem um número único. Compartilhando dados na sessão • Como já dissemos os dados colocados em uma sessão ficam vivos entre requisições do usuário: Requisição 1 Aluno aluno = new Aluno(“Daniel", “083948"); HttpSession session = request.getSession(); session.setAttribute( “alunoSession", aluno ); Requisição 2 HttpSession session = request.getSession(); Aluno alunoObtido = (Aluno)session.getAttribute(“alunoSession"); Sessões - Tempo • As sessões ocupam recursos no servidor que precisam eventualmente ser liberados; • Problema: ▫ É difícil determinar exatamente quando uma sessão não é mais válida. • É necessário portanto determinar quando se deve expirar uma sessão: ▫ No TomCat o tempo padrão para expirar uma sessão é de 30 minutos. Sessões - Tempo • O tempo de vida das sessões também pode ser determinado em minutos no arquivo web.xml: <session-config> <session-timeout>20</session-timeout> </session-config> Escopo de Objetos Escopo de objetos Escopo de objetos em Servlets • Servlets compartilham informações de várias maneiras; ▫ Usando meios persistentes (banco de dados, arquivos, etc); ▫ Usando objetos na memória por escopo (requisição, sessão, contexto); ▫ Usando variáveis estáticas ou de instância. • Servlets oferecem 3 níveis diferentes de persistência na memória (ordem decrescente de duração) ▫ Contexto da aplicação – vale enquanto a aplicação estiver na memória (ServletContext, obtido através do método getServletContext()); ▫ Sessão – dura uma sessão do cliente (HttpSession); ▫ Requisição – dura uma requisição (ServletRequest) Escopo de objetos em Servlets Contexto –Classe ServletContext • A classe ServletContext representa o contexto da aplicação • Cada aplicação possui um único ServletContext, que é compartilhado por todos os Servlets • O ServletContext é acessado através do método do Servlet: • public ServletContext getServletContext( ); Escopo de objetos em Servlets Contexto – Classe ServletContext • O ServletContext também funciona como um escopo onde podem ser guardados atributos ▫ public void setAttribute(String nome, Object o) Insere novo atributo ▫ public Object getAttribute(String nome) Recupera um atributo ▫ public void removeAttribute(String nome) Remove um atributo • O ServletContext é chamado de escopo de aplicação (application) e tem acesso global na aplicação. Escopo de objetos em Servlets Contexto – Definindo Parâmetros no web.xml • O ServletContext fornece o acesso a informações sobre o contexto da aplicação: ▫ public String getInitParameter(String name) Retorna um parâmetro de inicialização do Contexto. <web-app> <context-param> <param-name>idioma</param-name> <param-value>ingles</param-value> </context-param> </web-app> Os parâmetros de contexto são acessível a todos os Servlets da aplicação. Escopo de objetos em Servlets Contexto – Acessando os Parâmetros no Servlet public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{ ServletContext context = getServletContext(); String idioma = context.getInitParameter("idioma"); PrintWriter out = response.getWriter( ); //Gera texto de resposta no idioma indicado if ( idioma.equals("portugues") ) out.println("<h1> Bemvindo!</h1>"); else if ( idioma.equals("ingles") ) out.println("<h1> Welcome!</h1>"); ... } Escopo de objetos em Servlets Tipos • Em resumo, existem em três escopos de atributos: ▫ Requisição(classe HttpServletRequest): Os atributos são armazenados apenas durante a execução de uma requisição HTTP. ▫ Sessão(classe HttpSession): Os atributos são armazenados durante toda uma sessão de iterações com um usuário. Acessível apenas para o cliente dono da Sessão. ▫ Contexto de aplicação(classe ServletContext): Os atributos são armazenados durante toda a vida da aplicação Web. Acessível a todos os clientes da aplicação. OBS: Existe ainda um quarto escopo (de página) que só existirá nas páginas JSP Escopo de objetos em Servlets Exemplo Usando parâmetros HTTP ... // Parâmetro HTTP String nome = req.getParameter("nome"); ... Usando o escopo de Aplicação ... // Escopo de Aplicação ServletContext sc = getServletContext(); sc.setAttribute("nome", "João"); ... String n = (String) sc.getAttribute("nome"); ... Usando o escopo de Sessão ... // Escopo de Sessão HttpSession s = req.getSession(); s.setAttribute("nome", "Maria"); ... n = (String) s.getAttribute("nome"); ... Usando o escopo de Requisição ... // Escopo de Requisição req.setAttribute("nome", "Lucia"); ... n = (String) req.getAttribute("nome"); ... Usando parâmetros de inicialização do Servlet ServletContext sc = getServletContext(); ... // Parâmetro de inicialização do Servlet sc.setInitParameter("nome", "Pedro"); ... n = sc.getInitParameter("nome"); ... Exercício Faça uma página dentro do Servlet com uma lista de produtos, com o nome e preço, e um link para adicionar esse produto ao carrinho de compras. Crie uma Classe Produto com nome, quantidade e preço do produto. Utilize uma lista de produto e coloque na sessão dentro do seu Servlet para criar um carrinho de compras. Exercício Redirecionamento Motivação • Existem casos onde queremos que o servlet tenha somente a responsabilidade de fazer algum processamento inicial e deixe a geração do conteúdo a alguma outro servlet. • Redirecionar significa encaminhar uma requisição para outra URL: ▫ Pode ser redirecionado para qualquer recurso, estático(HTML) ou dinâmico(Servlet, JSP) Formas de Redirecionamento • aponte para o outro componente • Redirecionamento HTTP ▫ Mais de uma conexão HTTP. ▫ Retornar ao browser um cabeçalho HTTP para ele gerar uma nova requisição. ▫ Outra requisição é necessária. Parâmetros fornecidos pelo usuários são perdidos. ▫ Através do método sendRedirect() encontrado no objeto HttpServletResponse. • Encaminhamento de requisições ▫ Uma conexão HTTP. ▫ Através do objeto RequestDispatcher. HttpServletResponse • void sendRedirect (String url): ▫ Retorna um status HTTP que força o cliente (browser) a fazer uma nova requisição a nova url. ▫ O argumento String que ele requer representa o caminho até o alvo para o qual desejamos redirecionar o usuário. ▫ A URL na barra de endereços do navegador reflete o alvo especificado. Exemplo de sendRedirect import java.io.*; import javax.servlet.*; import javax.servlet.http.*; public class Servlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //Faça alguma coisa aqui ... response.sendRedirect(“http://...”); //Oops! Nesse ponto você não pode mais gerar conteúdo! } } RequestDispatcher • Existe uma outra forma de redirecionar, sem necessitar uma nova requisição; • É mais rápido redirecionar dentro do próprio servidor (sem realizar uma nova requisição); • Para obter uma instância dessa classe, use o método do HttpServletRequest: RequestDispatcher rd = request.getRequestDispatcher(String path); • O parâmetro String que este método recebe é a localização da página HTML, JSP ou a servlet para a qual se queria disparar a requisição. RequestDispatcher • O objeto RequestDispatcher possui dois métodos importantes: ▫ forward(ServletRequest request, ServletResponse response) Redireciona para a página/servlet onde esta é a responsável por gerar a resposta. Só pode ser chamado quando nada foi ainda escrito na saída. ▫ include(ServletRequest request, ServletResponse response) Representa a inclusão de página e não o redirecionamento. Pode ser chamado a qualquer instante para acrescentar ao resultado de uma página os dados de outra. Exemplo de Include public class DispatchServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,IOException { response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.println("<html><head><title>Exemplo de include</title></head><body>"); RequestDispatcher rd = request.getRequestDispatcher("login.html"); rd.include(request, response); rd = request.getRequestDispatcher("rodape.html"); rd.include(request, response); out.println("</body></html>"); } } Exemplo de Forward import java.io.IOException; import java.util.*; import javax.servlet.*; import javax.servlet.annotation.WebServlet; import javax.servlet.http.*; @WebServlet("/exemplo_forward") public class ExemploForward extends HttpServlet { protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setAttribute("ano", 2013); RequestDispatcher rd = request.getRequestDispatcher("/exemplo_forward.jsp"); rd.forward(request, response); } Exemplo de Forward <?xml version="1.0" encoding="UTF-8" ?> <%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1- transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>Exemplo Forward</title> </head> <body> <h1>Exemplo Forward</h1> <p>Ano: ${ano}</p> </body> </html> Expression Language (EL) da JSP exemplo_forward.jsp Arquitetura de aplicação com Servlets e JSP seguindo o padrão MVC (Modelo-Visão- Controlador) Filtros • Filtros são classes que permitem que executemos código antes da requisição e também depois que a resposta foi gerada. • Mecanismo para diminuir acoplamento e isolar determinados comportamentos. • Sem filtros há uma tendência para um acoplamento muito forte entre a lógica e a implementação de requisitos não funcionais. ▫ Eles ficam espalhados em todas as lógicas. Sem uso de Filtros Com uso de filtros Filtro • Intercepta requests semelhantes, executa algo, mas depois permite que o processamento normal do request prossiga através dos Servlets e JSPs. • Um •filtro é ideal para fazer tratamento de erros ou medir o tempo de execução. • Qualquer código colocado antes da chamada chain.doFilter(request,response) será executado na ida, qualquer código depois na volta. Exemplo de Filtro public class FiltroTempoDeExecucao implements Filter { // implementação do init e destroy @WebFilter("/oi") public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { //todo o processamento vai aqui } } Exemplo de filtro @WebFilter(name = "MeuFiltro", ulrPatterns = {"/oi", "/ola"}) public class MeuFiltro implements Filter { public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) { //... } } • Se não de•finirmos um atributo “name” para nosso fi•ltro, o nome dele será o nome completo da classe. • Se quisermos defi•nir que mais de uma URL será •filtrada, podemos usar o atributo urlPatterns Filtro para medir o tempo de execução ... @WebFilter("/*") public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { long tempoInicial = System.currentTimeMillis(); chain.doFilter(request, response); long tempoFinal = System.currentTimeMillis(); String uri = ((HttpServletRequest)request).getRequestURI(); System.out.println("Tempo da requisição de " + uri + " demorou (ms): " + (tempoFinal - tempoInicial)); } ... Exemplo de filtro import java.io.IOException; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.*; @WebFilter("/*") public class LoginFilter implements Filter { public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpSession session = ((HttpServletRequest)request).getSession(false); String path = ((HttpServletRequest) request).getRequestURI(); if (path.contains("login")) { chain.doFilter(request, response); } else if (session != null && session.getAttribute("nome") != null) { chain.doFilter(request, response); } else { ((HttpServletResponse)response).sendRedirect("login.jsp"); } } public void destroy() {} public void init(FilterConfig arg0) throws ServletException {} } Exercícios Faça um Servlet de login onde ele irá autenticar o usuário pelo nome e senha. Caso o nome e a senha não esteja correto redirecione para a página erro.html de erro informando qual foi o erro. Caso esteja tudo correto, redirecione para a página sucesso.html de sucesso. Também faça a pagina inicial login.html.
Compartilhar