如何提供一组支持事务的工作流API
2007-02-27 14:17
507 查看
应用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();
}
}
这个功能的实现是利用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();
}
}
相关文章推荐
- Windows如何提供大内存支持(转)
- 免费超大量邮件发送服务Amazon SES和Mailgun提供SMTP和API支持
- iPhone 6/6 Plus 出现后,如何改进工作流以实现一份设计稿支持多个尺寸?
- 通过beego快速创建一个Restful风格API项目及API文档自动化 本文演示如何快速(一分钟内,不写一行代码)的根据数据库及表创建一个Restful风格的API项目,及提供便于在线测试API的界
- 如何为技术支持工程师提供DOORS .mod目录
- Python:一个小小程序,如何删除一组进程,而且只提供程序名而不需要pid。
- 如何为自定义属性提供表达式绑定支持
- 如何利用Ubuntu SDK提供的Organizer API来管理我们的日历
- 如何利用UCenter提供的uc_pm_send发站内短信以及UC_API的解决方法
- 【云计算】docker daemon如何提供Restful的API
- 如何调用别人提供的API?
- Dom元素基本操作方法API,先记录下,方便以后使用。 W3C DOM和JavaScript很容易混淆不清。DOM是面向HTML和XML文档的API,为文档提供了结构化表示,并定义了如何通过脚本
- 如何为自定义属性提供表达式绑定支持
- Hibernate各类概念-如何支持事务
- 如何给别人提供支持库
- JNBridge提供了跨越Java与.NET代码的分布式事务支持
- Holder 可直接在客户端渲染图片的占位。支持在线和离线,提供一个链式 API 对图像占位进行样式处理。
- Cordova提供了一组设备相关的API,通过这组API,移动应用能够以JavaScript访问原生的设备功能,如摄像头、麦克风等。
- 免费超大量邮件发送服务Amazon SES和Mailgun提供SMTP和API支持
- 如何利用Revit API提供的阵列方法