31
Aula 7: Servlets (II) Diego Passos Universidade Federal Fluminense ecnicas de Projeto e Implementac ¸˜ ao de Sistemas II Diego Passos (UFF) Servlets (II) TEPIS II 1 / 31

Aula 7: Servlets (II)

  • Upload
    others

  • View
    4

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Aula 7: Servlets (II)

Aula 7: Servlets (II)

Diego Passos

Universidade Federal Fluminense

Tecnicas de Projeto e Implementacao de Sistemas II

Diego Passos (UFF) Servlets (II) TEPIS II 1 / 31

Page 2: Aula 7: Servlets (II)

Ultima Aula

O que sao Servlets.Estrutura basica de um Servlet.Criacao de Servlets simples.Contexto de um Servlet.Informacoes sobre requisicoes.

Diego Passos (UFF) Servlets (II) TEPIS II 2 / 31

Page 3: Aula 7: Servlets (II)

Nesta Aula

Respostas de requisicoes.Inicializacao de Servlets.Filtros.

Diego Passos (UFF) Servlets (II) TEPIS II 3 / 31

Page 4: Aula 7: Servlets (II)

Respostas a Requisicoes

Servlets recebem requisicoes.Clientes esperam respostas.

I Dados de uma consulta.I Confirmacao de uma operacao.I . . .

Para um Servlet HTTP, resposta contem tres partes:I Codigo de status.I Cabecalhos HTTP.I Corpo da resposta.

Diego Passos (UFF) Servlets (II) TEPIS II 4 / 31

Page 5: Aula 7: Servlets (II)

Respostas a Requisicoes (II)

Manipulacao da resposta e feita pelas interfaces ServletResponse eHttpServletResponse.Incluem metodos para a criacao e manipulacao das tres partes da resposta de um Servlet.Exemplo de metodo de manipulacao da resposta: setContentType().

I Recebe como parametro uma String especificando um MIME: e.g., “text/html”.I Configura o header Content-Type na resposta.I Tipo mais comum e o “text/html”, mas deve ser configurado de acordo com a saıda do Servlet.

Diego Passos (UFF) Servlets (II) TEPIS II 5 / 31

Page 6: Aula 7: Servlets (II)

Respostas a Requisicoes (III)

Interfaces ServletResponse e HttpServletResponse tambem sao usadas paraproduzir stream de saıda.Dois metodos:

I getOutputStream(): retorna um ServletOutputStream para conteudo binario outexto.

I getWriter(): retorna um PrintWriter para conteudo texto apenas.Atencao ao usar o metodo getWriter():

I Ele inspeciona o Content-Type para determinar configuracoes de codificacao de caracteres.I setContentType() deve ser chamado antes do getWriter().

Diego Passos (UFF) Servlets (II) TEPIS II 6 / 31

Page 7: Aula 7: Servlets (II)

Respostas a Requisicoes (IV)

Ha metodos especıficos para a interface HttpServletResponse.Estes metodos obviamente manipulam componentes especıficos de respostas HTTP.Exemplo: manipulacao de cabecalhos.

I setHeader(String,String): configura o valor de um cabecalho como uma string.I setIntHeader(String,int): configura o valor de um cabecalho como um inteiro.I setDateHeader(String,long): configura o valor de um cabecalho como uma data

(milisegundos desde a Era Unix).I containsHeader(String): verifica se um determinado cabecalho ja foi definido.

Diego Passos (UFF) Servlets (II) TEPIS II 7 / 31

Page 8: Aula 7: Servlets (II)

Respostas a Requisicoes (V)

E possıvel ainda manipular o codigo de status da resposta.Feito atraves de dois metodos:

I setStatus(int): envia o codigo correspondente a constante especificada.I sendError(int, String): envia o codigo correspondente a constante especificada e uma

mensagem de erro.F Nao pode ser usado se ja houve saıda enviada ao cliente.

Outro metodo util e o sendRedirect(String): envia um redirecionamento a outra URL.O parametro da funcao pode especificar:

I Uma URL absoluta.I Um caminho relativo ao contexto do servlet (iniciado pelo caracter “/”).I Um caminho relativo a URL atual (iniciado sem o caracter “/”).

Tambem gera excecao se ha conteudo ja enviado ao cliente.

Diego Passos (UFF) Servlets (II) TEPIS II 8 / 31

Page 9: Aula 7: Servlets (II)

Despacho de Requisicoes

Muitas vezes em um Servlet e desejavel delegar uma requisicao a um outro servlet.Exemplos:

I Servlet principal apenas detecta qual servlet “secundario” deve ser chamado.I Servlet principal chama servlets secundarios para obter “pedacos” da resposta.

API de Servlets permite este tipo de solucao atraves da classe RequestDispatcher.A partir de um ServletContext e possıvel obter um RequestDispatcher:

ServletContext context = getServletContext();RequestDispatcher d = getRequestDispatcher("/ServletSecundario");

O argumento especifica o caminho ate o Servlet para o qual se deseja delegar a requisicao.

Diego Passos (UFF) Servlets (II) TEPIS II 9 / 31

Page 10: Aula 7: Servlets (II)

Despacho de Requisicoes (II)

De posse de um objeto do tipo RequestDispatcher e possıvel fazer dois tipos dedelegacao:

I forward : a responsabilidade pela requisicao e totalmente passada para o Servlet secundario.I include: apenas inclui a saıda do Servlet secundario na saıda do Servlet primario.

A classe RequestDispatcher define dois metodos correspondentes: forward() einclude().Exemplo de delegacao do tipo include:

out.println("Uptime for our servers");ServletContext context = getServletContext();RequestDispatcher d = context.getRequestDispatcher("/servlet/ServerMonitor");req.setAttribute("serverurl", new URL("http://www1.company.com"));d.include(req, res);req.setAttribute("serverurl", new URL("http://www2.company.com"));d.inc1ude(req, res);

Diego Passos (UFF) Servlets (II) TEPIS II 10 / 31

Page 11: Aula 7: Servlets (II)

Despacho de Requisicoes (III)

Qual a diferenca entre um despacho do tipo forward e um redirecionamento?I Redirecionamento exige que cliente receba a resposta e faca uma nova requisicao.I No despacho, a mesma requisicao e passada internamente ao servidor para o servlet em

questao.I Consequencias:

F Despacho tende a ser mais rapido.F Para o cliente, URL se mantem como a da requisicao original.

Note que o metodo getRequestDispatcher() pode ser usado para qualquer tipo derecurso dentro do contexto do Servlet.

I Arquivos HTML estaticos, imagens, . . .I Nao apenas outros Servlets.

Diego Passos (UFF) Servlets (II) TEPIS II 11 / 31

Page 12: Aula 7: Servlets (II)

Lidando com Erros

O que fazer quando o Servlet encontra uma situacao de erro ao processar uma requisicao?Ha varias possibilidades.A API de Servlets prove duas:

I Enviar uma mensagem de erro diretamente ao cliente.I Levantar uma excecao.

Diego Passos (UFF) Servlets (II) TEPIS II 12 / 31

Page 13: Aula 7: Servlets (II)

Lidando com Erros: Enviando Mensagem ao Cliente

E possıvel imprimir mensagens de erro diretamente ao cliente.I Da mesma forma que imprimimos o conteudo de uma resposta qualquer.

No entanto, e mais elegante (e muitas vezes poderoso) utilizar um metodo especıfico paraisso:

I sendError(int): envia um codigo de erro HTTP ao cliente com uma mensagem de erropadrao.

I sendError(int, String): envia um codigo de erro HTTP ao cliente com uma mensagemde erro especificada.

Ambos os metodos podem ser acessados atraves da interface HttpServletResponse:

response.sendError(HttpServletResponse.SC_NOT_FOUND);response.sendError(HttpServletResponse.SC_NOT_FOUND,

"Could not find the specified file.");

Estes metodos geram uma excecao caso alguma saıda ja tenha sido enviada aocliente.

Diego Passos (UFF) Servlets (II) TEPIS II 13 / 31

Page 14: Aula 7: Servlets (II)

Lidando com Erros: Enviando Mensagem ao Cliente (II)

(Fonte: “Java Enterprise in a Nutshell”)

Diego Passos (UFF) Servlets (II) TEPIS II 14 / 31

Page 15: Aula 7: Servlets (II)

Lidando com Erros: Gerando Excecoes

Breve revisao:I Excecoes sao a maneira padrao de lidar com erros em Java.I Um metodo pode se declarar capaz de gerar um determinado tipo de excecao.I Neste caso, ele pode utilizar a palavra reservada throw, gerando uma nova excecao.I Metodo chamador recebe a excecao e deve lidar com ela de alguma forma.

A API de Servlets prove dois tipos de excecao:I ServletException: reportar problemas gerais.I UnavailableException: reportar que o Servlet se encontra indisponıvel.

Servidor de aplicacao (ou container) deve lidar com a excecao gerada pelo Servlet.

Diego Passos (UFF) Servlets (II) TEPIS II 15 / 31

Page 16: Aula 7: Servlets (II)

Lidando com Erros: Gerando Excecoes

O comportamento do servidor ao receber uma ServletException nao e padronizado.I Isto e, servidores diferentes podem tratar a excecao de formas distintas.

Para a UnavailableException, no entanto, o comportamento e definido:I O servidor (container) nao deve repassar novas requisicoes.I Servlet esta indisponıvel.

Pode-se especificar um “tempo de indisponibilidade” para a UnavailableException.I Mas nao ha garantias de que o servidor ira tentar novamente apos este tempo.

Exemplos:

throw new UnavailableException(this, "Mensagem que especifica o problema.").throw new UnavailableException(120, this,

"Mensagem que especifica o problema (temporario).").

Diego Passos (UFF) Servlets (II) TEPIS II 16 / 31

Page 17: Aula 7: Servlets (II)

Lidando com Erros: Gerando Excecoes (Exemplo)

(Fonte: “Java Enterprise in a Nutshell”)

Diego Passos (UFF) Servlets (II) TEPIS II 17 / 31

Page 18: Aula 7: Servlets (II)

Inicializacao de Servlets

Relembrando:I Quando um Servlet e iniciado pelo container, meu metodo init() e chamado.I Requisicoes so sao passadas ao Servlet apos o fim do respectivo init().

Implementacao padrao do metodo init() nao faz muito.Mas metodo pode ser re-implementando por cada Servlet.Permite realizar tarefas que so precisam ser feitas uma vez:

I Operacoes intensivas em E/S.I Criacao de threads para realizar diversas tarefas.

Diego Passos (UFF) Servlets (II) TEPIS II 18 / 31

Page 19: Aula 7: Servlets (II)

Inicializacao de Servlets (II)

Ha duas versoes do metodo init():I Uma sem parametros.I Outra que recebe um objeto do tipo ServletConfig.

Pode-se reimplementar qualquer uma delas.I Mas se reimplementarmos a versao com parametro, e obrigatorio chamar a versao

original.I super.init(ServletConfig).

Diego Passos (UFF) Servlets (II) TEPIS II 19 / 31

Page 20: Aula 7: Servlets (II)

Inicializacao de Servlets (IV): Parametros de Configuracao

O objeto do tipo ServletConfig encapsula parametros de configuracao especıficos doServlet.Estes parametros podem ser acessados atraves de dois metodos:

I getInitParameter(String): retorna uma String com o valor do parametro especificado.I getInitParameterNames(): retorna uma enumeracao com os nomes dos parametros

disponıveis.Os parametros (e seus valores) sao configurados no descritor web.xml atraves da tag<init-param>.

Diego Passos (UFF) Servlets (II) TEPIS II 20 / 31

Page 21: Aula 7: Servlets (II)

Finalizacao de Servlets

Analogamente ao metodo init(), Servlets podem implementar um metodo destroy().Este metodo e chamado sempre que o servidor quer “descarregar” um Servlet.Util para liberar recursos alocados no sistema.

Diego Passos (UFF) Servlets (II) TEPIS II 21 / 31

Page 22: Aula 7: Servlets (II)

Inicializacao e Finalizacao do Contexto

A partir da versao 2.3, a API de Servlets disponibilizou a interfaceServletContextListener.Uma classe que implementa esta interface pode ser associada a um contexto.Neste caso, a classe e avisada sempre que o contexto e criado ou destruıdo.

I Atraves dos metodos contextInitialized e contextDestroyed.A associacao de uma classe a um contexto e feito no descritor web.xml:

<web-app ...><listener>

<listener-class>MyAppServletContextListener

</listener-class></listener>

</web-app>

Diego Passos (UFF) Servlets (II) TEPIS II 22 / 31

Page 23: Aula 7: Servlets (II)

Filtros

Filtros sao objetos que podem ser colocados no caminho entre as requisicoes e Servlets (ououtros recursos em um servidor).Filtros podem modificar a requisicao recebida ou resposta enviada por um servlet.

I Exemplo: comprimir os dados da resposta.Eles podem ainda realizar tarefas de monitoramento ou implementar polıticas de seguranca.Mais de um filtro pode ser utilizado, formando uma cadeia.

I Cada filtro executa sua acao e passa o controle para o proximo filtro.

Cliente Container Filtro ServletFiltro Filtro

Requisição

Resposta

Diego Passos (UFF) Servlets (II) TEPIS II 23 / 31

Page 24: Aula 7: Servlets (II)

Filtros (II)

Filtros sao implementados sobre a interface Filter.Metodos relevantes:

I init(): inicializacao do filtro.I destroy(): finalizacao do filtro.I doFilter(): metodo principal do filtro.

No metodo doFilter(), filtro pode fazer qualquer processamento sobre a requisicao.Em algum ponto, deve chamar o metodo doFilter() do proximo filtro.

I Disponıvel no objeto FilterChain, recebido como parametro.Pode tambem interromper a cadeia e retornar um erro para o cliente.Pode realizar redirecionamentos.

Diego Passos (UFF) Servlets (II) TEPIS II 24 / 31

Page 25: Aula 7: Servlets (II)

Filtros: Um Exemplo Mınimo

import javax.servlet.*;

public class GenericFilter implements javax.servlet.Filter {public FilterConfig filterConfig;

public void doFilter(final ServletRequest request,final ServletResponse response,FilterChain chain)

throws java.io.IOException, javax.servlet.ServletException {chain.doFilter(request,response);

}

public void init(final FilterConfig filterConfig) {this.filterConfig = filterConfig;

}

public void destroy() {}

}

Diego Passos (UFF) Servlets (II) TEPIS II 25 / 31

Page 26: Aula 7: Servlets (II)

Filtros: Exemplo de Codificacao de Caracteres

public void doFilter(ServletRequest request,ServletResponse response, FilterChain chain) throwsIOException, ServletException {String encoding = selectEncoding(request);if (encoding != null)

request.setCharacterEncoding(encoding);chain.doFilter(request, response);

}public void init(FilterConfig filterConfig) throws

ServletException {this.filterConfig = filterConfig;this.encoding = filterConfig.getInitParameter("encoding");

}protected String selectEncoding(ServletRequest request) {

return (this.encoding);}

Diego Passos (UFF) Servlets (II) TEPIS II 26 / 31

Page 27: Aula 7: Servlets (II)

Filtros: Exemplo de Configuracao

<filter><filter-name>Compression Filter</filter-name><filter-class>CompressionFilter</filter-class><init-param>

<param-name>compressionThreshold</param-name><param-value>10</param-value>

</init-param></filter>

Diego Passos (UFF) Servlets (II) TEPIS II 27 / 31

Page 28: Aula 7: Servlets (II)

Filtros: Requisicoes Despachadas

Originalmente, filtros so eram executados em requisicoes originadas em clientes.Requisicoes despachadas atraves da interface getRequestDispatcher() nao passavampor filtros.Em determinados casos, este comportamento e desejavel.A partir da versao 2.4 da API de Servlets, isso passou a ser possıvel.

<filter><filter-name>Compression Filter</filter-name><filter-class>CompressionFilter</filter-class><init-param>

<param-name>compressionThreshold</param-name><param-value>10</param-value>

</init-param><dispatcher>FORWARD</dispatcher><dispatcher>REQUEST</dispatcher>

</filter>

Diego Passos (UFF) Servlets (II) TEPIS II 28 / 31

Page 29: Aula 7: Servlets (II)

Filtros: Como Alterar a Saıda de Um Servlet

E facil fazer filtros adicionarem conteudo antes ou depois da resposta de um Servlet.Mas como alterar o conteudo que o Servlet gera?Exemplo:

I Suponha que o Servlet chamado gera uma pagina HTML.I Queremos adicionar alguma informacao na pagina.I Mas apos a chamada do Servlet, este inclui um </html>.

Solucao: utilizacao de wrappers.I ServletResponsetWrapper ou HttpServletResponseWrapper.

Diego Passos (UFF) Servlets (II) TEPIS II 29 / 31

Page 30: Aula 7: Servlets (II)

Filtros: Como Alterar a Saıda de Um Servlet (II)

Wrappers encapsulam objetos que representam respostas.Sobreescrevem metodos como o getWriter() ou getOutputStream().

I Ao inves de enviarem o conteudo diretamente para o cliente, pode enviar para algum bufferpor exemplo.

Filtro cria o wrapper encapsulando o objeto de resposta original.Filtro chama o proximo filtro (ou Servlet) passando o wrapper.Quando o controle retorna para o filtro, ele pode inspecionar e alterar o conteudo daresposta.

Diego Passos (UFF) Servlets (II) TEPIS II 30 / 31

Page 31: Aula 7: Servlets (II)

Filtros: Exemplo de Wrapper

public void doFilter(ServletRequest request,ServletResponse response, FilterChain chain) throwsIOException, ServletException {

PrintWriter out = response.getWriter();CharResponseWrapper wrapper = new CharResponseWrapper(

(HttpServletResponse)response);chain.doFilter(request, wrapper);

if(wrapper.getContentType().equals("text/html")) {

CharArrayWriter caw = new CharArrayWriter();caw.write(wrapper.toString().substring(0,

wrapper.toString().indexOf("</body>")-1));caw.write("<p>\nYou are visitor number

<font color=’red’>" + counter.getCounter()+ "</font>");

caw.write("\n</body></html>");response.setContentLength(caw.toString().length());out.write(caw.toString());

} elseout.write(wrapper.toString());

out.close();}

public class CharResponseWrapper extendsHttpServletResponseWrapper {private CharArrayWriter output;public String toString() {

return output.toString();}public CharResponseWrapper(

HttpServletResponse resp){super(resp);output = new CharArrayWriter();

}public PrintWriter getWriter(){

return new PrintWriter(output);}

}

Diego Passos (UFF) Servlets (II) TEPIS II 31 / 31