如何提供一组支持事务的工作流API

    技术2022-05-11  58

    应用Spring事务管理的功能可以把一组普通的API转换为支持事务的API.

    这个功能的实现是利用spring 事务管理的特性: 同一个事务中,其所有应用访问数据库时只维护了一个connection来访问数据库.

    这样我们就能通过判断当前LocalThread上下文环境,来决定Connection是否进行commite(),close()等操作.

    我们首先需要构造一个WFConnection类,它实现了Connection接口.WFConnection对象可以通过访问LocalThread上下问环境来判断是否进行commite(),close()等操作.

     

    /**  * 能够动态的识别数据库connection请求到底来自wfapi还是工作流系统内部 * 对connection进行调用  */ public   class  WFSpringConnection  implements  Connection {     private  Connection myConnection  =   null ;         private  org.apache.commons.logging.Log __log  =  LogFactory.getFactory().getInstance( this .getClass());     public  WFSpringConnection(Connection connection) {        myConnection  =  connection;    }     public   void  initProxyConnection(Connection connection) {        myConnection  =  connection;    }     public   void  close()  throws  SQLException {        String threadName  = Thread.currentThread().getName();        __log.debug( " call WFSpringConnection close()   threadName: " + threadName);         if ( ! isSpringCall()){            myConnection.close();        }    }     public   void  commit()  throws  SQLException {                String threadName  = Thread.currentThread().getName();        __log.debug( " call WFSpringConnection commit()   threadName: " + threadName);         if ( ! isSpringCall()){            myConnection.commit();        }    }

     /**  * 判断当前线程是否被spring管理  * @return true 被spring管理的应用调用  */ public boolean isSpringCall(){  boolean isCall =false;  Object o = WFAPIContext.get(WFAPIAspect.WFAPI_THREAD_REQUEST_LABEL);  if(o!=null){   String threadLabel = (String)o;   if(threadLabel.compareTo(WFAPIAspect.WFAPI_THREAD_REQUEST_LABEL)==0){    isCall= true;   }  }  __log.debug(" isSpringCall: "+isCall);  return isCall; }

    ..................... ............... ... }

     

    LocalThread上下文环境,可以通过继承InheritableThreadLocal类来实现.

     

    /**  * 构造可继承线程 * 在创建子线程时,子线程会接收所有可继承的线程局部变量的初始值,以获得父线程所具有的值。 * 应用了“线程局部变量”技术。充当存储或检索一个值时的间接句柄。 *  @author   *  */ class  ThreadLocalMap  extends  InheritableThreadLocal {         public   final  Object childValue(Object parentValue) {         // Hashtable中的方法是同步的,而HashMap中的方法在缺省情况下是非同步的。         // 即是说,在多线程应用程序中,不用专门的操作就安全地可以使用Hashtable了;而对于HashMap,则需要额外的同步机制。         Hashtable ht  =  (Hashtable) parentValue;                 if  (ht  !=   null ) {             return  ht.clone();        }  else  {             return   null ;        }    }} /**  * 工作流API调用时所提供的上下文环境 *  @author   *  */ public   class  WFAPIContext {     final   static  WFAPIContext wfAPIContext  =   new  WFAPIContext();     static   final   int  HT_SIZE  =   7 ;    Object tlm;     private  WFAPIContext() {        tlm  =   new  ThreadLocalMap();    }      public   static   void  put(String key, Object o) {         wfAPIContext.put0(key, o);    }     public   static  Object get(String key) {         return  wfAPIContext.get0(key);    }       public   static   void  remove(String key) {          wfAPIContext.remove0(key);    }     public   static  Hashtable getContext() {         return  wfAPIContext.getContext0();    }     private   void  put0(String key, Object o) {        Hashtable ht  =  (Hashtable) ((ThreadLocalMap) tlm).get();         if  (ht  ==   null ) {            ht  =   new  Hashtable(HT_SIZE);            ((ThreadLocalMap) tlm).set(ht);        }        ht.put(key, o);    }     private  Object get0(String key) {        Hashtable ht  =  (Hashtable) ((ThreadLocalMap) tlm).get();         if  (ht  !=   null   &&  key  !=   null ) {             return  ht.get(key);        }  else  {             return   null ;        }    }     private   void  remove0(String key) {        Hashtable ht  =  (Hashtable) ((ThreadLocalMap) tlm).get();         if  (ht  !=   null ) {            ht.remove(key);        }    }     private  Hashtable getContext0() {         return  (Hashtable) ((ThreadLocalMap) tlm).get();    }}

     

     


    最新回复(0)