Activiti工做流引擎自己配套了包括User、Group的Identify模塊,可是實際上公司內部各個部門關係、領導下級等關係都很複雜,Activiti自身的id模塊就顯得有些弱了。java
有關自定義Activiti用戶羣組表的具體方式有三種,本文只詳細介紹第二種:spring
方案一:經過數據推送方式同步數據到引擎的身份表,須要把數據備份到引擎的身份表或者公司有平臺或者WebService推送用戶數據的推薦使用數據庫
方案二:自定義SessionFactory,非侵入式替換接口實現,對於公司內部有統一身份訪問接口的推薦使用ide
方案三:不須要編寫Java代碼,只須要建立同名視圖便可學習
引擎內部與數據庫交互使用的是MyBatis,Activiti的每一張表都有一個對應的XxxEntityManager(實體管理類,有接口和實現類)和XxxEntityManagerFactory(實體管理工廠類)。this
引擎的7個Service接口在須要CRUD實體時會根據接口獲取註冊的實體管理器實現類(初始化引擎時引擎會使用Map對象維護二者的映射關係),而引擎容許咱們本身註冊實體管理器實現類,查看源碼後能夠知道有關Identity操做的兩個接口分別爲:UserIdentityManager和GroupIdentityManager。spa
例以下圖:code
User和Group同理,這裏以User實體管理類舉例,其繼承的AbstractManager實現了Session。xml
查看引擎配置對象ProcessEngineConfigurationImpl類能夠找到一個名稱爲「customSessionFactories」的屬性,該屬性能夠用來自定義SessionFactory(從上文能夠看到每個XxxEntityManager都是一個Session<實現了Session接口>,並由SessionFactory來管理)對象
爲了能替代內部的實體管理器實現類,咱們能夠自定義一個SessionFactory並註冊到引擎。
這種自定義SessionFactory的方式適用於公司內部有獨立的身份系統或者公共的身份模塊的狀況,全部和用戶、角色、權限的服務均經過一個統一的接口獲取,而業務系統則不保存這些數據,此時引擎不會再使用本來的身份模塊表(ACT_ID_*)。
配置文件:
<bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration"> ... ... <!-- 自定義用戶、用戶組的配置 --> <property name="customSessionFactories"> <list> <bean class="xxx.xxx.xxx.xxx.CustomUserEntityManagerFactory"> <property name="customUserEntityManager"> <bean class="xxx.xxx.xxx.xxx.CustomUserEntityManager"> <property name="CustomUserManager"> <bean class="xxx.xxx.xxx.xxx.CustomUserManager"/> </property> </bean> </property> </bean> <bean class="xxx.xxx.xxx.xxx.CustomGroupEntityManagerFactory"> <property name="customGroupEntityManager"> <bean class="xxx.xxx.xxx.xxx.CustomGroupEntityManager"> <property name="customGroupManager"> <bean class="xxx.xxx.xxx.xxx.CustomGroupManager"/> </property> </bean> </property> </bean> </list> </property> </bean>
以自定義User爲例
1、須要自定義對應的SessionFactory,這裏是你可否成功註冊自定義管理類的關鍵,getSessionType()是返回給引擎XxxEntityManager的接口(前文有說),然後經過openSession()返回給引擎你自定義的CustomXxxEntityManager。
public class CustomUserEntityManagerFactory implements SessionFactory { private CustomUserEntityManager customUserEntityManager; public void setCustomUserEntityManager(CustomUserEntityManager customUserEntityManager) { this.customUserEntityManager = customUserEntityManager; } @Override public Class<?> getSessionType() { // 返回原始的UserManager類型 return UserIdentityManager.class; } @Override public Session openSession() { // 返回自定義的UserManager實例 return customUserEntityManager; } }
2、須要完成自定義的CustomXxxEntityManager類,這裏我只覆蓋了兩種方法,其中CustomUserManager類與引擎無關,你能夠在裏面注入dao層接口(dao層接口和實現類,與CustomUserManager類分開能夠方便往後維護)
public class CustomUserEntityManager extends UserEntityManager { private CustomUserManager customUserManager; public void setCustomUserManager(CustomUserManager customUserManager) { this.customUserManager = customUserManager; } @Override public BpmUser findUserById(String userId) { return customUserManager.findUserById(userId); } @Override public List<Group> findGroupsByUser(String userId) { return customUserManager.findGroupsByUser(userId); } }
3、使用,由於咱們已經成功註冊即覆蓋了引擎自帶的管理類,因此直接使用service中的方法便可
Boolean judge = processEngine.getIdentityService() .checkPassword(bpmUser.getUserId(),bpmUser.getUserPasswd());
此種方法不是爲所欲爲的。首先,由於是引擎啓動後咱們自定義的管理類才被註冊進去,而service中的方法是引擎啓動前源碼就定義好的,因此你只能重寫引擎管理類中已有的那幾個方法。
其次,重寫主要的限制在於返回值,譬如上文我重寫了兩個方法,我自定義的BpmUser必需要繼承引擎自帶的User。另外一個方法的返回值List<Group>更麻煩,個人BpmGroup不只僅須要繼承Group,更須要在裝填List時「偷樑換柱」,以下,若是你直接返回bpmGroupList是必定會報錯的!
public List<Group> findGroupsByUser(String userId) { List<BpmGroup> bpmGroupList=customUserDao.findGroupsByUser(userId); List<Group> groupList = new ArrayList<>(); for (BpmGroup bpmGroup:bpmGroupList){ groupList.add(bpmGroup); } return groupList; }
歡迎留言,歡迎聯繫我,互相學習, QQ:1144901177
但願轉載的時候能夠貼上本文地址,感謝!