事务管理

        当每个执行JDBC的类都需要执行回滚和提交的操作,如下:

         那么如果有的DAO成功提交,有的需要回滚。但是service的操作需要是一个整体,不能部分成功,部分失败。所以事务管理应该以业务层的方法为单位,而不能以DAO层的单精度方法为单位。

        所以应该将上图中的try...catch...语句执行的内容转到service中。但因为servlet对应一个service,service又被filter拦截,所以可以将事务提交转移到filter中,如下:

        Notations:DAO1、2、3中的数据库连接Connection需要同一个。因此需要ThreadLocal本地线程。里面有set和get方法,将Connection设置到线程中。

OpenSessionFilter:

        先写一个开始、提交和回滚事务的工具类,如下所示:        

public class TransManager {
    //本地线程存储连接方便各个DAO方法使用
    private static ThreadLocal<Connection> threadLocal=new ThreadLocal<Connection>();

    //开始事务
    public void startTrans() throws SQLException {
        this.getConnection().setAutoCommit(false);
    }

    //提交事务
    public void commitTrans() throws SQLException {
        this.getConnection().commit();
        //因为这里的提交和回滚函数都是在filter处理响应的时候才执行,所以要执行关闭连接的操作
        this.getConnection().close();
    }

    //回滚事务
    public void rollTrans() throws SQLException {
        this.getConnection().rollback();
        this.getConnection().close();
    }

    private Connection getConnection() throws SQLException{
        Connection con=threadLocal.get();
        if(con==null){
            //发现threadLocal里面没有connection,就获取并设置
            //放在threadLocal里面就是为了一个DAO调用后再给下一个调用
            con=DButil.getConnection();
            threadLocal.set(con);
        }
        return con;
    }

}

         然后在Filter的doFilter方法中进行事务的管理      

 @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        TransManager tm=new TransManager();
        try {
            tm.startTrans();
            filterChain.doFilter(servletRequest,servletResponse);
            tm.commitTrans();
        } catch (SQLException e) {
            try {
                tm.rollTrans();
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
            e.printStackTrace();
        }

    }

ThreadLocal

        ThreadLocal的set(obj)方法。源码如下:    

public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            map.set(this, value);
        } else {
            createMap(t, value);
        }
    }

        首先获取了当前的线程。每个线程都有一个容器(ThreadLocalMap)。map.set(this)就是将ThreadLocal作为key,因为我们的组件中需要传输的对象可能有多个。后面的createMap是初始化Map。

        set的源码如下:

public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null) {
                @SuppressWarnings("unchecked")
                T result = (T)e.value;
                return result;
            }
        }
        return setInitialValue();
    }

        其中this指的是ThreadLocal对象,通过它才知道是哪个ThreadLocalMap。entry.value是获取工具箱。

Listener(监听器)

        Servlet规范中定义的一种特殊类,它用于监听Web应用程序中的ServletContext,HttpSession 和HttpServletRequest等域对象的创建与销毁事件,以及监听这些域对象中的属性发生修改的事件。

        部分示例:

        1,ServletContextListener-监听ServletContext对象的创建和销毁的过程

        2,HttpSessionListener-同理

        3,ServletRequestListener

        4,ServletContextAttributeListener-监听ServletContext的保存域的改动

        5,HttpSessionBindingListener-监听某个对象在session中的绑定与移除

        

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值