监听器Listener、过滤器Filter、ThreadLocal线程局部变量知识概括
监听器Listener
Listener介绍:
- 监听器就是实时监视一些事物状态的程序,我们称为监听器。 就好像朝阳群众?朝阳区只要有哪个明星有什么不好的事,他们都会知道,然后举报。
- 那么朝阳群众就是监听器,明星就是被监视的事物,举报就是响应的内容。
- 又或者说是电动车的报警器。当报警器锁上的时候。我们去碰电动车,电动车就会报警。报警器,就是监听器,电动车就是被监视的对象。报警就是响应的内容。
监听器的使用步骤:
编写一个监听器类去实现监听器接口覆盖监听器的方法需要在web.xml中进行配置(注册)- 案例:
public class MyServletContextListener implements ServletContextListener{
@Override
//监听context域对象的创建
public void contextInitialized(ServletContextEvent sce) {
System.out.println("context创建了....");
}
//监听context域对象的销毁
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("context销毁了....");
}
}
<listener>
<!--全类名 -->
<listener-class>com.georgeMyServletContextListener </listener-class>
</listener>
一、当启动工程时ServletContext对象被创建,监听器会监听ServletContext对象,并作出相应反应。
二、日志信息:
Connected to server
[2020-07-10 12:43:02,570] Artifact servlettemp:war exploded: Artifact is being deployed, please wait...
10-Jul-2020 00:43:02.636 警告 [RMI TCP Connection(2)-127.0.0.1] org.apache.tomcat.util.descriptor.web.WebXml.setVersion Unknown version string [4.0]. Default version will be used.
ServletContext初始化了
[2020-07-10 12:43:02,711] Artifact servlettemp:war exploded: Artifact is deployed successfully
[2020-07-10 12:43:02,711] Artifact servlettemp:war exploded: Deploy took 141 milliseconds
三、当关闭工程时ServletContext对象被销毁,监听器会监听ServletContext对象,并作出相应反应。
四、日志信息:
10-Jul-2020 00:43:16.605 信息 [main] org.apache.catalina.core.StandardService.stopInternal Stopping service Catalina
ServletContext销毁了
10-Jul-2020 00:43:16.627 信息 [main] org.apache.coyote.AbstractProtocol.stop Stopping ProtocolHandler ["http-apr-8080"]
10-Jul-2020 00:43:16.695 信息 [main] org.apache.coyote.AbstractProtocol.stop Stopping ProtocolHandler ["ajp-apr-8009"]
10-Jul-2020 00:43:16.748 信息 [main] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler ["http-apr-8080"]
10-Jul-2020 00:43:16.748 信息 [main] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler ["ajp-apr-8009"]
Disconnected from server
常用监听器:
- 按照被监听的对象划分:
ServletRequest域;HttpSession域;ServletContext域。 - 按照监听的内容分:
监听域对象的创建与销毁的;监听域对象的属性变化的。
其中监听域对象的属性变化主要分为添加,覆盖(修改),删除。注意:其中最常用的为ServletContextListener,应用场景有:
①在服务器启动时建立数据库表结构,初始化数据库
②在服务器启动时将数据库常量数据加载到内存,提供访问效率
③在服务器启动时获取项目上下文路径,存放到application域给页面使用
④存放计数器计算在线用户数。
过滤器Filter
Filter介绍:
- Filter 过滤器它是 JavaWeb 的三大组件之一。三大组件分别是:Servlet 程序、Listener 监听器、Filter 过滤器
- Filter 过滤器它是 JavaEE 的规范。也就是接口
- Filter 过滤器它的作用是:
拦截请求,过滤响应。
void doFilter(ServletRequest request,ServletResponse response,FilterChain chain):实现过滤功能,该方法就是对每个请求及响应增加的额外处理。该方法可以实现对用户请求进行预处理(ServletRequest request),也可实现对服务器响应进行后处理(ServletResponse response)—它们的分界线为是否调用了chain.doFilter(),执行该方法之前,即对用户请求进行预处理;执行该方法之后,即对服务器响应进行后处理。
Filter详解:
Filter过滤器是基于函数(同步)回调方式实现。在内部调用后进入过滤器类,然后必须经过过滤器类过滤处理再回调调用原有类的原有方法。- 拦截请求常见的应用场景有:
①权限检查
②日记操作
③事务管理
④ ……
Filter的生命周期:
- ①构造器方法
- ②init 初始化方法
第一,二 步,在 web 工程启动的时候执行(Filter 已经创建)- ③doFilter 过滤方法
第三步,每次拦截到请求就会执行- ④destroy 销毁
第四步,停止 web 工程的时候就会执行(停止 web 工程,也会销毁 Filter 过滤器)
FilterConfig类:
- FilterConfig 类见名知义,它是 Filter 过滤器的配置文件类。
Tomcat 每次创建 Filter 的时候,也会同时创建一个 FilterConfig 类,这里包含了 Filter配置文件的配置信息。- FilterConfig 类的作用是获取 filter 过滤器的配置内容:
①获取 Filter 的名称 filter-name 的内容
②获取在 Filter 中配置的 init-param 初始化参数
③获取 ServletContext 对象
FilterChain过滤器链:
过滤器过滤规则:
- 过滤器默认对请求进行过滤,对服务器内部资源转发不进行过滤。
若希望服务器内部资源转发也进行过滤,在<filter-mapping>中增加转发过滤设置。
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
Filter的拦截路径:
- Filter 过滤器它只关心请求的地址是否匹配,
不关心请求的资源是否存在!
路径匹配详解:
精确匹配:
①以上配置的路径表示请求地址必须为:http://ip:port/工程路径/target.jsp
<url-pattern>/target.jsp</url-pattern>
目录匹配:
①以上配置的路径表示请求地址必须为:http://ip:port/工程路径/admin/*
<url-pattern>/admin/*</url-pattern>
后缀名匹配:
<url-pattern>*.html</url-pattern>
以上配置的路径,表示请求地址必须以.html 结尾才会拦截到
<url-pattern>*.do</url-pattern>
以上配置的路径,表示请求地址必须以.do 结尾才会拦截到
<url-pattern>*.action</url-pattern>
以上配置的路径,表示请求地址必须以.action 结尾才会拦截到
根据servlet进行过滤:
- Filter不仅可以经过url-pattern根据请求path路径进行过滤,
还可以经过servlet-name根据Servlet名称过滤- 案例:
<filter>
<filter-name>CompressingFilter</filter-name>
<filter-class>org.web.filter.CompressingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CompressingFilter</filter-name>
<servlet-name>CodeServlet</servlet-name>
</filter-mapping>
过滤器使用步骤:
编写一个过滤器类去实现过滤器接口覆盖过滤器的方法需要在web.xml中进行配置(注册)- 案例:
public class MyFilter implements Filter{
//初始化方法
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("Filter销毁了....");
}
//过滤方法
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
System.out.println("Filter过滤了....");
//必须要有放行方法
chain.doFilter(request, response);
}
//销毁方法
@Override
public void destroy() {
System.out.println("Filter销毁了....");
}
}
<filter>
<filter-name>myFilter </filter-name>
<filter-class>com.george.myFilter </filter-class>
<!--配置初始化参数 -->
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<!--配置过滤路径 -->
<filter-mapping>
<filter-name>myFilter </filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
解决乱码问题:
- GET:
①在Tomcat/conf/server.xml中设置编码.
<Connector URIEncoding="UTF-8" connectionTimeout="20000"
port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
- POST :
①字符编码过滤器只能解决POST请求乱码问题.不能解决GET请求乱码问题.
<!--字符码编辑拦截器-->
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
<init-param>
<param-name>forceRequestEncoding</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>forceResponseEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
ThreadLocal线程局部变量
ThreadLocal 的作用:
它可以解决多线程的数据安全问题。ThreadLocal 它可以给当前线程关联一个数据(可以是普通变量,可以是对象,也可以是数组,集合)。
ThreadLocal 的特点:
- ThreadLocal 可以为当前线程关联一个数据。(它可以像 Map 一样存取数据,key 为当前线程)
每一个 ThreadLocal 对象只能为当前线程关联一个数据,如果要为当前线程关联多个数据,就需要使用多个 ThreadLocal 对象实例。- 每个 ThreadLocal 对象实例定义的时候一般都是 static 类型。
ThreadLocal 中保存数据,在线程销毁后会由 JVM 虚拟自动释放。
使用 Filter 和 ThreadLocal 组合管理事务:
- 使用 ThreadLocal 来确保所有 dao 操作都在同一个 Connection 连接对象中完成

- 使用 Filter 过滤器统一给所有的 Service 方法都加上 try-catch。来进行实现的管理

- 将所有异常都统一交给 Tomcat,让 Tomcat 展示友好的错误信息页面
- 在 web.xml 中我们可以通过错误页面配置来进行管理。
ThreadLocal总结:
- 每个Thread维护着一个ThreadLocalMap的引用
- ThreadLocalMap是ThreadLocal的内部类,用Entry来进行存储
- ThreadLocal创建的副本是存储在自己的threadLocals中的,也就是自己的ThreadLocalMap
- ThreadLocalMap的键值为ThreadLocal对象,而且可以有多个threadLocal变量,因此保存在map中
- 在进行get之前,必须先set,否则会报空指针异常,当然也可以初始化一个,但是必须重写initialValue()方法。
- ThreadLocal本身并不存储值,它只是作为一个key来让线程从ThreadLocalMap获取value。
- 对于ThreadLocal来说关键就是内部的ThreadLocalMap。
使用ThreadLocal时的注意点:
- 内存泄漏问题。我们先来看下面这张图:

- 上面这张图详细的揭示了ThreadLocal和Thread以及ThreadLocalMap三者的关系。
①Thread中有一个map,就是ThreadLocalMap。
②ThreadLocalMap的key是ThreadLocal,值是我们自己设定的。
③ThreadLocal是一个弱引用,当为null时,会被当成垃圾回收。
④重点来了:突然我们ThreadLocal是null了,也就是要被垃圾回收器回收了,但是此时我们的ThreadLocalMap生命周期和Thread的一样,它不会回收,这时候就出现了一个现象。那就是ThreadLocalMap的key没了,但是value还在,这就造成了内存泄漏。 - 解决办法:
使用完ThreadLocal后,执行remove操作,避免出现内存溢出情况。 - 链接:面试官:知道ThreadLocal嘛?谈谈你对它的理解?(基于jdk1.8)
版权声明:本文为weixin_41005188原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。