107_JavaWeb_Filter_ThreadLocal

举报
alexsully 发表于 2021/08/06 19:20:05 2021/08/06
【摘要】 ThreadLocalThreadLocal作用,解决多线程的数据安全问题ThreadLocal 它可以给当前线程关联一个数据(可以是普通变量,可以是对象,也可以是数组,集合)ThreadLocal 特点: 1 ThreadLocal 可以为当前线程关联一个数据。(它可以像 Map 一样存取数据,key为当前线程) 2 每一个 ThreadLocal 对象,只能为当前线程关联一个数据,如果要...

ThreadLocal
ThreadLocal作用,解决多线程的数据安全问题
ThreadLocal 它可以给当前线程关联一个数据(可以是普通变量,可以是对象,也可以是数组,集合)
ThreadLocal 特点:

 1 ThreadLocal 可以为当前线程关联一个数据。(它可以像 Map 一样存取数据,key为当前线程)
 2 每一个 ThreadLocal 对象,只能为当前线程关联一个数据,如果要为当前线程关联多个数据,就需要使用多个ThreadLocal 对象实例。
 3 每个 ThreadLocal 对象实例定义的时候,一般都是 static 类型
 4 ThreadLocal 中保存数据,在线程销毁后。会由 JVM 虚拟自动释放

public class JdbcUtils {

    private static DruidDataSource dataSource;

    private static ThreadLocal<Connection> conns = new ThreadLocal<Connection>();

    static {
        try {
            Properties properties = new Properties();
            // 读取 jdbc.properties属性配置文件
            InputStream inputStream = JdbcUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
            // 从流中加载数据
            properties.load(inputStream);
            // 创建 数据库连接 池
            dataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

  public static Connection getConnection(){
        Connection conn = conns.get();
        if (conn == null) {
            try {
                conn = dataSource.getConnection();//从数据库连接池中获取连接
                conns.set(conn); // 保存到ThreadLocal对象中,供后面的jdbc操作使用
                conn.setAutoCommit(false); // 设置为手动管理事务
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return conn;
    }

 public static void commitAndClose(){
        Connection connection = conns.get();
        if (connection != null) { // 如果不等于null,说明 之前使用过连接,操作过数据库
            try {
                connection.commit(); // 提交 事务
            } catch (SQLException e) {
                e.printStackTrace();
            } finally {
                try {
                    connection.close(); // 关闭连接,资源资源
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        // 一定要执行remove操作,否则就会出错。(因为Tomcat服务器底层使用了线程池技术)
        conns.remove();
    }


public static void rollbackAndClose(){
        Connection connection = conns.get();
        if (connection != null) { // 如果不等于null,说明 之前使用过连接,操作过数据库
            try {
                connection.rollback();//回滚事务
            } catch (SQLException e) {
                e.printStackTrace();
            } finally {
                try {
                    connection.close(); // 关闭连接,资源资源
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        // 一定要执行remove操作,否则就会出错。(因为Tomcat服务器底层使用了线程池技术)
        conns.remove();
    }

}

    public Object queryForSingleValue(String sql, Object... args){

        Connection conn = JdbcUtils.getConnection();

        try {
            return queryRunner.query(conn, sql, new ScalarHandler(), args);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);   // BaseDAO 把异常抛出去
        }
    }

public class TransactionFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        try {
            filterChain.doFilter(servletRequest,servletResponse);
            JdbcUtils.commitAndClose();// 提交事务
        } catch (Exception e) {
            JdbcUtils.rollbackAndClose();//回滚事务
            e.printStackTrace();
            throw new RuntimeException(e);//把异常抛给Tomcat管理展示友好的错误页面
        }
    }

    @Override
    public void destroy() {

    }
}

<filter>
        <filter-name>TransactionFilter</filter-name>
        <filter-class>com.alex.filter.TransactionFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>TransactionFilter</filter-name>
        <!-- /* 表示当前工程下所有请求 -->
        <url-pattern>/*</url-pattern>
    </filter-mapping>

 <!--error-page标签配置,服务器出错之后,自动跳转的页面-->
    <error-page>
        <!--error-code是错误类型-->
        <error-code>500</error-code>
        <!--location标签表示。要跳转去的页面路径-->
        <location>/pages/error/error500.jsp</location>
    </error-page>

    <!--error-page标签配置,服务器出错之后,自动跳转的页面-->
    <error-page>
        <!--error-code是错误类型-->
        <error-code>404</error-code>
        <!--location标签表示。要跳转去的页面路径-->
        <location>/pages/error/error404.jsp</location>
    </error-page>

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。