一、先看一下spring配置文件中的配置内容:
1、首先设置数据源dataSource:
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:conf/jdbc.properties</value>
</list>
</property>
</bean>
1 <bean id="dataSource" destroy-method="close" class="org.apache.commons.dbcp.BasicDataSource"> 2 <property name="driverClassName"> 3 <value>${driverClassName}</value> 4 </property> 5 <property name="url"> 6 <value>${urlAddr}</value> 7 </property> 8 <property name="username"> 9 <value>${username}</value> 10 </property> 11 <property name="password"> 12 <value>${password}</value> 13 </property> 14 <property name="maxActive"> 15 <value>${maxActive}</value> 16 </property> 17 <property name="maxIdle"> 18 <value>${maxIdle}</value> 19 </property> 20 <property name="minIdle"> 21 <value>${minIdle}</value> 22 </property> 23 <property name="maxWait"> 24 <value>${maxWait}</value> 25 </property> 26 <property name="timeBetweenEvictionRunsMillis"> 27 <value>${timeBetweenEvictionRunsMillis}</value> 28 </property> 29 <property name="minEvictableIdleTimeMillis"> 30 <value>${minEvictableIdleTimeMillis}</value> 31 </property> 32 <property name="testWhileIdle"> 33 <value>${mysqlTestWhileIdle}</value> 34 </property> 35 <property name="testOnReturn" value="true" /> 36 <property name="testOnBorrow" value="true"/> 37 <property name="validationQuery"> 38 <value>${mysqlValidationQuery}</value> 39 </property> 40 <property name="removeAbandoned"> 41 <value>true</value> 42 </property> 43 <property name="removeAbandonedTimeout"> 44 <value>180</value> 45 </property> 46 </bean>
2、设置Osworkflow:
<bean id="workflowStore" class="com.opensymphony.workflow.spi.jdbc.ExtMySQLWorkflowStore" init-method="init"> <property name="dataSource" ref="dataSource"></property> <property name="map"> <map> <entry key="step.sequence.increment" value="INSERT INTO OS_STEPIDS (ID) values (null)"> </entry> <entry key="step.sequence.retrieve" value="SELECT max(ID) FROM OS_STEPIDS"> </entry> <entry key="entry.sequence.increment" value="INSERT INTO os_entryids (ID) values (null)"> </entry> <entry key="entry.sequence.retrieve" value="SELECT max(ID) FROM os_entryids"> </entry> <entry key="entry.sequence" value="SELECT max(id)+1 FROM OS_WFENTRY"/> <entry key="entry.table" value="OS_WFENTRY"/> <entry key="entry.id" value="ID"/> <entry key="entry.name" value="NAME"/> <entry key="entry.state" value="STATE"/> <entry key="step.sequence" value="SELECT max(ID)+1 FROM OS_STEPIDS"/> <entry key="step.sequence.increment" value="INSERT INTO OS_STEPIDS (ID) values (null)"/> <entry key="step.sequence.retrieve" value="SELECT max(ID) FROM OS_STEPIDS"/> <entry key="history.table" value="OS_HISTORYSTEP"/> <entry key="current.table" value="OS_CURRENTSTEP"/> <entry key="historyPrev.table" value="OS_HISTORYSTEP_prev"/> <entry key="currentPrev.table" value="OS_CURRENTSTEP_prev"/> <entry key="step.id" value="ID"/> <entry key="step.entryId" value="ENTRY_ID"/> <entry key="step.stepId" value="STEP_ID"/> <entry key="step.actionId" value="ACTION_ID"/> <entry key="step.owner" value="OWNER"/> <entry key="step.caller" value="CALLER"/> <entry key="step.startDate" value="START_DATE"/> <entry key="step.finishDate" value="FINISH_DATE"/> <entry key="step.dueDate" value="DUE_DATE"/> <entry key="step.status" value="STATUS"/> <entry key="step.divviousId" value="divVIOUS_ID"/> </map> </property> </bean> <bean id="workflowFactory" class="com.opensymphony.workflow.loader.XMLWorkflowFactory" init-method="initDone"/> <bean id="workflowConfiguration" class="com.opensymphony.workflow.config.SpringConfiguration"> <property name="store" ref="workflowStore"/> <property name="factory" ref="workflowFactory"/> </bean> <bean id="workflowTypeResolver" class="com.opensymphony.workflow.util.SpringTypeResolver"/> <bean id="workflow" class="com.jd.bse.osworkflow.ExtBasicWorkflow" scope="prototype"> <constructor-arg value="bjjdz"/> <property name="configuration" ref="workflowConfiguration"/> <property name="resolver" ref="workflowTypeResolver"/> </bean>
3、事务管理器:
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<tx:annotation-driven transaction-manager="txManager"/>
<bean id="sharedTransactionTemplate"
class="org.springframework.transaction.support.TransactionTemplate">
<constructor-arg ref="txManager"></constructor-arg>
<property name="isolationLevelName" value="ISOLATION_READ_UNCOMMITTED"/>
<property name="timeout" value="30"/>
</bean>
4、首先看类ExtMySQLWorkflowStore,与最顶层接口继承关系是ExtMySQLWorkflowStore->MySQLWorkflowStore->JDBCWorkflowStore->WorkflowStore,除了自定义扩展的ExtMySQLWorkflowStore。其它都是osworkflow自带类或者接口,首先看ExtMySQLWorkflowStore类:
public class ExtMySQLWorkflowStore extends MySQLWorkflowStore { //防止并发 private ThreadLocal<Connection> threadlocal = new ThreadLocal<Connection>();//当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本 private Map<String,String> map;//对应上面spring配置文件中workflowStore中的map,传递参数 private DataSource dataSource;//对应spring配置文件中的dataSource,设置数据源 public void init() throws StoreException { if(null!=map){ map.put("datasource",null); } super.init(map); super.ds=dataSource; } public Connection getConnection() throws SQLException{ Connection con = threadlocal.get(); if((null != con) && !con.isClosed()){ System.out.println("getConnection"+con.hashCode()); return con ; }else{ con = super.ds.getConnection(); System.out.println("|-------------"+Thread.currentThread().getId()); setConnection(con); System.out.println("super.ds.getConnection"+con.hashCode()); return con; } } public void setConnection(Connection connection) { threadlocal.set(connection); // this.connection = connection; } public Map<String, String> getMap() { return map; } public void setMap(Map<String, String> map) { this.map = map; } public DataSource getDataSource() { return dataSource; } public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; } @Override public PropertySet getPropertySet(long entryId) { HashMap args = new HashMap(1); args.put("globalKey", "osff_" + entryId); PropertySet ps= PropertySetManager.getInstance("memory", args); ps.setString("col.globalKey","GLOBAL_KEY"); ps.setString("col.itemKey","ITEM_KEY"); ps.setString("col.itemType","ITEM_TYPE"); ps.setString("col.string","STRING_VALUE"); ps.setString("col.date","DATE_VALUE"); ps.setString("col.data","DATA_VALUE"); ps.setString("col.float","FLOAT_VALUE"); ps.setString("col.number","NUMBER_VALUE"); return ps; } }
5、再看MySQLWorkflowStore:
public class MySQLWorkflowStore extends JDBCWorkflowStore { //~ Instance fields private String _stepSequenceIncrement = null; private String _stepSequenceRetrieve = null; //~ Methods public void init(Map props) throws StoreException { super.init(props); _stepSequenceIncrement = (String) props.get("step.sequence.increment"); _stepSequenceRetrieve = (String) props.get("step.sequence.retrieve"); } protected long getNextStepSequence(Connection c) throws SQLException { PreparedStatement stmt = null; ResultSet rset = null; try { stmt = c.prepareStatement(_stepSequenceIncrement); stmt.executeUpdate(); rset = stmt.executeQuery(_stepSequenceRetrieve); rset.next(); long id = rset.getLong(1); return id; } finally { cleanup(null, stmt, rset); } } }
6、再看JDBCWorkflowStore,因为代码比较长,所以一个片段一个片段讲:
public class JDBCWorkflowStore implements WorkflowStore
首先定义一些属性:
protected DataSource ds; protected String currentPrevTable; protected String currentTable; protected String entryId; protected String entryName; protected String entrySequence; protected String entryState; protected String entryTable; protected String historyPrevTable; protected String historyTable; protected String stepActionId; protected String stepCaller; protected String stepDueDate; protected String stepEntryId; protected String stepFinishDate; protected String stepId; protected String stepOwner; protected String stepPreviousId; protected String stepSequence; protected String stepStartDate; protected String stepStatus; protected String stepStepId; protected boolean closeConnWhenDone = false;
然后在init方法中初始化这些变量:
public void init(Map props) throws StoreException { entrySequence = getInitProperty(props, "entry.sequence", "SELECT nextVal('seq_os_wfentry')"); stepSequence = getInitProperty(props, "step.sequence", "SELECT nextVal('seq_os_currentsteps')"); entryTable = getInitProperty(props, "entry.table", "OS_WFENTRY"); entryId = getInitProperty(props, "entry.id", "ID"); entryName = getInitProperty(props, "entry.name", "NAME"); entryState = getInitProperty(props, "entry.state", "STATE"); historyTable = getInitProperty(props, "history.table", "OS_HISTORYSTEP"); currentTable = getInitProperty(props, "current.table", "OS_CURRENTSTEP"); currentPrevTable = getInitProperty(props, "currentPrev.table", "OS_CURRENTSTEP_PREV"); historyPrevTable = getInitProperty(props, "historyPrev.table", "OS_HISTORYSTEP_PREV"); stepId = getInitProperty(props, "step.id", "ID"); stepEntryId = getInitProperty(props, "step.entryId", "ENTRY_ID"); stepStepId = getInitProperty(props, "step.stepId", "STEP_ID"); stepActionId = getInitProperty(props, "step.actionId", "ACTION_ID"); stepOwner = getInitProperty(props, "step.owner", "OWNER"); stepCaller = getInitProperty(props, "step.caller", "CALLER"); stepStartDate = getInitProperty(props, "step.startDate", "START_DATE"); stepFinishDate = getInitProperty(props, "step.finishDate", "FINISH_DATE"); stepDueDate = getInitProperty(props, "step.dueDate", "DUE_DATE"); stepStatus = getInitProperty(props, "step.status", "STATUS"); stepPreviousId = getInitProperty(props, "step.previousId", "PREVIOUS_ID"); String jndi = (String) props.get("datasource"); if (jndi != null) { try { ds = (DataSource) lookup(jndi); if (ds == null) { ds = (DataSource) new javax.naming.InitialContext().lookup(jndi); } } catch (Exception e) { throw new StoreException("Error looking up DataSource at " + jndi, e); } } }
其它主要还有一些方法就是对osworkflow表的操作。