Introdução a Containers Web: A Primeira Aplicação Web com Servlets
Tipos de Clientes
- Há dois tipos básicos de clientes:
- Clientes tipo "Aplicação"
- Arquitetura em 2 camadas
- "Fat client"
- São instalados em cada desktop
- Clientes Web
- Browser como cliente universal fornecendo a interface com o usuário (UI)
- Uso de HTML (talvez com Javascript ou DHTML), ou XHTML ou XML/XSL para definir as telas
- Uso de HTTP ou HTTPS como protocolo
- A lógica de negócio (Business Logic) roda no servidor
- J2EE permite criar aplicações Web dinâmicas (com conteúdo dinâmico)
- J2EE provê Web Containers e duas API para escrever
aplicações
- API servlets
- API Java Server Pages (JSP)
- Nesta seção, veremos:
- A anatomia de um Web Container
- Uma aplicação Web simples
- Detalhes sobre o funcionamento dessa aplicação
O Protocolo HTTP
- Supõe-se que o aluno esteja familiarizado com o protocolo HTTP, em especial:
- O cliente inicia a conversa pedindo uma página
- Não há callback do servidor para o cliente
- GET request Method
- Para pedir páginas estáticas ou dinâmicas
- http://www.dominio.com.br?nome=jacques
- Requisições até 128 bytes
- Requisição faz parte da URL
- POST Request Method
- Para pedir páginas dinâmicas
- Requisição faz parte do corpo da mensagem HTTP
- Não há tamanho máximo da mensagem
- Formulários em páginas HTML podem usar o método GET ou POST
- Response HTTP com a página pedida
- Tipos MIME (Multi-Purpose Internet Mail Extensions)
- Originalmente, a forma de obter informação dinâmica com HTTP é de usar CGI (Common
Gateway Interface), uma forma de ativar um programa externo que gera uma página de
resposta
Containers Web e Aplicações Web
- Aplicações Web rodam no servidor
- Para fazer aplicações no servidor, previsamos de:
- Um modelo de programação e uma API
- Suporte de runtime no servidor
- Suporte de deployment
- Para instalar aplicações no servidor e customizá-las
- J2EE oferece:
- Web Components
- Java Servlets e Java Server Pages
- Web Applications
- Uma coleção de servlets, páginas JSP, outras classes, bibliotecas e recursos
estáticos tais como páginas HTML, XML, etc.
- Um Web Container
- Para hospedar aplicações Web
- Essencialmente uma JVM com API especial de servlets e suporte para JSP
- O container é responsável pelo ciclo de vida dos componentes Web (inicialização,
chamada, destruição, ..)
- Uma estrutura de packaging e um Deployment
Descriptor
- Arquivos com formato especial para armazenar um Web Component (arquivo WAR) ou Web
Application (arquivo EAR)
- O Deployment Descriptor é um arquivo XML que permite customizar a aplicação em tempo
de deployment (instalação)
- Veja a figura abaixo:
Servlets
- Servlets permitem que a lógica de aplicação seja embutida no processo
request-response
- Um servlet é um programa Java que roda do lado servidor e que estende a funcionalidade
do servidor Web
- A API de servlets provê um framework simples para construir aplicações em servidores
Web que dão suporte a servlets
- Um exemplo de um servlet está aqui
- Exemplos de servidor Web que dão suporte a servlets
- Tomcat do projeto Apache
- WebLogic da BEA
- Inprise Application Server da Borland
- iPlanet Application Server da Sun
- WebSphere Application Server da IBM
- Servidores completos J2EE grátis tais como JBoss
- Internet Information Server (IIS) da Microsoft não tem suporte a Web Containers
- Use Tomcat, JRun ou ServletExec como plug-in no IIS
- Quando o Web server entende que uma URL deve ser atendida por um Web Container, ele
passa o controle para o container
- Este container decide qual Web Application deve executar
- Quando é um servlet, o container controla a execução do servlet
- Através da API de servlets, o servlet pode acessar a informação do Request, fornecer
uma Response, etc.
Java Server Pages
- A geração de informação dinâmica pode ser feita de duas formas:
- Programaticamente (servlets)
- Através de templates (Java Server Pages ou JSP)
- O uso de templates é melhor pois deixa o Web Designer com possibilidade de criar as
páginas
- JSP é uma extensão da tecnologia de servlets
- Uma página JSP contém código HTML (ou XML)
- Tags especiais ou "scriplets" especiais são embutidos no HTML para execução
para produzir o conteúdo final
- A página JSP é traduzida para um servlet automaticamente pelo servidor J2EE
- O servlet é compilado (apenas uma vez)
- A partir daí, o servlet é executado para gerar o conteúdo dinâmico
- Observe que, depois que a página JSP foi transformada em servlet, a situação é
idêntica à execução de um servlet
- Active Server Pages (ASP) da Microsoft é semelhante mas:
- É interpretado, não compilado
- A linguagem é VBScript
Servlets ou Java Server Pages?
- Temos várias alternativas para a geração de páginas dinâmicas
- Servlets contêm a lógica de aplicação e geram o conteúdo das páginas
- JSP contêm a lógica de aplicação e geram o conteúdo das páginas
- Servlets contêm a lógica de aplicação e JSP geram o conteúdo das páginas
Deployment Descriptors
- Deployment Descriptors ajudam a configurar a aplicação Web durante a instalação
(deployment)
- O Deployment Descriptor é um arquivo chamado web.xml que tem os seguintes propósitos:
- Prover valores iniciais para parâmetros de Web Applications
- Exemplo: servidor de Banco de Dados, etc.
- Usado para inicializar qualquer valor que poderá mudar entre duas instalações
- Exemplo: não é um bom lugar para colocar a taxa de câmbio do dólar
- Permite configurar as aplicações sem alterar código e recompilar os servlets
- Definir servlets e JSPs
- Cada servlet e JSP usado pela aplicação deve ser descrito para permitir que seu
deployment seja feito
- Especificar mapeamentos de servlets e JSPs
- Define como URLs que chegam do cliente serão mapeadas para servlets e JSPs
- Especificar MIME types usados por cada aplicação
- Especificar dados de segurança
- Pode especificar quais páginas precisam de um login, qual é a página de login, que
papel o usuário deve ter para acessar a página, etc.
- Customizar páginas de boas vindas, páginas de erro, configuração de sessão, etc.
Nossa Primeira Aplicação Web
- Vamos programar?
- O problema:
- Escreva uma aplicação que peça ao usuário seu nome e email
- Imprima uma página de boas vindas dependente do horário do dia
- A solução: usaremos
- Uma página HTML fixa com um formulário para pedir a informação
- Um servlet para processar o request e gerar a página de boas vindas
- Um Deployment Descriptor
Criação do arquivo HTML
- Escolha um diretório para colocar todo o código fonte da aplicação
- Chamaremos este diretório de "src/cadastromail"
- Crie o seguinte arquivo src/cadastromail/index.html
<html>
<head>
<title>Cadastro de Mail</title>
</head>
<body>
<h1>Bem-vindo!</h1>
<form method="POST" action="/cadastromail/cadastra">
<p>Seu nome <input type="text" name="nome" size="40"></p>
<p>Seu email <input type="text" name="email" size="40"></p>
<p><input type="submit" value="Submit"> <input type="reset" value="Reset"></p>
</form>
</body>
</html>
package cadastromail;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.*;
public class CadastroServlet extends HttpServlet {
protected void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
// pega parâmetros do request
String nome = request.getParameter("nome");
String email = request.getParameter("email");
GregorianCalendar calendário = new GregorianCalendar();
String mensagem = calendário.get(Calendar.AM_PM) == Calendar.AM ?
"Bom dia" : "Boa Tarde";
// acerta tipo MIME para a resposta
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<HTML>");
out.println("<BODY>");
out.println("<P>" + mensagem + ", " + nome + "</P>");
out.println("<P>Obrigado por cadastrar seu email (" + email + ") conosco.</P>");
out.println("<P>- A Galera Java</P>");
out.println("</BODY>");
out.println("</HTML>");
out.close();
}
}
- Não se preocupe com a forma de funcionamento do servlet ainda
- Usaremos "ant" para compilar nossas aplicações
- Por enquanto, o arquivo src/build.xml deve conter (o que está sendo mostrado é uma versão simplificada do build.xml):
<project name="disciplina-j2ee-exemplos" default="all" basedir=".">
<target name="init">
<tstamp/>
<property name="build" value="../build" />
<property name="cadastromail" value="cadastromail" />
<property environment="myenv" />
<property name="j2eepath" value="${myenv.J2EE_HOME}/lib/j2ee.jar" />
</target>
<target name="prepare" depends="init">
<mkdir dir="${build}" />
</target>
<target name="clean" depends="init">
<delete dir="${build}" />
</target>
<target name="all" depends="init,cadastromail">
</target>
<target name="cadastromail" depends="init">
<mkdir dir="${build}/${cadastromail}" />
<copy todir="${build}/${cadastromail}" >
<fileset dir="${cadastromail}" >
<include name="**/*.html" />
</fileset>
</copy>
<javac srcdir="${cadastromail}"
destdir="${build}/${cadastromail}"
classpath="${j2eepath}" >
<include name="**/*.java" />
</javac>
</target>
</project>
C:\...\src>ant cadastromail
Buildfile: build.xml
init:
cadastromail:
[mkdir] Created dir: C:\...\build\cadastromail
[copy] Copying 1 file to C:\...\build\cadastromail
[javac] Compiling 1 source file to C:\...\build\cadastromail
BUILD SUCCESSFUL
Total time: 4 seconds
- Isso automaticamente criará o diretório "build", no mesmo nível de
"src"
Construção da aplicação
- O arquivo cadastromail.war
foi criado com a seguinte estrutura:
- web.xml
é o Deployment Descriptor do Web component (o servlet)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC '-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN' 'http://java.sun.com/dtd/web-app_2_3.dtd'>
<web-app>
<display-name>CadastromailWAR</display-name>
<servlet>
<servlet-name>CadastroServlet</servlet-name>
<display-name>CadastroServlet</display-name>
<servlet-class>CadastroServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CadastroServlet</servlet-name>
<url-pattern>/cadastra</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>30</session-timeout>
</session-config>
</web-app>
- Podemos agora fazer o deployment da aplicação
- Copie o arquivo cadastromail.war para a pasta $TOMCAT_HOME/webapps
- Podemos agora rodar a aplicação:
- http://<host>:8080/cadastromail/index.html
- O resultado deve ser o seguinte (pelo menos, à tarde):
Como a Aplicação Funciona
- Explicação rápida da sequência de eventos (ver figura)
- Explicação rápida do código do servlet
- doPost
- Ponto de entrada no servlet, chamado pelo Web Container
- HttpServletRequest
- De onde se pode acessar o request
- String nome = request.getParameter("nome");
- HttpServletResponse
- Para onde se encaminha a resposta
- response.setContentType("text/html");
- Default é "text/html", portanto essa linha é
opcional
- PrintWriter out = response.getWriter();
- out.println("...");
Mais sobre Servlet
- Vamos tratar dos diferentes escopos de servlet;
- Como passar o tratamento do request para outro servlet;
Sobre o ciclo de vida de um servlet
- Durante sua vida, o servlet passa pelas seguintes etapas:
- Instanciação
- O Web Container cria uma instância do servlet
- Inicialização
- O Web Container chama o método init() do servlet
- Serviço
- Se o container receber um pedido para o servlet, o método service() do servlet é chamado
- Destruição
- Antes de destruir a instância, o Web Container chama o método destroy() do servlet
- Não disponível
- A instância é destruída e marcada para coleta de lixo
Informação sobre o ServletContext
- Ele serve basicamente para armazenar informação relativa à aplicação como um todo
- Em particular, o ServletContext é usado para:
- Conter parâmetros de inicialização da aplicação
- Armazenar recursos associados à aplicação
- Uma conexão de Banco de Dados, por exemplo
- Armazenar qualquer atributo da aplicação como objetos
- Fornecer acesso à funcionalidade de logging
- Este último item é importante:
- Como fazer para depurar uma aplicação que executa no servidor?
- Como fazer para logar informação por parte da aplicação?
- Ambas as coisas podem ser feitas como segue:
contexto.log(String mensagem);
- Aqui, o "contexto" se refere ao ServletContext
- Ele pode ser obtido de várias formas:
// num Servlet qualquer
contexto = getServletContext();
// num ContextListener que recebeu um evento
contexto = event.getServletContext();
// num filtro
contexto = filterConfig.getServletContext();
- A seguinte tabela mostra como fazer compartilhamento através de objetos de escopos variados
Escopo |
Classe |
Quem pode acessar? |
Contexto Web
(a aplicação toda) |
javax.servlet.ServletContext |
Qualquer componente Web da aplicação |
Sessão |
javax.servlet.http.HttpSession |
Qualquer componente Web tratando de um pedido da sessão |
Pedido |
subtipo de javax.servlet.ServletRequest |
Qualquer componente Web tratando do pedido |
Página |
javax.servlet.jsp.PageContext |
A página JSP que cria o objeto
(Veja outro capítulo sobre JSP) |
Incluindo o conteúdo de outro recurso na resposta
- Um servlet pode diretamente incluir outro recurso enquanto está executando
- As duas formas de fazer isso são:
- Incluir o conteúdo de outro recurso
- Encaminhar (forward) o pedido para outro recurso
- Usaremos a segunda forma para chamar uma página de erro no CadastrMail
- O primeiro passo para fazer umas dessas duas chamadas é de obter o RequestDispatcher do recurso desejado
- Depois, é só chamar o método forward(...) do RequestDispatcher
// Obtém o dispatcher; ele vai mandar o banner para o usuário
RequestDispatcher dispatcher =
getServletContext().getRequestDispatcher("/ErroServlet");
if (dispatcher != null) {
dispatcher.forward(request, response);
}
- Vamos ver um exemplo;
- Todo o código pode ser pego aqui.
intro programa