从零开始写javaweb框架 (4)

时间:2021-06-26 13:09:27

  今天是我要记录javaweb框架的最后一篇文章了,后面的内容主要是利用其他的一些开源中间件来完成一些功能,所以想了解后面的内容可以看从零开始写javaweb框架这本书,这本书非常的好。我基本也是按着这书一步一步的做的,只是有时候需要自己再进行一个梳理。

  今天讲的是在AOP中添加事务。我们主要针对Service层中带有Transaction方法进行事务控制。

  事务控制结合AOP是非常简单的,只不过在处理Service方法的前后添加事务的控制而已,但是有两个点需要注意的是

  1. 每个线程不可以共享同一连接,否则线程1可能关闭线程2的连接,导致线程2的连接报错。
  2. 在目前的AOP框架中是无法实现调用Servlet的API的,如果需要使用就必须要将request和response对象传递给Controller中的Action方法,这必然会增加Controller和Servlet API之间的耦合。

  我们现在来写事务控制的代理类,再慢慢来解决上面两个问题。

public Object doProxy(ProxyChain proxyChain) throws Throwable {
    Object result;
    boolean flag = FLAG_HOLDER.get();
    Method method = proxyChain.getTargetMethod();
    if(!flag && method.isAnnotationPresent(Transaction.class)){
        FLAG_HOLDER.set(true);
        try {
            DatabaseHelper.beginTransaction();
            LOGGER.debug("begin tranaction");
            result = proxyChain.doProxyChain();
            DatabaseHelper.commitTransaction();
            LOGGER.debug("commit tranaction");
        } catch (Exception e) {
            DatabaseHelper.rollbackTransaction();
            LOGGER.debug("rollback tranaction");
            throw new RuntimeException();
        }
    }else{
        result = proxyChain.doProxyChain();
    }
    return result;
}

FLAG_HOLDER是保存在ThreadLocal中的布尔变量,保证同一线程中事务控制相关逻辑只会执行一次。这个代理类非常的简单,现在我们来解决第一个问题--连接共享问题

  使用ThreadLocal存放连接,保证每个线程有自己独立的连接副本。使用静态块来进行初始化即可。

//使用ThreadLocal 存放连接,保证每个连接有自己独立的连接
private static final ThreadLocal<Connection> CONNECTION_HOLDER;
static {
    CONNECTION_HOLDER = new ThreadLocal<Connection>();
}

  我们来解决第二个问题,我们将request、response、session等对象进行封装,并提供一些常用的Servlet API并在DispatcherServlet中进行初始化,如此一来整个框架都可以使用基础的Servlet API方法。

/**
 * 每个线程拥有一份ServletHelper实例
 */
private static final ThreadLocal<ServletHelper> SERVLET_HELPER_HOLDER = 
        new ThreadLocal<ServletHelper>();

private HttpServletRequest request;
private HttpServletResponse response;

public ServletHelper(HttpServletRequest request,
        HttpServletResponse response) {
    this.request = request;
    this.response = response;
}
//......其他常用方法的调用

  在这几节中,我主要是对从零开始写javaweb框架里面几个我自己没看懂觉得需要梳理的地方进行了大致的梳理!如果你有地方没看懂可以看一下那本书,书里面有不懂的也欢迎留言来探讨一下~~~