Ultimamente tornou-se muito importante sabermos como podemos manipular os Servlet Filters e Event Listeners para aplicações mais complexas e que precisam de tais funcionalidades. Ambos são muito utilizados nas aplicações comerciais e suportam diversas funcionalidades vitais para aplicações conforme veremos no restante do artigo.
Nas próximas seções veremos o que são e como podemos utilizar os Servlet Filter e Event Listeners. Também veremos como podemos defini-los, as novidades incorporadas nas duas funcionalidades e códigos de exemplo para demonstrar como podemos utilizá-los.
Servlet Filters
Um Servlet Filter pode ser utilizado para diversas situações. Com Servlet Filter podemos atualizar a solicitação (request) e a resposta (response) dos objetos, além manipular informações como do cabeçalho de e para o Servlet. Vale ressaltar que os filtros não criam a resposta, eles apenas modificam ou adaptam as solicitações e as respostas. Outras tarefas típicas dos filtros são: autenticação, logging, compressão de dados, encriptação de dados, entre outras.
Os filtros são empacotados juntamente com um Servlet e agem sobre o conteúdo dinâmico ou estático.
Para definirmos um filtro usamos a anotação @WebFilter conforme exemplo da Listagem 1.
Listagem 1. Exemplo como podemos definir um filtro através de uma anotação WebFilter.
@WebFilter("/*")
public class LoggingFiltro implements javax.servlet.Filter {
public void doFilter(HttpServletRequest request, HttpServletResponse response) {
//. . .
}
}
No código acima, o “LoggingFiltro” é um filtro aplicado a todos os Servlets e página de conteúdos estáticos na aplicação web. Ou seja, para toda requisição teremos esse filtro sendo processado. Como podemos ver esse filtro tem acesso à solicitação e a resposta proveniente dessa solicitação.
A anotação @WebInitParam pode ser utilizada para especificar parâmetros de inicialização para os filtros.
Um filtro e o Servlet destino sempre executam no mesmo segmento de chamada. Vários filtros podem ser organizados em uma cadeia de filtros.
Podemos também definir um filtro usando os elementos e no deployment descriptor web.xml. Segue na Listagem 2 um exemplo.
Listagem 2. Exemplo de como podemos definir um filtro da maneira antiga utilizando um arquivo web.xml.
<filter>
<filter-name>LoggingFilter</filter-name>
<filter-class>org.sample.LoggingFilter</filter-class>
</filter>
. . .
<filter-mapping>
<filter-name>LoggingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Além de declararmos os filtros usando @WebFilter e web.xml, podemos defini-los programaticamente usando métodos “ServletContext.addFilter”. Podemos fazer isto através do método “ServletContainerInitializer.onStartup” ou do método “ServletContextListener.contextInitialized”.
O método “addFilter” retorna um “ServletRegistration.Dynamic”, que pode então ser utilizado para adicionar o mapeamento para padrões de URL, configurar parâmetros de inicialização, e lidar com outros itens de configuração.
Segue na Listagem 3 um exemplo de como poderíamos definir um filtro programaticamente.
Listagem 3. Exemplo de como podemos definir um filtro programaticamente.
public class MeuInicializador implements ServletContainerInitializer {
public void onStartup (Set<Class<?>> clazz, ServletContext context) {
FilterRegistration.Dynamic reg =
context.addFilter("LoggingFiltro", "com.exemplo.LoggingFiltro");
reg.addMappingForUrlPatterns(null, false, "/");
}
}
Event Listeners
Os Event Listeners fornecem eventos de retorno de chamada do ciclo de vida para objetos “ServletContext”, “HttpSession”, e “ServletRequest”. Esses listeners são classes que implementam uma interface que suporta notificações de evento para alterações de estado nesses objetos.
Cada classe é anotada com @WebListener, declarado no web.xml, ou registrado via um dos métodos “ServletContext.addListener”.
Pode haver múltiplas classes listener "monitorando" cada tipo de evento, e eles podem ser especificados na ordem em que o container invoca os listeners para cada tipo de evento. Os listeners são notificados na ordem inversa durante o encerramento do aplicativo. Listeners em contexto de Servlets monitoram eventos a partir de recursos nesse contexto. Veja a Listagem 4.
Listagem 4. Exemplo de implementação de um listener.
@WebListener
public class MeuContextListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
ServletContext context = sce.getServletContext();
//. . .
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
//. . .
}
}
O ServletContextAttributeListener é usado para monitorar alterações de atributos no contexto.
Segue o código de exemplo na Listagem 5.
Listagem 5. Exemplo de um listener para monitorar alterações de atributos no contexto.
public class MeuServletContextAttributeListener implements ServletContextAttributeListener {
@Override
public void attributeAdded(ServletContextAttributeEvent event) {
//. . . event.getName();
//. . . event.getValue();
}
@Override
public void attributeRemoved(ServletContextAttributeEvent event) {
//. . .
}
@Override
public void attributeReplaced(ServletContextAttributeEvent event) {
//. . .
}
}
O HttpSessionListener monitora eventos a partir de recursos nessa sessão (Listagem 6).
Listagem 6. Exemplo de um listener para monitorar eventos na sessão.
@WebListener
public class MeuSessionListener implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent hse) {
HttpSession session = hse.getSession();
//. . .
}
@Override
public void sessionDestroyed(HttpSessionEvent hse) {
//. . .
}
}
O HttpSessionActivationListener é usado para monitorar por eventos quando a sessão é passivada (serialização da sessão) ou ativada. Veja a Listagem 7.
Listagem 7. Exemplo de listener para monitorar quando a sessão é passivada ou ativada.
public class MeuHttpSessionActivationListener implements HttpSessionActivationListener {
@Override
public void sessionWillPassivate(HttpSessionEvent hse) {
// ... hse.getSession();
}
@Override
public void sessionDidActivate(HttpSessionEvent hse) {
// ...
}
}
O HttpSessionAttributeListener é utilizado para monitorar alterações de atributos na sessão, conforme a Listagem 8.
Listagem 8. Exemplo de listener para monitorar alterações de atributos na sessão.
public class MeuHttpSessionAttributeListener implements HttpSessionAttributeListener {
@Override
public void attributeAdded(HttpSessionBindingEvent event) {
HttpSession session = event.getSession();
//. . . event.getName();
//. . . event.getValue();
}
@Override
public void attributeRemoved(HttpSessionBindingEvent event) {
//. . .
}
@Override
public void attributeReplaced(HttpSessionBindingEvent event) {
//. . .
}
}
O HttpSessionBindingListener é utilizado para monitorar eventos quando um objeto é ligado ou desligado de uma sessão. Veja um exemplo na Listagem 9.
Listagem 9. Exemplo utilizando listener para monitorar quando um objeto é ligado ou desligado de uma sessão.
public class MeuHttpSessionBindingListener implements HttpSessionBindingListener {
@Override
public void valueBound(HttpSessionBindingEvent event) {
HttpSession session = event.getSession();
//. . . event.getName();
//. . . event.getValue();
}
@Override
public void valueUnbound(HttpSessionBindingEvent event) {
//. . .
}
}
O ServletRequestListener monitora eventos de recursos nessa solicitação (request), conforme a Listagem 10.
Listagem 10. Exemplo de listener para monitorar eventos de recursos na solicitação.
@WebListener
public class MeuRequestListener implements ServletRequestListener {
@Override
public void requestDestroyed(ServletRequestEvent sre) {
ServletRequest request = sre.getServletRequest();
//. . .
}
@Override
public void requestInitialized(ServletRequestEvent sre) {
//. . .
}
}
O ServletRequestAttributeListener é utilizado para monitorar alterações de atributos na solicitação (request).
Temos também o “AsyncListener”, que é utilizado para gerenciar eventos assíncronos tais como concluído, tempo limite excedido, ou um erro.
Além de declarar listeners usando @WebListener e web.xml, podemos defini-los programaticamente usando métodos “ServletContext.addListener”. Podemos definir isto através do método “ServletContainerInitializer.onStartup” ou “ServletContextListener.contextInitialized” conforme já foi falado anteriormente no artigo.
O método ServletContainerInitializer.onStartup é invocado quando a aplicação está iniciando para um dado ServletContext. Segue um exemplo na Listagem 11.
Listagem 11. Exemplo de como definir um listener programaticamente.
public class MeuInicializador implements ServletContainerInitializer {
public void onStartup(Set<Class<?>> clazz, ServletContext context) {
context.addListener("com.exemplo.MeuContextListener");
}
}
Bibliografia
- Josh Juneau. Java EE 7 Recipes: A Problem-Solution Approach. Apress, 2013.
- Josh Juneau. Introducing Java EE 7: A Look at What's New. Apress, 2013.
- Arun Gupta. Java EE 7 Essentials. O'Reilly, 2013.