使用Filter和ThreadLocal对JAVAWeb工程进行事务管理以处理异常并利用Tomcat进行页面跳转注意事项

在JAVAWeb工程中,需要利用JDBC对数据库进行交互,而如果在一次操作中有多个JDBC操作,但是异常发生在JDBC操作的中间,这时就会出现仅完成异常出现前的JDBC操作,会得到错误的结果,需要避免。

在数据库中,为了防止上述错误的发生,需要进行事务管理。
事务管理的原理:
在这里插入图片描述
发生异常时使事务进行回滚,之前的操作都会被回滚,无异常则提交。

注意:
在这里插入图片描述

JDBCUtils工具类获取连接、提交、回滚关闭连接:

 /**
     * 获取存入ThreadLocal中的连接
     * @return
     */
    public static Connection getConnection() {
        Connection connection = threadLocal.get();

        if (connection == null) {
            // threadLocal中为空,第一次获取,从连接池中获取
            try {
                connection = dataSource.getConnection();

                // 放入ThreadLocal中供后续JDBC操作使用
                threadLocal.set(connection);

                // 创建连接的时候就设置为手动管理事务
                connection.setAutoCommit(false);

            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        return connection;
    }

ThreadLocal一定要执行 remove 操作,否则就会出错!
因为 Tomcat 服务器底层使用了线程池技术。

/**
     * 提交事务并关闭释放连接
     */
    public static void commitAndClose() {
        Connection connection = threadLocal.get();
        if (connection != null) {
            try {
                // 提交事务
                connection.commit();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }finally {
                try {
                    connection.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
        }
        /**
         * 一定要执行 remove 操作,否则就会出错!
         * (因为 Tomcat 服务器底层使用了线程池技术)
         */
        threadLocal.remove();
    }
/**
     * 回滚事务并关闭释放连接
     */
    public static void rollbackAndClose() {
        Connection connection = threadLocal.get();
        if (connection != null) {
            try {
                // 回滚事务
                connection.rollback();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }finally {
                try {
                    connection.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
        }
        /**
         * 一定要执行 remove 操作,否则就会出错!
         * (因为 Tomcat 服务器底层使用了线程池技术)
         */
        threadLocal.remove();
    }

由于工程中所有程序都需要进行事务处理,所以使用Filter过滤器对所有程序进行异常判断,出现异常则回滚,否则提交:

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();
            // 将异常抛给Tomcat服务器,以跳转页面
            throw new RuntimeException(e);
        }
    }

web.xml中对Filter进行配置:
在这里插入图片描述

注意:
由于使用Filter在Servlet层才对异常进行事务处理,所以需要保证异常能抛到Servlet层,即子程序的异常都需要抛出,即BaseDAO和BaseServlet的异常都需要向上抛出;

BaseDAO:

public abstract class BaseDAO {
    //使用DbUtils操作数据库
    private QueryRunner queryRunner = new QueryRunner();

    /**
     * 更新数据库操作
     */
    public int Update(String sql,Object ...params){
        Connection connection = JDBCUtils.getConnection();
        try {
            queryRunner.update(connection,sql,params);
            return 1;
        } catch (SQLException throwables) {
            throwables.printStackTrace();
            /**
             * 因为DAO层捕获异常之后不抛出的话,
             * 后续的DAO及Service层无法对异常进行回滚处理,
             * 所以必须向上抛出异常以供处理
             */
            throw new RuntimeException(throwables);
        }
    }

BaseServlet:

@Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String action = request.getParameter("action");
        try {
            // 获取action业务鉴别字符串,获取相应的业务 方法反射对象
            Method method = this.getClass().getDeclaredMethod
                    (action, HttpServletRequest.class, HttpServletResponse.class);

            // 调用目标业务方法
            method.invoke(this, request, response);

        } catch (Exception e) {
            e.printStackTrace();
            // 抛出异常
            throw new RuntimeException(e);
        }
    }

注意Filter捕获异常进行回滚之后,也要将异常抛出给Tomcat服务器,这样Tomcat才能进行页面跳转:
在这里插入图片描述

使用Tomcat进行错误页面跳转:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Dame'Seven

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值