Introdução aos filtros
Mas isso não é tudo. Você realmente não acha que os servlets são tão simples, não é?
Além dos servlets que já analisamos, existem também os chamados “servlets utilitários” - filtros . Eles são muito semelhantes aos servlets, mas sua função principal é ajudar os servlets a processar solicitações.
Um filtro é como uma secretária e um servlet é como um diretor. Antes que o documento chegue à mesa do diretor, ele passará pelas mãos do secretário. E depois que o diretor assinar, ele irá novamente para a secretária, já como correspondência de saída, por exemplo.
Essa secretária pode rejeitar alguns dos pedidos ao diretor (por exemplo, spam). Ou dê respostas padrão a perguntas conhecidas por ele ("o diretor não está no lugar"). E assim por diante. Além disso, pode haver várias dessas secretárias: uma pode filtrar spam para todos os diretores de uma vez, a outra pode transferir solicitações entre diferentes diretores e assim por diante.
Os filtros funcionam da mesma maneira.
Classes Filter, FilterChain, FilterConfig
Os filtros são muito semelhantes aos servlets, mas com algumas pequenas diferenças. Para escrever seu próprio filtro, você precisa herdar do arquivo javax.servlet.Filter
.
O filtro também possui métodos init()
e arquivos destroy()
. Em vez de um método, service()
um filtro tem uma extensão doFilter()
. E ainda tem sua própria classe FilterConfig. O filtro também é adicionado ao servlet no arquivo web.xml ou por meio da anotação @WebFilter.
Lista de métodos:
Métodos | Descrição | |
---|---|---|
1 | init(FilterConfig config) |
inicialização do filtro |
2 | destroy() |
filtro de descarga |
3 | doFilter(ServletRequest , ServletResponse, FilterChain) |
processamento de solicitação (filtragem) |
Qual é a diferença entre um servlet e um filtro?
Pode haver vários filtros e eles processam sequencialmente a solicitação (e a resposta). Eles são combinados em uma chamada cadeia - e existe até uma classe especial para eles FilterChain
.
Depois de processar a solicitação no método, doFilter()
você precisa chamar o método doFilter()
do próximo filtro da cadeia. Exemplo:
public class MyFilter implements Filter {
public void init(FilterConfig arg0) throws ServletException {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws Exception {
PrintWriter out = resp.getWriter();
out.print("Adding something before the body of the response");
chain.doFilter(req, resp); // call the next filter in the chain
out.print("Adding something after the body of the response");
}
public void destroy() {
}
}
Na verdade, você não pode adicionar o corpo da resposta assim . Formalmente, filtros e servlets são independentes uns dos outros e podem ser alterados independentemente. Eles podem ser escritos por diferentes desenvolvedores em momentos diferentes. A função de filtro é apenas uma função de serviço, por exemplo:
- Registrando todas as solicitações recebidas (e respostas)
- Compressão de dados
- Criptografia (e descriptografia) de dados
- Solicitar validação de dados
- Adicionar/remover cabeçalhos desejados
- Solicitações de redirecionamento
- Controle de acesso (verificando se o usuário está logado)
classe RequestDispatcher
doFilter()
Algumas vezes pode ser necessário chamar outro servlet enquanto um filtro está rodando dentro de um método . Para fazer isso, o contêiner possui um objeto especial RequestDispatcher
.
Você pode obtê-lo de duas maneiras:
- no objeto
HttpServletRequest
- no objeto
ServletContext
Este objeto pode ser usado para redirecionar uma solicitação existente para outro servlet . Por exemplo, descobrimos que o usuário não está autorizado e queremos mostrar a ele uma página com autorização. Bem, ou houve um erro no servidor e queremos exibir uma página de erro para o usuário :)
public class HelloServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws Exception {
String path = "/error.html";
ServletContext servletContext = this.getServletContext();
RequestDispatcher requestDispatcher = servletContext.getRequestDispatcher(path);
requestDispatcher.forward(request, response);
}
}
Você também pode ligar RequestDispatcher
de um filtro.
public class MyFilter implements Filter {
public void init(FilterConfig arg0) throws ServletException {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws Exception {
String path = "/error.html";
ServletContext servletContext = req.getServletContext();
RequestDispatcher requestDispatcher = servletContext.getRequestDispatcher(path);
requestDispatcher.forward(req, resp);
}
public void destroy() {
}
}
Observe que a requisição será tratada no método forward()
e não há necessidade de chamada doFilter()
após o uso RequestDispatcher
.
Comparação de redirecionamento e encaminhamento
E mais um ponto importante. Se você deseja redirecionar o usuário para outro URI em seu servlet, pode fazer isso de duas maneiras:
redirect
forward
Já os analisamos, mas por conveniência direi novamente.
Quando você redireciona por meio de uma chamada response.sendRedirect("link")
, o servidor envia de volta ao navegador (cliente) uma resposta 302
e o link que você especificou. E o navegador, após analisar a resposta do servidor, baixa o link que você passou. Ou seja, o link no navegador muda para um novo.
Se você encaminhar por meio de uma chamada requestDispatcher.forward()
, uma nova solicitação será feita dentro do contêiner e seu servlet enviará sua resposta ao navegador (cliente) como a resposta do seu servlet. Nesse caso, o navegador recebe uma resposta do novo servlet, mas o link no navegador não é alterado.
GO TO FULL VERSION