JavaWeb学习——监听器和过滤器
2021-06-22 17:04
标签:3.5 isp current exce bsp parameter 因此 rac syn 监听器是用于监听Web应用而实现了特定接口的Java类。监听器可以在事件发生前、后做一些有必要的处理。 Servlet API提供了一系列的事件和事件监听接口。上层的servlet/JSP应用能够通过调用这些API进行事件驱动的开发。 这里监听的所有事件都继承自java.util.EventObject对象。 Servlet 中的监听器分类: Filters是拦截Request请求的对象: 在用户的请求访问资源前处理ServletRequest以及ServletResponse,它可以用于日志记录、解加密、Session检查、图像文件保护等。 监听器接口主要在 javax.servlet 和 javax.servlet.http 的包中。对应上文的三类,有以下这些接口: 第一类: 第二类: 编写一个监听器,只需要写一个Java类来实现对应的监听器接口就可以了。在Servlet 3.0和Servlet 3.1中提供了两种注册监听器的方法。一种是使用WebListener注解。例如: 第二种是在部署描述文档中增加一个listener元素。 当ServletContext 初始化时,容器会调用所有注册的ServletContextListeners 的 contextInitialized方法。 当ServletContext 将要销毁是,容器会调用所有注册的ServletContextListeners 的 contextDestroyed方法。 contextInitialized方法和contextDestroyed方法都会从容器获取到一个ServletContextEvent。 javax.servlet.ServletContextEvent 是一个 java.util.EventObject的子类,它定义了一个访问ServletContext的getServletContext方法。 当一个ServletContext范围的属性被添加、删除或者替换时,ServletContextAttributeListener接口的实现类会接受到消息。这个接口定义了三个方法: 这三个方法都能获取到一个 ServletContextAttributeEvent 的对象,通过这个对象可以获取属性的名称和值。 当一个HttpSession创建或者销毁时,容器都会通知所有的HttpSessionListener监听器,HttpSessionListener接口有两个方法:sessionCreated 和 sessionDestroyed。 这两个方法都可以接收到一个继承于 java.util.EventObject 的HttpSessionEvent 对象。可以通过调用HttpSessionEvent 对象的getSession方法来获取当前的HttpSession。 下面举一个例子,这个监听器可以用来统计HttpSession的数量。 当第一次访问页面时,控制台打印如下信息: HttpSessionAttributeListener接口有以下方法: 这三个方法都能获取到一个 HttpSessionBindingEvent的对象,通过这个对象可以获取属性的名称和值。 由于HttpSessionBinding是 HttpSessionEvent的子类,因此也可以在HttpSessionAttributeListener实现类中获得HttpSession。 在分布式环境下,会用多个容器进行负载均衡,有可能需要将session保存起来,在容器之间传递。例如当一个容器内存不足时,会把很少用到的对象转存到其他容器上,这时候,容器就会通知所有HttpSessionActivationListener接口实现的类。 HttpSessionActivationListener接口有两个方法,sessionDidActivate 和 sessionWillPassivate。 当HttpSession被转移到其他容器之后,sessionDidActivate就会被调用。容器将一个HttpSession方法传递到方法里,可以从这个对象获得HttpSession。 当有属性绑定或者解绑到HttpSession上时,HttpSessionBindingListener 监听器就会被调用。 ServletRequestListener监听器会对ServletRequest的创建和销毁事件进行响应。容器通过一个池来存放并重复利用多个ServletRequest,ServletRequest的创建是从容器池里被分配出来的时刻开始,而它的销毁时刻是放回池里的事件。 ServletRequestListener接口有两个方法: 这两个方法都会接收到一个ServletRequestEvent对象,可以通过这个对象的getServletRequest方法来获取ServletRequest对象。 另外,ServletRequestEvent接口也提供了一个getServletContext方法来获取ServletContext。 此接口提供了三个方法: 下面介绍与Filter相关的接口,包含 Filter、FilterConfig、Filter Chain。 Filter的实现必须继承 javax.servlet.Filter 接口。这个接口包含了 Filter 的三个生命周期:init,doFilter,destroy。 Servlet容器初始化 Filter 时,会触发 Filter 的 init 方法,一般在应用开始时,而不是在相关资源使用时才初始化,这个方法只调用一次。init 定义如下: 当Servlet 容器每次处理Filter相关资源时,都会调用该Filter实例的doFilter方法。doFilter包含三个参数,定义如下: 在doFilter中可以访问ServletRequest、ServletResponse。 在Filter的doFilter的实现中,最后一行需要调用FilterChain 中的 doFilter 方法。注意Filter的doFilter方法里的第三个参数,就是filterChain的实例: 一个资源可能被多个Filter关联到(即Filter 链条),这时Filter.doFilter()的方法将会触发Filter链条中的下一个Filter。只有在Filter链条中最后一个Filter里调用的FilterChain.doFilter(),才会触发处理资源的方法。 如果在Filter,doFilter()的实现中,没有在结尾处调用FilterChain.doFilter() 的方法,那么该Request请求终止,后面的处理就会中断。 注意:FilterChain接口中,唯一的方法是doFilter。该方法与Filter中的doFilter方法的定义是不一样的,它只有两个参数。 Filter接口中,最后一个方法是destroy,定义如下: 该方法在Servlet容器要销毁Filter时触发,一般在应用停止的时候进行调用。 当完成Filter的实现后,就要进行配置Filter了。步骤如下: FilterConfig接口允许通过它的getServletContext的方法来访问ServletContext: 如果配置了 Filter 的名字,在FilterConfig 的getFilterName 中就可以获取Filter的名字。定义如下: 当然,最重要还是要获取配置给Filter的初始化参数,需要用到FilterConfig中的两个方法,第一个方法是getParameterNames: 这个方法返回Filter参数名字的Enumeration对象。如果没有给这个Filter配置任何参数,返回空。 第二个方法是getParameter: 有两种方法可以配置Filter:一种是通过WebFilter的Annotation来配置Filter,另一种是通过部署描述来注册。下面是WebFilter的参数,所有参数都是可选的。 下面举个例子: 如果使用部署描述符,那么对应的配置为: 通过检查日志文件的内容,就可以验证这个Filter是否运行正常。 实现检查HTTP Header的referrer值,只有通过页面访问获取图片资源,直接输入文件路径无效。 如果多个Filter应用于同一个资源,Filter的触发顺序将会很重要,需要使用部署描述符来管理Filter。举个例子,Filter1要在Filter2前被触发: 如果需要保持或者改变Filter实现中的状态,就要考虑到线程安全问题。 JavaWeb学习——监听器和过滤器 标签:3.5 isp current exce bsp parameter 因此 rac syn 原文地址:https://www.cnblogs.com/cardiolith/p/9671211.html监听器 与 Filters
一、概述
二、监听器
2.1 监听器接口和注册
名称
作用
javax.servlet.ServletContextListener
它能响应Servlet生命周期事件,它提供了ServletContext创建之后和ServletContext关闭之前的会被调用的方法。
javax.servlet.http.HttpSessionListener
它能响应HttpSession的创建、超时和失效事件。
javax.servlet.http.HttpActivationListener
它在一个HttpSession激活或者失效时被调用。
javax.servlet.ServletRequestListener
它能响应一个ServletRequest的创建或删除。
名称
作用
javax.servlet.ServletContextAttributeListener
它能响应ServletContext范围内的属性添加、删除、替换事件。
javax.servlet.http.HttpSessionAttributeListener
它能响应HttpSession范围内的属性添加、删除、替换事件。
javax.servlet.http.HttpSessionBindingListener
可以实现这个接口来保存HttpSession范围的属性。当有属性从HttpSession添加或者删除时,它能做出响应。
javax.servlet.ServletRequestListener
它能响应ServletRequest范围的属性添加、删除、修改事件。
@WebListener
public class ListenerClass implements ListenerInterface {
}
listener>
listener-class>fully-qualified listener classlistener-class>
listener>
2.2 ServletContext 监听器
2.2.1 ServletContextListener
void contextInitialized(ServletContextEvent event)
void contextDestroyed(ServletContextEvent event)
2.2.2 ServletContextAttributeListener
void attributeAdded(ServletContextAttributeEvent event)
void attributeRemoved(ServletContextAttributeEvent event)
void attributeReplaced(ServletContextAttributeEvent event)
2.3 Session Listeners
2.3.1 HttpSessionListener
void sessionCreated(HttpSessionEvent event)
void sessionDestroyed(HttpSessionEvent event)
package app08a.listener;
import java.util.concurrent.atomic.AtomicInteger;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
@WebListener
public class SessionListener implements HttpSessionListener, ServletContextListener{
@Override
public void contextInitialized(ServletContextEvent e){
ServletContext servletContext = e.getServletContext();
servletContext.setAttribute("userCount", new AtomicInteger());
}
@Override
public void contextDestroyed(ServletContextEvent e){
}
@Override
public void sessionCreated(HttpSessionEvent e){
HttpSession session = e.getSession();
ServletContext servletContext = session.getServletContext();
AtomicInteger userCounter = (AtomicInteger)servletContext.getAttribute("userCount");
int userCount = userCounter.incrementAndGet();
System.out.println("userCount incremented to :"+userCount);
}
public void sessionDestroyed(HttpSessionEvent e){
HttpSession session = e.getSession();
ServletContext servletContext = session.getServletContext();
AtomicInteger userCounter = (AtomicInteger)servletContext.getAttribute("userCount");
int userCount = userCounter.decrementAndGet();
System.out.println("---------- userCount decremented to :"+userCount);
}
}
2.3.2 HttpSessionAttributeListener
void attributeAdded(HttpSessionBindingEvent event)
void attributeRemoved(HttpSessionBindingEvent event)
void attributeReplaced(HttpSessionBindingEvent event)
2.3.3 HttpSessionActivationListener
void sessionDidActivate(HttpSessionEvent event)
void sessionWillPassivate(HttpSessionEvent event)
2.3.4 HttpSessionBindingListener
2.4 ServletRequest Listeners
2.4.1 ServletRequestListener
void requestInitialized(ServletRequestEvent event)
void requestDestroyed(ServletRequestEvent event)
2.4.2 ServletRequestAttributeListener
void attributeAdded(ServletRequestAttributeEvent event)
void attributeRemoved(ServletRequestAttributeEvent event)
void attributeReplaced(ServletRequestAttributeEvent event)
三、Filters
3.1 Filter API
void init(FilterConfig filterConfig)
void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
filterChain.doFilter(request, response)
void destroy()
3.2 Filter配置
ServletContext getServletContext()
java.lang.String getFilterName()
java.util.Enumeration
java.lang.String getInitParameter(java.lang.String parameterName)
属性
描述
asyncSupported
Filter是否支持异步操作
description
Filter的描述
dispatcerTypes
Filter所生效范围
displayName
Filter的显示名
filterName
Filter的名称
initParams
Filter的初始化参数
largeIcon
Filter的大图名称
servletName
Filter所生效的Servlet名称
smallIcon
Filter的小图名称
urlPatterns
Filter所生效的URL路径
value
Filter所生效的URL路径
@WebFilter(filterName = "Security Filter", urlPatterns = {"/*"},
initParams = {
@WebInitParam(name = "frequency", value = "1909"),
@WebInitParam(name = "resolution", value = "1024")
}
}
filter>
filter-name>Security Filterfilter-name>
filter-class>filterClassfilter-class>
init-param>
param-name>frequencyparam-name>
param-value>1909param-value>
init-param>
init-param>
param-name>resolutionparam-name>
param-value>1024param-value>
init-param>
filter>
filter-mapping>
filter-name>DateCompressionFilterfilter-name>
url-pattern>/*url-pattern>
filter-mapping>
3.3 示例1:日志Filter
package filter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.http.HttpServletRequest;
@WebFilter(filterName = "LoggingFilter", urlPatterns= {"/*"},
initParams = {
@WebInitParam(name = "logFileName", value = "log.txt"),
@WebInitParam(name = "prefix", value="URI: ")
})
public class LoggingFilter implements Filter{
private PrintWriter logger;
private String prefix;
@Override
public void init(FilterConfig filterConfig) throws ServletException{
prefix = filterConfig.getInitParameter("prefix");
String logFileName = filterConfig.getInitParameter("logFileName");
String appPath = filterConfig.getServletContext().getRealPath("/");
System.out.println("logFileName:" + logFileName);
try{
logger = new PrintWriter(new File(appPath, logFileName));
}catch(FileNotFoundException e){
e.printStackTrace();
throw new ServletException(e.getMessage());
}
}
@Override
public void destroy(){
System.out.println("destroying filter");
if(logger != null)
logger.close();
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)throws IOException, ServletException{
System.out.println("LoggingFilter.doFilter");
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
logger.println(new Date() + "" + prefix + httpServletRequest.getRequestURL());
logger.flush();
filterChain.doFilter(request, response);
}
}
3.4 示例2:图像文件保护Filter
package filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
@WebFilter(filterName = "ImageProtetorFilter", urlPatterns = {"*.png","*.jpg","*.gif"})
public class ImageProtectorFilter implements Filter{
@Override
public void init(FilterConfig filterConfig) throws ServletException{
}
@Override
public void destroy(){}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)throws IOException, ServletException{
System.out.println("ImageProtectorFilter");
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
String referrer = httpServletRequest.getHeader("referer");
System.out.println("referrer:" + referrer);
if(referrer!=null)
filterChain.doFilter(request, response);
else
throw new ServletException("Image not available");
}
}
3.5 示例3:下载计数Filter
package filter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
@WebFilter(filterName = "DownloadCounterFilter", url = {"/*"})
public class DownLoadCounterFilter implements Filter{
ExecutorService executorService = Executors.newSingleThreadExecutor();
Properties downloadLog;
File logFile;
@Override
public void init(FilterConfig filterConfig) throws ServletException{
System.out.println("DownloadCounterFilter");
String appPath = filterConfig.getServletContext().getRealPath("/");
logFile = new File(appPath, "downloadLog.txt");
if(!logFile.exists()){
try{
logFile.createNewFile();
}catch(IOException e){
e.printStackTrace();
}
}
downloadLog = new Properties();
try{
downloadLog.load(new FileReader(logFile));
}catch(IOException e){
e.printStackTrace();
}
}
@Override
public void destroy(){}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException{
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
final String uri = httpServletRequest.getRequestURI();
executorService.execute(new Runnable(){
@Override
public void run(){
String property = downloadLog.getProperty(uri);
if(property == null){
downloadLog.setProperty(uri, "1");
}else{
int count = 0;
try{
count = Integer.parseInt(property);
}catch(NumberFormatException e){
}
count++;
downloadLog.setProperty(uri, Integer.toString(count));
}
try{
downloadLog.store(new FileWriter(logFile),"");
}catch(IOException e){}
}
});
filterChain.doFilter(request, response);
}
}
3.6 Filter顺序
上一篇:Java设计模式学习总结
下一篇:排序算法C语言实现