Activiti Identify同步或者重构用户数据的多种方案比较

相信每个涉及到用户的系统都有一套用户权限管理平台或者模块,用来维护用户以及在系统内的功能、数据权限,我们使用的Activiti工作流引擎配套设计了包括User、Group的Identify模块,怎么和业务数据同步呢,这个问题是每个新人必问的问题之一,下面介绍几种同步方案,最后总结比较。
如果你在考虑直接使用Activiti引擎的Identify模块作为系统的用户数据管理模块,您真是奇才~开个玩笑
方案一:调用IdentifyService接口完成同步
参考IdentifyService接口Javadoc:http://www.activiti.org/javadocs/org/activiti/engine/IdentityService.html
接口定义:
?
1 package com.foo.arch.service.id;
2 import java.util.List;
3  
4 import com.foo.arch.entity.id.User;
5 import com.foo.arch.service.ServiceException;
6  
7 /**
8  * 维护用户、角色、权限接口
9  * 
10  * @author HenryYan
11  *
12  */
13 public interface AccountService {
14  
15     /**
16      * 添加用户并[同步其他数据库]
17      * <ul>
18      * <li>step 1: 保存系统用户,同时设置和部门的关系</li>
19      * <li>step 2: 同步用户信息到activiti的identity.User,同时设置角色</li>
20      * </ul>
21      * 
22      * @param user              用户对象
23      * @param orgId             部门ID
24      * @param roleIds           角色ID集合
25      * @param synToActiviti     是否同步到Activiti数据库,通过配置文件方式设置,使用属性:account.user.add.syntoactiviti
26      * @throws OrganizationNotFoundException    关联用户和部门的时候从数据库查询不到哦啊部门对象
27      * @throws  Exception                       其他未知异常
28      */
29     public void save(User user, Long orgId, List<long> roleIds, boolean synToActiviti)
30             throws  OrganizationNotFoundException, ServiceException, Exception;
31      
32     /**
33      * 删除用户
34      * @param userId        用户ID
35      * @param synToActiviti     是否同步到Activiti数据库,通过配置文件方式设置,使用属性:account.user.add.syntoactiviti
36      * @throws Exception
37      */
38     public void delete(Long userId, boolean synToActiviti) throws ServiceException, Exception;
39  
40     /**
41      * 同步用户、角色数据到工作流
42      * @throws Exception
43      */
44     public void synAllUserAndRoleToActiviti() throws Exception;
45  
46     /**
47      * 删除工作流引擎Activiti的用户、角色以及关系
48      * @throws Exception
49      */
50     public void deleteAllActivitiIdentifyData() throws Exception;
51 }
52 </long>
同步单个接口实现片段:
?
1 @Service
2 @Transactional
3 public class AccountServiceImpl implements AccountService { 
4     /**
5      * 保存用户信息,并且同步用户信息到activiti的identity.User和identify.Group
6      * @param user              用户对象{@link User}
7      * @param roleIds           用户拥有的角色ID集合
8      * @param synToActiviti     是否同步数据到Activiti
9      * @see Role
10      */
11     public void saveUser(User user, List<long> roleIds, boolean synToActiviti) {
12         String userId = ObjectUtils.toString(user.getId());
13  
14         // 保存系统用户
15         accountManager.saveEntity(user);
16  
17         // 同步数据到Activiti Identify模块
18         if (synToActiviti) {
19             UserQuery userQuery = identityService.createUserQuery();
20             List<org.activiti.engine.identity.user> activitiUsers = userQuery.userId(userId).list();
21  
22             if (activitiUsers.size() == 1) {
23                 updateActivitiData(user, roleIds, activitiUsers.get(0));
24             } else if (activitiUsers.size() > 1) {
25                 String errorMsg = "发现重复用户:id=" + userId;
26                 logger.error(errorMsg);
27                 throw new RuntimeException(errorMsg);
28             } else {
29                 newActivitiUser(user, roleIds);
30             }
31         }
32  
33     }
34  
35     /**
36      * 添加工作流用户以及角色
37      * @param user      用户对象{@link User}
38      * @param roleIds   用户拥有的角色ID集合
39      */
40     private void newActivitiUser(User user, List<long> roleIds) {
41         String userId = user.getId().toString();
42  
43         // 添加用户
44         saveActivitiUser(user);
45  
46         // 添加membership
47         addMembershipToIdentify(roleIds, userId);
48     }
49  
50     /**
51      * 添加一个用户到Activiti {@link org.activiti.engine.identity.User}
52      * @param user  用户对象, {@link User}
53      */
54     private void saveActivitiUser(User user) {
55         String userId = user.getId().toString();
56         org.activiti.engine.identity.User activitiUser = identityService.newUser(userId);
57         cloneAndSaveActivitiUser(user, activitiUser);
58         logger.debug("add activiti user: {}", ToStringBuilder.reflectionToString(activitiUser));
59     }
60  
61     /**
62      * 添加Activiti Identify的用户于组关系
63      * @param roleIds   角色ID集合
64      * @param userId    用户ID
65      */
66     private void addMembershipToIdentify(List<long> roleIds, String userId) {
67         for (Long roleId : roleIds) {
68             Role role = roleManager.getEntity(roleId);
69             logger.debug("add role to activit: {}", role);
70             identityService.createMembership(userId, role.getEnName());
71         }
72     }
73  
74     /**
75      * 更新工作流用户以及角色
76      * @param user          用户对象{@link User}
77      * @param roleIds       用户拥有的角色ID集合
78      * @param activitiUser  Activiti引擎的用户对象,{@link org.activiti.engine.identity.User}
79      */
80     private void updateActivitiData(User user, List<long> roleIds, org.activiti.engine.identity.User activitiUser) {
81  
82         String userId = user.getId().toString();
83  
84         // 更新用户主体信息
85         cloneAndSaveActivitiUser(user, activitiUser);
86  
87         // 删除用户的membership
88         List<group> activitiGroups = identityService.createGroupQuery().groupMember(userId).list();
89         for (Group group : activitiGroups) {
90             logger.debug("delete group from activit: {}", ToStringBuilder.reflectionToString(group));
91             identityService.deleteMembership(userId, group.getId());
92         }
93  
94         // 添加membership
95         addMembershipToIdentify(roleIds, userId);
96     }
97  
98     /**
99      * 使用系统用户对象属性设置到Activiti User对象中
100      * @param user          系统用户对象
101      * @param activitiUser  Activiti User
102      */
103     private void cloneAndSaveActivitiUser(User user, org.activiti.engine.identity.User activitiUser) {
104         activitiUser.setFirstName(user.getName());
105         activitiUser.setLastName(StringUtils.EMPTY);
106         activitiUser.setPassword(StringUtils.EMPTY);
107         activitiUser.setEmail(user.getEmail());
108         identityService.saveUser(activitiUser);
109     }
110  
111     @Override
112     public void delete(Long userId, boolean synToActiviti, boolean synToChecking) throws ServiceException, Exception {
113         // 查询需要删除的用户对象
114         User user = accountManager.getEntity(userId);
115         if (user == null) {
116             throw new ServiceException("删除用户时,找不到ID为" + userId + "的用户");
117         }
118  
119         /**
120          * 同步删除Activiti User Group
121          */
122         if (synToActiviti) {
123             // 同步删除Activiti User
124             List<role> roleList = user.getRoleList();
125             for (Role role : roleList) {
126                 identityService.deleteMembership(userId.toString(), role.getEnName());
127             }
128  
129             // 同步删除Activiti User
130             identityService.deleteUser(userId.toString());
131         }
132  
133         // 删除本系统用户
134         accountManager.deleteUser(userId);
135  
136         // 删除考勤机用户
137         if (synToChecking) {
138             checkingAccountManager.deleteEntity(userId);
139         }
140     }
141 }
142 </role></group></long></long></long></org.activiti.engine.identity.user></long>
 
同步全部数据接口实现片段:
同步全部数据步骤:
• 删除Activiti的User、Group、Membership数据
• 复制Role对象数据到Group
• 复制用户数据以及Membership数据
ActivitiIdentifyCommonDao.java
?
1 public class ActivitiIdentifyCommonDao {
2  
3     protected Logger logger = LoggerFactory.getLogger(getClass());
4      
5     @Autowired
6     private JdbcTemplate jdbcTemplate;
7  
8     /**
9      * 删除用户和组的关系
10      */
11     public void deleteAllUser() {
12         String sql = "delete from ACT_ID_USER";
13         jdbcTemplate.execute(sql);
14         logger.debug("deleted from activiti user.");
15     }
16  
17     /**
18      * 删除用户和组的关系
19      */
20     public void deleteAllRole() {
21         String sql = "delete from ACT_ID_GROUP";
22         jdbcTemplate.execute(sql);
23         logger.debug("deleted from activiti group.");
24     }
25  
26     /**
27      * 删除用户和组的关系
28      */
29     public void deleteAllMemerShip() {
30         String sql = "delete from ACT_ID_MEMBERSHIP";
31         jdbcTemplate.execute(sql);
32         logger.debug("deleted from activiti membership.");
33     }
34  
35 }
ActivitiIdentifyService.java
?
1 public class ActivitiIdentifyService extends AbstractBaseService {
2      
3     @Autowired
4     protected ActivitiIdentifyCommonDao activitiIdentifyCommonDao;
5      
6     /**
7      * 删除用户和组的关系
8      */
9     public void deleteAllUser() {
10         activitiIdentifyCommonDao.deleteAllUser();
11     }
12      
13     /**
14      * 删除用户和组的关系
15      */
16     public void deleteAllRole() {
17         activitiIdentifyCommonDao.deleteAllRole();
18     }
19      
20     /**
21      * 删除用户和组的关系
22      */
23     public void deleteAllMemerShip() {
24         activitiIdentifyCommonDao.deleteAllMemerShip();
25     }
26 }
AccountServiceImpl.java
?
1 public class AccountServiceImpl implements AccountService {
2 @Override
3     public void synAllUserAndRoleToActiviti() throws Exception {
4  
5         // 清空工作流用户、角色以及关系
6         deleteAllActivitiIdentifyData();
7  
8         // 复制角色数据
9         synRoleToActiviti();
10  
11         // 复制用户以及关系数据
12         synUserWithRoleToActiviti();
13     }
14  
15     /**
16      * 复制用户以及关系数据
17      */
18     private void synUserWithRoleToActiviti() {
19         List<user> allUser = accountManager.getAll();
20         for (User user : allUser) {
21             String userId = user.getId().toString();
22  
23             // 添加一个用户到Activiti
24             saveActivitiUser(user);
25  
26             // 角色和用户的关系
27             List<role> roleList = user.getRoleList();
28             for (Role role : roleList) {
29                 identityService.createMembership(userId, role.getEnName());
30                 logger.debug("add membership {user: {}, role: {}}", userId, role.getEnName());
31             }
32         }
33     }
34  
35     /**
36      * 同步所有角色数据到{@link Group}
37      */
38     private void synRoleToActiviti() {
39         List<role> allRole = roleManager.getAll();
40         for (Role role : allRole) {
41             String groupId = role.getEnName().toString();
42             Group group = identityService.newGroup(groupId);
43             group.setName(role.getName());
44             group.setType(role.getType());
45             identityService.saveGroup(group);
46         }
47     }
48  
49     @Override
50     public void deleteAllActivitiIdentifyData() throws Exception {
51         activitiIdentifyService.deleteAllMemerShip();
52         activitiIdentifyService.deleteAllRole();
53         activitiIdentifyService.deleteAllUser();
54     }
55 }
56 </role></role></user>
方案二:覆盖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.修改引擎默认配置
在引擎配置中设置属性isDbIdentityUsed为false即可。
?
1 <bean class="org.activiti.spring.SpringProcessEngineConfiguration" id="processEngineConfiguration">
2     ...
3     <property ref="false" name="isDbIdentityUsed">
4     ...
5 </property>
6 </bean>
总结
• 方案一:不破坏、不修改源码,面向接口编程,推荐;
• 方案二:放弃原有的Identify模块,使用自定义的实现,特殊情况可以使用此方式;
• 方案三:不需要编写Java代码,只需要创建同名视图即可。

源文档 <http://www.kafeitu.me/activiti/2012/04/23/synchronize-or-redesign-user-and-role-for-activiti.html>
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值