Filter(过滤器)、ThreadLocal(本地线程)、Listener(监听器)
Filter(过滤器)
Filter过滤器它的作用是:拦截请求,过滤响应。
过滤器链
1)执行的顺序依次是: A B C Demo03 C2 B2 A2
2)如果采取的是注解的方式进行配置,那么过滤器链的拦截顺序是按照全类名的先后顺序排序的
@WebFilter("*.do")
3)如果采取的是xml的方式进行配置,那么按照配置的先后顺序进行排序
精确匹配:<url-pattern>/target.jsp</url-pattern> 目录匹配:<url-patten>/admin/*</url-pattern> 后缀名匹配:<url-pattern>*.do</url-pattern>//请求地址必须以.do结尾才会拦截到(add.do)
Filter过滤器它只关心请求的地址是否匹配,而不关心请求的资源是否存在!
ThreadLocal(本地线程)
- 主要方法:get() , set(obj),remove()
- ThreadLocal称之为本地线程 。 我们可以通过set方法在当前线程上存储数据、通过get方法在当前线程上获取数据
set方法源码分析:
public void set(T value) { Thread t = Thread.currentThread(); //获取当前的线程 ThreadLocalMap map = getMap(t); //每一个线程都维护各自的一个容器(ThreadLocalMap) if (map != null) map.set(this, value); //这里的key对应的是ThreadLocal,因为我们的组件中需要传输(共享)的对象可能会有多个(不止Connection) else createMap(t, value); //默认情况下map是没有初始化的,那么第一次往其中添加数据时,会去初始化 }
get方法源码分析:
public T get() { Thread t = Thread.currentThread(); //获取当前的线程 ThreadLocalMap map = getMap(t); //获取和这个线程(企业)相关的ThreadLocalMap(也就是工作纽带的集合) if (map != null) { ThreadLocalMap.Entry e = map.getEntry(this); //this指的是ThreadLocal对象,通过它才能知道是哪一个工作纽带 if (e != null) { @SuppressWarnings("unchecked") T result = (T)e.value; //entry.value就可以获取到工具箱了 return result; } } return setInitialValue(); }
remove方法源码分析:
public void remove() { ThreadLocalMap m = getMap(Thread.currentThread()); //获取当前的线程 if (m != null) m.remove(this);//删除此线程 }
使用Filter和ThreadLocal组合管理
ConnUtil.class
package fruit.dao.base; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class ConnUtil { private static ThreadLocal<Connection> threadLocal=new ThreadLocal<>(); public static final String DRIVER = "com.mysql.jdbc.Driver" ; public static final String URL = "jdbc:mysql://localhost:3306/fruitdb?useUnicode=true&characterEncoding=utf-8&useSSL=false"; public static final String USER = "root"; public static final String PWD = "a1814995041" ; public static Connection createConn(){ try { //1.加载驱动 Class.forName(DRIVER); //2.通过驱动管理器获取连接对象 return DriverManager.getConnection(URL, USER, PWD); } catch (ClassNotFoundException | SQLException e) { e.printStackTrace(); } return null; } public static Connection getConn(){ Connection conn=threadLocal.get(); if (conn == null) { conn=createConn(); threadLocal.set(conn); } return threadLocal.get(); } public static void closeConn() throws SQLException { Connection conn=threadLocal.get(); if (conn==null){ return; }if(!conn.isClosed()){ conn.close(); threadLocal.set(null); } } }
TransactionManger.class
package myssm.trans; import fruit.dao.base.ConnUtil; import java.sql.Connection; import java.sql.SQLException; public class TransactionManger { //开始事务 public static void beginTrans() throws SQLException{ ConnUtil.getConn().setAutoCommit(false); } //提交事务 public static void commit() throws SQLException { Connection conn = ConnUtil.getConn(); conn.commit(); ConnUtil.closeConn(); } //回滚事务 public static void rollback() throws SQLException { Connection conn = ConnUtil.getConn(); conn.rollback(); ConnUtil.closeConn(); } }
OpenSessionInViewFilter.class
package myssm.fiflters; import myssm.trans.TransactionManger; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import java.io.IOException; import java.sql.SQLException; @WebFilter("*.do") public class OpenSessionInViewFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { try{ TransactionManger.beginTrans(); System.out.println("开始事务"); filterChain.doFilter(servletRequest,servletResponse); TransactionManger.commit(); System.out.println("提交事务"); }catch (Exception e){ e.printStackTrace(); try { TransactionManger.rollback(); System.out.println("回滚事务"); } catch (SQLException throwables) { throwables.printStackTrace(); } } } @Override public void destroy() { } }
Listener(监听器)
常用Listener
1) ServletContextListener - 监听ServletContext对象的创建和销毁的过程
2) HttpSessionListener - 监听HttpSession对象的创建和销毁的过程
3) ServletRequestListener - 监听ServletRequest对象的创建和销毁的过程
4) ServletContextAttributeListener - 监听ServletContext的保存作用域的改动(add,remove,replace)
5) HttpSessionAttributeListener - 监听HttpSession的保存作用域的改动(add,remove,replace)
6) ServletRequestAttributeListener - 监听ServletRequest的保存作用域的改动(add,remove,replace)
7) HttpSessionBindingListener - 监听某个对象在Session域中的创建与移除
8) HttpSessionActivationListener - 监听某个对象在Session域中的序列化和反序列化
ServletContextListener的应用 - ContextLoaderListener(上下文的监听器)
- ServletContextListener:可以监听ServletContext对象的创建和销毁。
- ServletContext 对象在web工程启动的时候创建,在web工程停止的时候销毁。
public class ListenerTest implements ServletContextListener { @Override public void contextInitialized(ServletContextEvent sce) { System.out.println("ServletContext对象被创建了"); } @Override public void contextDestroyed(ServletContextEvent sce) { System.out.println("ServletContext对象被销毁了"); }
与上面的项目对应(使用Filter和ThreadLocal组合管理)
ContextLoaderListener.class
package myssm.listeners; import myssm.io.BeanFactory; import myssm.io.ClassPathXmlApplicationContext; import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import javax.servlet.annotation.WebListener; @WebListener public class ContextLoaderListener implements ServletContextListener { @Override public void contextInitialized(ServletContextEvent servletContextEvent) { //1.获取ServletContext对象(上下文) ServletContext application=servletContextEvent.getServletContext(); //2.获取上下文的初始化参数 String path=application.getInitParameter("contextConfigLocation"); //3.创建IOC容器 BeanFactory beanFactory=new ClassPathXmlApplicationContext(path); //4.将IOC容器保存到application作用域中 application.setAttribute("beanFactory",beanFactory); } @Override public void contextDestroyed(ServletContextEvent servletContextEvent) { } }
web.xml
<context-param> <param-name>contextConfigLocation</param-name> <param-value>/com/applicationContext.xml</param-value> </context-param>
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 字符编码:从基础到乱码解决
· 提示词工程——AI应用必不可少的技术