專案中加入activiti後,使用者許可權管理處理的三種方式
相信每個涉及到使用者的系統都有一套使用者許可權管理平臺或者模組,用來維護使用者以及在系統內的功能、資料許可權,我們使用的Activiti工作流引擎配套設計了包括User、Group的Identify模組,怎麼和業務資料同步呢,這個問題是每個新人必問的問題之一,下面介紹幾種同步方案,最後總結比較。
方案一:呼叫IdentifyService介面完成同步
介面定義:
[java]- importjava.util.List;
- importcom.foo.arch.entity.id.User;
- importcom.foo.arch.service.ServiceException;
- /**
- * 維護使用者、角色、許可權介面
- * @author HenryYan
- */
- public interface AccountService {
- /**
- * 新增使用者並[同步其他資料庫]
- * <ul>
- * <li>step 1: 儲存系統使用者,同時設定和部門的關係</li>
- * <li>step 2: 同步使用者資訊到activiti的identity.User,同時設定角色</li>
- * </ul>
- * @param user 使用者物件
- * @param orgId 部門ID
- * @param roleIds 角色ID集合
- * @param synToActiviti 是否同步到Activiti資料庫,通過配置檔案方式設定,使用屬性:account.user.add.syntoactiviti
- * @throws OrganizationNotFoundException 關聯使用者和部門的時候從資料庫查詢不到哦啊部門物件
- * @throws Exception 其他未知異常
- */
- public void save(User user, Long orgId, List<long> roleIds, booleansynToActiviti)
- throws OrganizationNotFoundException, ServiceException, Exception;
- /**
- * 刪除使用者
- * @param userId 使用者ID
- * @param synToActiviti 是否同步到Activiti資料庫,通過配置檔案方式設定,使用屬性:account.user.add.syntoactiviti
- * @throws Exception
- */
- public void delete(Long userId, booleansynToActiviti) throwsServiceException, Exception;
- /**
- * 同步使用者、角色資料到工作流
- * @throws Exception
- */
- public void synAllUserAndRoleToActiviti() throwsException;
- /**
- * 刪除工作流引擎Activiti的使用者、角色以及關係
- * @throws Exception
- */
- public void deleteAllActivitiIdentifyData() throwsException;
- }
同步單個介面實現片段:
[java]- @Service
- @Transactional
- public class AccountServiceImpl implements AccountService {
- /**
- * 儲存使用者資訊,並且同步使用者資訊到activiti的identity.User和identify.Group
- * @param user 使用者物件{@link User}
- * @param roleIds 使用者擁有的角色ID集合
- * @param synToActiviti 是否同步資料到Activiti
- * @see Role
- */
- public void saveUser(User user, List<long> roleIds, booleansynToActiviti) {
- String userId = ObjectUtils.toString(user.getId());
- // 儲存系統使用者
- accountManager.saveEntity(user);
- // 同步資料到Activiti Identify模組
- if(synToActiviti) {
- UserQuery userQuery = identityService.createUserQuery();
- List<org.activiti.engine.identity.user> activitiUsers = userQuery.userId(userId).list();
- if(activitiUsers.size() == 1) {
- updateActivitiData(user, roleIds, activitiUsers.get(0));
- }elseif (activitiUsers.size() > 1) {
- String errorMsg = "發現重複使用者:id="+ userId;
- logger.error(errorMsg);
- thrownew RuntimeException(errorMsg);
- }else{
- newActivitiUser(user, roleIds);
- }
- }
- }
- /**
- * 新增工作流使用者以及角色
- * @param user 使用者物件{@link User}
- * @param roleIds 使用者擁有的角色ID集合
- */
- private void newActivitiUser(User user, List<long> roleIds) {
- String userId = user.getId().toString();
- // 新增使用者
- saveActivitiUser(user);
- // 新增membership
- addMembershipToIdentify(roleIds, userId);
- }
- /**
- * 新增一個使用者到Activiti {@link org.activiti.engine.identity.User}
- * @param user 使用者物件, {@link User}
- */
- private void saveActivitiUser(User user) {
- String userId = user.getId().toString();
- org.activiti.engine.identity.User activitiUser = identityService.newUser(userId);
- cloneAndSaveActivitiUser(user, activitiUser);
- logger.debug("add activiti user: {}", ToStringBuilder.reflectionToString(activitiUser));
- }
- /**
- * 新增Activiti Identify的使用者於組關係
- * @param roleIds 角色ID集合
- * @param userId 使用者ID
- */
- private void addMembershipToIdentify(List<long> roleIds, String userId) {
- for(Long roleId : roleIds) {
- Role role = roleManager.getEntity(roleId);
- logger.debug("add role to activit: {}", role);
- identityService.createMembership(userId, role.getEnName());
- }
- }
- /**
- * 更新工作流使用者以及角色
- * @param user 使用者物件{@link User}
- * @param roleIds 使用者擁有的角色ID集合
- * @param activitiUser Activiti引擎的使用者物件,{@link org.activiti.engine.identity.User}
- */
- private void updateActivitiData(User user, List<long> roleIds, org.activiti.engine.identity.User activitiUser) {
- String userId = user.getId().toString();
- // 更新使用者主體資訊
- cloneAndSaveActivitiUser(user, activitiUser);
- // 刪除使用者的membership
- List<group> activitiGroups = identityService.createGroupQuery().groupMember(userId).list();
- for(Group group : activitiGroups) {
- logger.debug("delete group from activit: {}", ToStringBuilder.reflectionToString(group));
- identityService.deleteMembership(userId, group.getId());
- }
- // 新增membership
- addMembershipToIdentify(roleIds, userId);
- }
- /**
- * 使用系統使用者物件屬性設定到Activiti User物件中
- * @param user 系統使用者物件
- * @param activitiUser Activiti User
- */
- private void cloneAndSaveActivitiUser(User user, org.activiti.engine.identity.User activitiUser) {
- activitiUser.setFirstName(user.getName());
- activitiUser.setLastName(StringUtils.EMPTY);
- activitiUser.setPassword(StringUtils.EMPTY);
- activitiUser.setEmail(user.getEmail());
- identityService.saveUser(activitiUser);
- }
- @Override
- public void delete(Long userId, booleansynToActiviti, booleansynToChecking) throwsServiceException, Exception {
- // 查詢需要刪除的使用者物件
- User user = accountManager.getEntity(userId);
- if(user == null) {
- thrownew ServiceException("刪除使用者時,找不到ID為"+ userId + "的使用者");
- }
- /**
- * 同步刪除Activiti User Group
- */
- if(synToActiviti) {
- // 同步刪除Activiti User
- List<role> roleList = user.getRoleList();
- for(Role role : roleList) {
- identityService.deleteMembership(userId.toString(), role.getEnName());
- }
- // 同步刪除Activiti User
- identityService.deleteUser(userId.toString());
- }
- // 刪除本系統使用者
- accountManager.deleteUser(userId);
- // 刪除考勤機使用者
- if(synToChecking) {
- checkingAccountManager.deleteEntity(userId);
- }
- }
- }
同步全部資料步驟:
-
刪除Activiti的User、Group、Membership資料
-
複製Role物件資料到Group
-
複製使用者資料以及Membership資料
ActivitiIdentifyCommonDao.java
[java]- public class ActivitiIdentifyCommonDao {
- protectedLogger logger = LoggerFactory.getLogger(getClass());
- @Autowired
- private JdbcTemplate jdbcTemplate;
- /**
- * 刪除使用者和組的關係
- */
- public void deleteAllUser() {
- String sql = "delete from ACT_ID_USER";
- jdbcTemplate.execute(sql);
- logger.debug("deleted from activiti user.");
- }
- /**
- * 刪除使用者和組的關係
- */
- public void deleteAllRole() {
- String sql = "delete from ACT_ID_GROUP";
- jdbcTemplate.execute(sql);
- logger.debug("deleted from activiti group.");
- }
- /**
- * 刪除使用者和組的關係
- */
- public void deleteAllMemerShip() {
- String sql = "delete from ACT_ID_MEMBERSHIP";
- jdbcTemplate.execute(sql);
- logger.debug("deleted from activiti membership.");
- }
- }
ActivitiIdentifyService.java(下面兩段程式碼重複)
- public class ActivitiIdentifyService extends AbstractBaseService {
- @Autowired
- protected ActivitiIdentifyCommonDao activitiIdentifyCommonDao;
- /**
- * 刪除使用者和組的關係
- */
- public void deleteAllUser() {
- activitiIdentifyCommonDao.deleteAllUser();
- }
- /**
- * 刪除使用者和組的關係
- */
- public void deleteAllRole() {
- activitiIdentifyCommonDao.deleteAllRole();
- }
- /**
- * 刪除使用者和組的關係
- */
- public void deleteAllMemerShip() {
- activitiIdentifyCommonDao.deleteAllMemerShip();
- }
- }
publicclass ActivitiIdentifyService extendsAbstractBaseService {
@Autowired
protectedActivitiIdentifyCommonDao activitiIdentifyCommonDao;
/**
* 刪除使用者和組的關係
*/
publicvoid deleteAllUser() {
activitiIdentifyCommonDao.deleteAllUser();
}
/**
* 刪除使用者和組的關係
*/
publicvoid deleteAllRole() {
activitiIdentifyCommonDao.deleteAllRole();
}
/**
* 刪除使用者和組的關係
*/
publicvoid deleteAllMemerShip() {
activitiIdentifyCommonDao.deleteAllMemerShip();
}
}
AccountServiceImpl.java(下面兩段程式碼重複)
- public class AccountServiceImpl implements AccountService {
- @Override
- public void synAllUserAndRoleToActiviti() throwsException {
- // 清空工作流使用者、角色以及關係
- deleteAllActivitiIdentifyData();
- // 複製角色資料
- synRoleToActiviti();
- // 複製使用者以及關係資料
- synUserWithRoleToActiviti();
- }
- /**
- * 複製使用者以及關係資料
- */
- private void synUserWithRoleToActiviti() {
- List<user> allUser = accountManager.getAll();
- for(User user : allUser) {
- String userId = user.getId().toString();
- // 新增一個使用者到Activiti
- saveActivitiUser(user);
- // 角色和使用者的關係
- List<role> roleList = user.getRoleList();
- for(Role role : roleList) {
- identityService.createMembership(userId, role.getEnName());
- logger.debug("add membership {user: {}, role: {}}", userId, role.getEnName());
- }
- }
- }
- /**
- * 同步所有角色資料到{@link Group}
- */
- private void synRoleToActiviti() {
- List<role> allRole = roleManager.getAll();
- for(Role role : allRole) {
- String groupId = role.getEnName().toString();
- Group group = identityService.newGroup(groupId);
- group.setName(role.getName());
- group.setType(role.getType());
- identityService.saveGroup(group);
- }
- }
- @Override
- public void deleteAllActivitiIdentifyData() throwsException {
- activitiIdentifyService.deleteAllMemerShip();
- activitiIdentifyService.deleteAllRole();
- activitiIdentifyService.deleteAllUser();
- }
- }
publicclass AccountServiceImpl implementsAccountService {
@Override
publicvoid synAllUserAndRoleToActiviti() throwsException {
// 清空工作流使用者、角色以及關係
deleteAllActivitiIdentifyData();
// 複製角色資料
synRoleToActiviti();
// 複製使用者以及關係資料
synUserWithRoleToActiviti();
}
/**
* 複製使用者以及關係資料
*/
privatevoid synUserWithRoleToActiviti() {
List<user> allUser = accountManager.getAll();
for(User user : allUser) {
String userId = user.getId().toString();
// 新增一個使用者到Activiti
saveActivitiUser(user);
// 角色和使用者的關係
List<role> roleList = user.getRoleList();
for(Role role : roleList) {
identityService.createMembership(userId, role.getEnName());
logger.debug("add membership {user: {}, role: {}}", userId, role.getEnName());
}
}
}
/**
* 同步所有角色資料到{@link Group}
*/
privatevoid synRoleToActiviti() {
List<role> allRole = roleManager.getAll();
for(Role role : allRole) {
String groupId = role.getEnName().toString();
Group group = identityService.newGroup(groupId);
group.setName(role.getName());
group.setType(role.getType());
identityService.saveGroup(group);
}
}
@Override
publicvoid deleteAllActivitiIdentifyData() throwsException {
activitiIdentifyService.deleteAllMemerShip();
activitiIdentifyService.deleteAllRole();
activitiIdentifyService.deleteAllUser();
}
}
方案二:覆蓋IdentifyService介面的實現
此方法覆蓋IdentifyService介面的預設實現類:org.activiti.engine.impl.IdentityServiceImpl。
讀者可以根據現有的使用者管理介面實現覆蓋IdentityServiceImpl的每個方法的預設實現,這樣就等於放棄使用系列表:ACT_ID_。
此方法不再提供程式碼,請讀者自行根據現有介面逐一實現介面定義的功能。
方案三:用檢視覆蓋同名的ACT_ID_系列表
此方案和第二種類似,放棄使用系列表:ACT_ID_,建立同名的檢視。
1.刪除已建立的ACT_ID_*表
建立檢視必須刪除引擎自動建立的ACT_ID_*表,否則不能建立檢視。
2.建立檢視:
- ACT_ID_GROUP
- ACT_ID_INFO
- ACT_ID_MEMBERSHIP
- ACT_ID_USER
建立的檢視要保證資料型別一致,例如使用者的ACT_ID_MEMBERSHIP表的兩個欄位都是字元型,一般系統中都是用NUMBER作為使用者、角色的主鍵型別,所以建立檢視的時候要把數字型別轉換為字元型。
3.修改引擎預設配置
在引擎配置中設定屬性dbIdentityUsed為false即可。
- <beanidbeanid="processEngineConfiguration"class="org.activiti.spring.SpringProcessEngineConfiguration">
- ...
- <propertynamepropertyname="dbIdentityUsed"ref="false">
- ...
- </property></bean>
<beanid="processEngineConfiguration"class="org.activiti.spring.SpringProcessEngineConfiguration">
...
<propertyname="dbIdentityUsed"ref="false">
...
</property></bean>
總結
-
方案一:不破壞、不修改原始碼,面向介面程式設計,推薦;
-
方案二:放棄原有的Identify模組,使用自定義的實現,特殊情況可以使用此方式;
-
方案三:不需要編寫Java程式碼,只需要建立同名檢視即可,對於現有系統的整合、強烈推薦;
相關推薦
專案中加入activiti後,使用者許可權管理處理的三種方式
相信每個涉及到使用者的系統都有一套使用者許可權管理平臺或者模組,用來維護使用者以及在系統內的功能、資料許可權,我們使用的Activiti工作流引擎配套設計了包括User、Group的Identify模組,怎麼和業務資料同步呢,這個問題是每個新人必問的問題之一,下面介紹幾種同步方案,最後總結比較。 方案一:呼
解決專案中複製網址後,黏貼到搜尋框裡面,系統軟體盤未彈起
解決這個問題就主要兩句核心的程式碼: etSearch.addTextChangedListener(new TextWatcher() { public void onTextChanged(CharSequence s, int start, int before, in
Spring Boot 專案中引入websocket後,執行Junit測試報錯
1、報錯資訊如下 java.lang.IllegalStateException: Failed to load ApplicationContext at org.springframework.test.context.cache.Default
nginx反代httpd,實現三種tomcat代理模型至後端的tomcat服務器,會話綁定的三種方式
httpmod_jkajp 會話綁定 構建tomcat集群,實現前端一臺nginx反代,到後端的apache服務器,由apache負責向後端的tomcat服務器進行資源調度,這樣的模式比直接用nginx反代到後端主機,tomcat服務器所受到的壓力會更小,服務將會更加穩定,這樣的模式是經過實踐檢驗出來的。如
JavaWeb專案啟動時,自動執行程式碼的三種方式(包含不佔用tomcat啟動時長的方式)
三種方式實現在tomcat啟動時執行某段程式碼 由於這三種方式的執行時長計算在tomcat的啟動時長裡,如果tomcat設定了啟動超時時間,那麼這三種方式執行的操作很可能會讓tomcat啟動超時。 為了解決自動執行的部分不影響tomcat的正常啟動我們可以在三種方式中新建一個執行
Python基礎(四)--- Python多執行緒介紹,開啟執行緒的三種方式,time模組,join,Daemon,Lock、Rlock,事件機制,Timer
一、多執行緒介紹 --------------------------------------------------------- 1.threading用於提供執行緒相關的操作,執行緒是應用程式中工作的最小單元。 2.python當前版本的多執行緒庫沒有實現優先順序、執行緒組,執
三個執行緒輪流執行順序列印ABC,依次是ABCABCABC......(三種方式)
1.使用synchronized悲觀鎖 (秋招阿里的一個筆試題,應該寫的比較複雜,然後就沒有然後了o(╥﹏╥)o) public class ThreadThreadp { private int flag = 0; public synch
SpringMVC第一個例子,靜態資源過濾的三種方式
web.xml <?xml version="1.0" encoding="UTF-8"?> <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:
Android自定義View初體驗,實現圓形TextView的三種方式
自定義view對我來說一直是比較恐懼的,但是萬事開頭難,今天總結一下自己實現圓形TextView的三種方式。 首先來說一下自定義view的三種方式: 一,自繪控制元件: 自繪控制元件就是說介面展示的內容就是我們在ondraw()方法中繪製出來的,繼承Vie
Java中的Class類以及獲取Class物件的三種方式
java.lang.Class 之前Hadoop裡面job.setMapperClass(Map.class)之類的方法用到了 xxx.class的寫法,當時也沒有深究。這兩天又遇到了xxx.getClass()的寫法,稍微看了一下。 java API裡這樣寫道: Class 類的例項表示正在執行的
Struts2中jsp前臺傳值到action後臺的三種方式
使用者名稱:<s:textfield name="username"/><br/> 密 碼:<s:password name="password"/><br/> <s:submit value="提交"/> &l
SpringBoot專案攔截器中通過流獲取Request請求物件中的引數後,控制器中@RequestBody註解引數獲取不到
一、場景 第一次搭建專案開發環境,需要在專案中實現日誌攔截器,用來獲取使用者請求引數日誌,以便在後期維護中出現BUG時能夠快速定位錯誤發生的場景。請求引數一般通過GET和POST方式進行傳遞,GET請求引數獲取通過request.getParameterMap()獲
開發中使用Consul作為服務註冊中心時,專案接入sharding-jdbc後,db測活一致失敗問題解決
一、問題背景: 專案中(Spring boot)使用consul作為服務註冊中心時,當接入sharding-jdbc 1.4.x版本後,健康檢查一直失敗。主要是db檢測失敗,丟擲以下錯誤: "db": { "status": "DOWN", "database": "My
ssm+maven專案中加入“百度富文字編輯器”,實現圖片上傳
1.在UEditor官方下載編輯器。2.解壓壓縮檔案到資料夾,因為預設的資料夾名字過長,建議重新命名一下資料夾名,我這裡命名為ueditor資料夾中對應的目錄為3.將整個資料夾copy到專案webapp目錄下,(我這裡用的是IDEA,不知道什麼原因直接往IDEA開啟的專案裡拷
專案中使用Butterknife框架,修改包名後項目報錯原因
問題:專案中使用Butterknife框架,修改包名後項目報錯但不顯示任何錯誤。 原因:Butterknife框架導致Android 專案中有隱藏程式碼檔案,但是在工程包結構下卻沒有該類,隱藏檔案在工程專案的根目錄下的.apt_generated內。在A
eclipse中svn,就是點專案右鍵team後,只顯示Apply Patch、Share Project的解決辦法
問題描述:在一次關閉eclipse中電腦斷電,然後裡面的專案都不見了,就把本地儲存的專案匯入進工作空間裡,但是在準備提交程式碼到svn時,發現右擊專案team時,沒有提交項,只剩Apply Patch
如何在spring boot 專案中加入freemarker,以及使用yaml語法時的注意事項
最近在做一個用郵件傳送報表的專案,要求在郵件正文中將excel表格顯示出來。我考慮到通過字串拼接表格太麻煩,而且不利於維護,所以使用freemarker做郵件模板來做展示。 專案環境:spring boot 構建工具:maven 步驟如下: 1.引入pom依賴
解決 maven 專案中加入了 lombok 庫後依然報錯的問題
平時我們採用 maven 引入第三方庫,可以方便的管理第三方 jar 包,然加入 lombok 後啟動 eclipse 依然報錯,這是由於 lombok 是通過反射在執行時自動生成 getter()、setter()、hashCode()、toString(),故早於通過
前後端分離,如何在前端專案中動態插入後端API基地址?(in docker)
開門見山,本文分享**前後端分離,容器化前端專案時動態插入後端API基地址**,這是一個很讚的實踐,解決了前端專案容器化過程中受制後端呼叫的尷尬。 ## 尷尬從何而來 常見的web前後端分離:前後端分開部署,前端專案由nginx承載打包檔案,反向代理請求。 應用的某些部分必須是可配置的,比如`API呼叫
解決在Filter中讀取Request中的流後,後續controller或restful接口中無法獲取流的問題
catch java.net 原始的 more from 解析 amp per gson 首先我們來描述一下在開發中遇到的問題,場景如下: 比如我們要攔截所有請求,獲取請求中的某個參數,進行相應的邏輯處理:比如我要獲取所有請求中的公共參數 token,clientVer