文章目录
过滤器
认识
Java web三大组件之一,与Servlet相似。过滤器是用来拦截请求的,而非处理请求。
当用户请求某个Servlet时,会先执行部署在这个请求上的Filter,如果Filter“放行”,才会接着执行用户请求的Servlet(或者接着执行其它的Filter)。
过滤器需要实现Filter接口,其源码如下:
public interface Filter {
void init(FilterConfig var1) throws ServletException;
void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;
void destroy();
}
生命周期
- void init(FilterConfig var1):在服务器启动时会创建Filter实例,并且每个类型的Filter只有一个实例。创建完实例后,会马上执行init()方法完成初始化工作,且这个方法只会执行一次。
- doFilter(ServletRequest req,ServletResponse res,FilterChain chain):这个方法会在用户访问“目标资源时”(index.jsp)时执行。如果需要放行,则执行FilterChain var3的doFilter(ServletRequest,ServletResponse)方法;如果不需要放心,则不调用该方法,目标资源则无法访问。
- destroy():服务器会在创建Filter对象之后,把Filter放到缓存中一直使用,通常不会销毁它。一般会在服务器关闭时销毁Filter对象,在销毁Filter对象之前,服务器会调用Filter对象的destory()方法。
FilterConfig
Filter接口中的init()方法的参数类型为FilterConfig类型,它的功能与ServletConfig相似,与web.xml文件中的配置信息对应。下面是FilterConfig的功能介绍:
ServletContext getServletContext():获取ServletContext的方法;
String getFilterName():获取Filter的配置名称;与元素对应;
String getInitParameter(String name):获取Filter的初始化配置,与元素对应;
Enumeration getInitParameterNames():获取所有初始化参数的名称。
<filter>
<filter-name>FliterOne</filter-name>
<filter-class>com.luxiya.konghua.FliterOne</filter-class>
<init-param>
<param-name>name</param-name>
<param-value>luxiya</param-value>
</init-param>
<init-param>
<param-name>age</param-name>
<param-value>18</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>FliterOne</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
public class FliterOne implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("过滤器一初始化");
String filterName = filterConfig.getFilterName();
System.out.println("过滤器名称:" + filterName);
String name = filterConfig.getInitParameter("name");
System.out.println("过滤器参数名称:" + name);
Enumeration<String> names = filterConfig.getInitParameterNames();
while (names.hasMoreElements()){
String name = names.nextElement();
String value = filterConfig.getInitParameter(name);
System.out.println("元素:" + name + " 过滤器值:" + value);
}
}
----------------结果-----------------
过滤器一初始化
过滤器名称:FliterOne
过滤器参数名称:luxiya
元素:name 过滤器值:luxiya
元素:age 过滤器值:18
FilterChain
doFilter()方法的参数中有一个类型为FilterChain的参数,它只有一个方法:doFilter(ServletRequest,ServletResponse)。
一个目标资源上,可能部署了多个过滤器,如果当前过滤器是最后一个过滤器,那么调用chain.doFilter()方法表示执行目标资源,而不是最后一个过滤器,那么chain.doFilter()表示执行下一个过滤器的doFilter()方法。
过滤器执行顺序
web.xml:一个目标资源可以指定多个过滤器,过滤器的执行顺序是在web.xml文件中的部署顺序。
注释:
在 Servlet 3.0 及以上版本中,可以使用
@WebFilter
注解来配置过滤器。此时,过滤器的执行顺序由@Order
注解或@Priority
注解来决定。@Order
注解的值越小,优先级越高,过滤器会先执行;@Priority
注解的值越小,优先级也越高,过滤器先执行。
应用场景
执行目标资源之前做预处理工作,例如设置编码,这种试通常都会放行,只是在目标资源执行之前做一些准备工作;
通过条件判断是否放行,例如校验当前用户是否已经登录,或者用户IP是否已经被禁用;
在目标资源执行后,做一些后续的特殊处理工作,例如把目标资源输出的数据进行处理;
代码
---------------------过滤器一-------------------
public class FliterOne implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("过滤器一初始化");
String filterName = filterConfig.getFilterName();
System.out.println("过滤器名称:" + filterName);
String root = filterConfig.getInitParameter("name");
System.out.println("过滤器根路径:" + root);
Enumeration<String> names = filterConfig.getInitParameterNames();
while (names.hasMoreElements()){
String name = names.nextElement();
String value = filterConfig.getInitParameter(name);
System.out.println("元素:" + name + " 过滤器值:" + value);
}
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
servletRequest.setCharacterEncoding("utf-8");
servletResponse.setCharacterEncoding("utf-8");
servletResponse.setContentType("text/html;charset=UTF-8");
System.out.println("过滤器一检测中");
filterChain.doFilter(servletRequest,servletResponse);
System.out.println("过滤器一检测后");
}
@Override
public void destroy() {
System.out.println("过滤器一销毁");
}
}
---------------------过滤器二-------------------
public class FilterTwo implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("过滤器二检测中");
filterChain.doFilter(servletRequest,servletResponse);
System.out.println("过滤器二检测后");
}
@Override
public void destroy() {
}
}
---------------------web.xml-------------------
<filter>
<filter-name>FliterOne</filter-name>
<filter-class>com.luxiya.konghua.FliterOne</filter-class>
<init-param>
<param-name>name</param-name>
<param-value>luxiya</param-value>
</init-param>
<init-param>
<param-name>age</param-name>
<param-value>18</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>FliterOne</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>FilterTwo</filter-name>
<filter-class>com.luxiya.konghua.FilterTwo</filter-class>
</filter>
<filter-mapping>
<filter-name>FilterTwo</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
---------------------结果-------------------
过滤器一初始化
过滤器名称:FliterOne
过滤器根路径:luxiya
元素:name 过滤器值:luxiya
元素:age 过滤器值:18
过滤器一检测中
过滤器二检测中
Hello Servlet,我执行了HelloServlet
过滤器二检测后
过滤器一检测后
监听器
认识
在JavaWeb被监听的事件源为:ServletContext、HttpSession、ServletRequest,即三大域对象。
监听域对象“创建”与“销毁”的监听器;
监听域对象“操作域属性”的监听器;
监听HttpSession的监听器。
ServletContextListener
ServletContextListener:Tomcat启动和关闭时调用下面两个方法:
public void contextInitialized(ServletContextEvent evt):ServletContext对象被创建后调用;
public void contextDestroyed(ServletContextEvent evt):ServletContext对象被销毁前调用;
HttpSessionListener
HttpSessionListener:开始会话和结束会话时调用下面两个方法
public void sessionCreated(HttpSessionEvent evt):HttpSession对象被创建后调用;
public void sessionDestroyed(HttpSessionEvent evt):HttpSession对象被销毁前调用;
ServletRequestListener
ServletRequestListener:开始请求和结束请求时调用下面两个方法
public void requestInitiallized(ServletRequestEvent evt):ServletRequest对象被创建后调用;
public void requestDestroyed(ServletRequestEvent evt):ServletRequest对象被销毁前调用。
代码
public class Listener implements ServletContextListener, HttpSessionListener, ServletRequestListener {
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
System.out.println("监听器初始化---ServletContext对象被创建后调用");
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
System.out.println("监听器销毁---ServletContext对象被销毁后调用");
}
@Override
public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
System.out.println("监听器销毁---ServletRequest对象被销毁后调用");
}
@Override
public void requestInitialized(ServletRequestEvent servletRequestEvent) {
System.out.println("监听器初始化---ServletRequest对象被创建后调用");
}
@Override
public void sessionCreated(HttpSessionEvent httpSessionEvent) {
System.out.println("监听器初始化---HttpSession对象被创建后调用");
}
@Override
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
System.out.println("监听器销毁---HttpSession对象被销毁后调用");
}
}
-------------------结果----------------
监听器初始化---ServletContext对象被创建后调用
过滤器一初始化
过滤器名称:FliterOne
过滤器根路径:luxiya
元素:name 过滤器值:luxiya
元素:age 过滤器值:18
[2025-02-25 08:31:10,220] Artifact fliter_listener:war exploded: Artifact is deployed successfully
[2025-02-25 08:31:10,220] Artifact fliter_listener:war exploded: Deploy took 226 milliseconds
监听器初始化---ServletRequest对象被创建后调用
过滤器一检测中
过滤器二检测中
监听器初始化---HttpSession对象被创建后调用(第一次请求才有)
Hello Servlet,我执行了HelloServlet
过滤器二检测后
过滤器一检测后
监听器销毁---ServletRequest对象被销毁后调用
统计网站人数例子
//统计网站在线人数 : 统计session
public class OnlineCountListener implements HttpSessionListener {
//创建session监听: 看你的一举一动
//一旦创建Session就会触发一次这个事件!
public void sessionCreated(HttpSessionEvent se) {
ServletContext ctx = se.getSession().getServletContext();
System.out.println(se.getSession().getId());
Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");
if (onlineCount==null){
onlineCount = new Integer(1);
}else {
int count = onlineCount.intValue();
onlineCount = new Integer(count+1);
}
ctx.setAttribute("OnlineCount",onlineCount);
}
//销毁session监听
//一旦销毁Session就会触发一次这个事件!
public void sessionDestroyed(HttpSessionEvent se) {
ServletContext ctx = se.getSession().getServletContext();
Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");
if (onlineCount==null){
onlineCount = new Integer(0);
}else {
int count = onlineCount.intValue();
onlineCount = new Integer(count-1);
}
ctx.setAttribute("OnlineCount",onlineCount);
}
/*
Session销毁:
1. 手动销毁 getSession().invalidate();
2. 自动销毁
*/
}