flsh

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>

 

posted on   小鱼洗香香  阅读(459)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 字符编码:从基础到乱码解决
· 提示词工程——AI应用必不可少的技术
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

导航

统计

点击右上角即可分享
微信分享提示