您的位置:首页 > 其它

Activiti学习资料(同步或者重构Activiti Identify用户数据)

2012-10-17 23:37 357 查看


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

相信每个涉及到用户的系统都有一套用户权限管理平台或者模块,用来维护用户以及在系统内的功能、数据权限,我们使用的Activiti工作流引擎配套设计了包括User、Group的Identify模块,怎么和业务数据同步呢,这个问题是每个新人必问的问题之一,下面介绍几种同步方案,最后总结比较。
如果你在考虑直接使用Activiti引擎的Identify模块作为系统的用户数据管理模块,您真是奇才~开个玩笑

方案一:调用IdentifyService接口完成同步

参考IdentifyService接口Javadoc:http://www.activiti.org/javadocs/org/activiti/engine/IdentityService.html


接口定义:

package com.foo.arch.service.id;
import java.util.List;

import com.foo.arch.entity.id.User;
import com.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, boolean synToActiviti)
throws  OrganizationNotFoundException, ServiceException, Exception;

/**
* 删除用户
* @param userId        用户ID
* @param synToActiviti     是否同步到Activiti数据库,通过配置文件方式设置,使用属性:account.user.add.syntoactiviti
* @throws Exception
*/
public void delete(Long userId, boolean synToActiviti) throws ServiceException, Exception;

/**
* 同步用户、角色数据到工作流
* @throws Exception
*/
public void synAllUserAndRoleToActiviti() throws Exception;

/**
* 删除工作流引擎Activiti的用户、角色以及关系
* @throws Exception
*/
public void deleteAllActivitiIdentifyData() throws Exception;
}


?

同步单个接口实现片段:

@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, boolean synToActiviti) {
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));
} else if (activitiUsers.size() > 1) {
String errorMsg = "发现重复用户:id=" + userId;
logger.error(errorMsg);
throw new 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, boolean synToActiviti, boolean synToChecking) throws ServiceException, Exception {
// 查询需要删除的用户对象
User user = accountManager.getEntity(userId);
if (user == null) {
throw new 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);
}
}
}
</role></group></long></long></long></org.activiti.engine.identity.user></long>


?

同步全部数据接口实现片段:

同步全部数据步骤:

删除Activiti的User、Group、Membership数据

复制Role对象数据到Group

复制用户数据以及Membership数据

ActivitiIdentifyCommonDao.java
public class ActivitiIdentifyCommonDao {

protected Logger 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();
}
}


?
AccountServiceImpl.java
public class AccountServiceImpl implements AccountService {
@Override
public void synAllUserAndRoleToActiviti() throws Exception {

// 清空工作流用户、角色以及关系
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() throws Exception {
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.修改引擎默认配置

笔者按照表结构创建了以上几个同名的视图,但是Activiti具有自我保护机制,导致引擎不能初始化,需要需改源码才可以正常使用。
修改org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl的isDbIdentityUsed=false
切记,每次升级版本的时候复制最新的源码然后再次更改属性isDbIdentityUsed=false。

总结

方案:不破坏、不修改源码,面向接口编程推荐

方案:放弃原有的Identify模块,使用自定义的实现,特殊情况可以使用此方式;

方案:破坏了部分源码,在现有的用户数据表基础上创建和ACT_ID_*一直的同名视图即可;还有一个缺陷就是不能使用IdentifyService添加User、Group和简历两者的关系,当然也不需要在从Activiti维护了。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐