項目中使用activiti做的總結,記錄一下方便回顧,也希望可以幫到需要幫助的人。
不使用activiti自帶的act_id_*表,自定義管理器進行操作。我們項目讓獨立出來一個微服務,自定義了ActUser(用戶)和Role(角色)ManyToMany
自定義用戶組的方法有三種:自定義SessionFactory、創建視圖、同步數據。
以下示例使用自定義SessionFactory來實現。
查看源文件可知Activiti內部與數據庫交互是使用MyBatis實現的,如下圖。
Activiti的每一張表都對應一個EntityManager和EntityManagerFactory,關於identity操作(CRUD)牽扯到兩個接口:UserIdentityManager和GroupIdentityManager。
- EntityManager
- EntityManagerFactory
- UserIdentityManager
- GroupIdentityManager
因此我們只需定義xxxUserManager管理器繼承UserEntityManager,xxxGroupManager繼承GroupEntityManager(內部寫CRDU,把自定義的User和Role轉換爲Activiti中的實體類型),定義CustomGroupManagerFactory和UserManagerFactory實現SessionFactory(注入自定義的管理器),就可以覆蓋原有的Act_id_*,完成自定義用戶了。具體實現示例如下:
自定義實體類
- ActUser(用戶)
package com.mycompany.myapp.domain;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import javax.persistence.*;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
/**
* A ActUser.
*/
@Entity
@Table(name = "act_user")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class ActUser implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "rev")
private Integer rev;
@Column(name = "first")
private String first;
@Column(name = "last")
private String last;
@Column(name = "email")
private String email;
@Column(name = "pwd")
private String pwd;
@Column(name = "picture_id")
private String pictureId;
@ManyToMany
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
@JoinTable(name = "act_user_role",
joinColumns = @JoinColumn(name = "act_user_id", referencedColumnName = "id"),
inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id"))
private Set<Role> roles = new HashSet<>();
// jhipster-needle-entity-add-field - JHipster will add fields here, do not remove
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Integer getRev() {
return rev;
}
public ActUser rev(Integer rev) {
this.rev = rev;
return this;
}
public void setRev(Integer rev) {
this.rev = rev;
}
public String getFirst() {
return first;
}
public ActUser first(String first) {
this.first = first;
return this;
}
public void setFirst(String first) {
this.first = first;
}
public String getLast() {
return last;
}
public ActUser last(String last) {
this.last = last;
return this;
}
public void setLast(String last) {
this.last = last;
}
public String getEmail() {
return email;
}
public ActUser email(String email) {
this.email = email;
return this;
}
public void setEmail(String email) {
this.email = email;
}
public String getPwd() {
return pwd;
}
public ActUser pwd(String pwd) {
this.pwd = pwd;
return this;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
public String getPictureId() {
return pictureId;
}
public ActUser pictureId(String pictureId) {
this.pictureId = pictureId;
return this;
}
public void setPictureId(String pictureId) {
this.pictureId = pictureId;
}
public Set<Role> getRoles() {
return roles;
}
public ActUser roles(Set<Role> roles) {
this.roles = roles;
return this;
}
public ActUser addRole(Role role) {
this.roles.add(role);
role.getActUsers().add(this);
return this;
}
public ActUser removeRole(Role role) {
this.roles.remove(role);
role.getActUsers().remove(this);
return this;
}
public void setRoles(Set<Role> roles) {
this.roles = roles;
}
// jhipster-needle-entity-add-getters-setters - JHipster will add getters and setters here, do not remove
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof ActUser)) {
return false;
}
return id != null && id.equals(((ActUser) o).id);
}
@Override
public int hashCode() {
return 31;
}
@Override
public String toString() {
return "ActUser{" +
"id=" + getId() +
", rev=" + getRev() +
", first='" + getFirst() + "'" +
", last='" + getLast() + "'" +
", email='" + getEmail() + "'" +
", pwd='" + getPwd() + "'" +
", pictureId='" + getPictureId() + "'" +
"}";
}
}
- Role(角色)
package com.mycompany.myapp.domain;
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import javax.persistence.*;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
/**
* A Role.
*/
@Entity
@Table(name = "role")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class Role implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "rev")
private Integer rev;
@Column(name = "name")
private String name;
@Column(name = "type")
private String type;
@ManyToMany(mappedBy = "roles")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
@JsonIgnore
private Set<ActUser> actusers = new HashSet<ActUser>();
// jhipster-needle-entity-add-field - JHipster will add fields here, do not remove
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Integer getRev() {
return rev;
}
public Role rev(Integer rev) {
this.rev = rev;
return this;
}
public void setRev(Integer rev) {
this.rev = rev;
}
public String getName() {
return name;
}
public Role name(String name) {
this.name = name;
return this;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public Role type(String type) {
this.type = type;
return this;
}
public void setType(String type) {
this.type = type;
}
public Set<ActUser> getActUsers() {
return actusers;
}
public Role actusers(Set<ActUser> actusers) {
this.actusers = actusers;
return this;
}
public Role addActUser(ActUser actuser) {
this.actusers.add(actuser);
actuser.getRoles().add(this);
return this;
}
public Role removeActUser(ActUser actuser) {
this.actusers.remove(actuser);
actuser.getRoles().remove(this);
return this;
}
public void setActUsers(Set<ActUser> actusers) {
this.actusers = actusers;
}
// jhipster-needle-entity-add-getters-setters - JHipster will add getters and setters here, do not remove
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof Role)) {
return false;
}
return id != null && id.equals(((Role) o).id);
}
@Override
public int hashCode() {
return 31;
}
@Override
public String toString() {
return "Role{" +
"id=" + getId() +
", rev=" + getRev() +
", name='" + getName() + "'" +
", type='" + getType() + "'" +
"}";
}
}
1.創建 CustomGroupManager 繼承 GroupEntityManager
package com.mycompany.myapp.activiti;
/**
* 自定義的Activiti用戶組管理器
*
* @author [email protected]
* @version 1.0
* @date 2019-10-09 09:24
*/
import com.mycompany.myapp.activiti.util.ActivitiUserUtils;
import com.mycompany.myapp.domain.ActUser;
import com.mycompany.myapp.domain.Role;
import com.mycompany.myapp.repository.ActUserRepository;
import com.mycompany.myapp.repository.RoleRepository;
import org.activiti.engine.identity.Group;
import org.activiti.engine.identity.GroupQuery;
import org.activiti.engine.impl.GroupQueryImpl;
import org.activiti.engine.impl.Page;
import org.activiti.engine.impl.persistence.entity.GroupEntityManager;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Set;
@Component
public class CustomGroupManager extends GroupEntityManager {
private static final Log logger = LogFactory
.getLog(CustomGroupManager.class);
@Autowired
private ActUserRepository actUserRepository;
@Autowired
private RoleRepository roleRepository;
@Override
public Group createNewGroup(String groupId) {
return super.createNewGroup(groupId);
}
@Override
public GroupQuery createNewGroupQuery() {
// TODO Auto-generated method stub
return super.createNewGroupQuery();
}
@Override
public List<Group> findGroupByQueryCriteria(GroupQueryImpl query, Page page) {
// TODO Auto-generated method stub
return super.findGroupByQueryCriteria(query, page);
}
@Override
public long findGroupCountByQueryCriteria(GroupQueryImpl query) {
// TODO Auto-generated method stub
return super.findGroupCountByQueryCriteria(query);
}
// @Override
// public GroupEntity findGroupById(String groupId) {
// // TODO Auto-generated method stub
// return super.findGroupById(groupId);
// }
/**
* 查找角色
*
* @param userId
* @return
*/
@Override
public List<Group> findGroupsByUser(String userId) {
// TODO Auto-generated method stub
// return super.findGroupsByUser(userId);
if (userId == null) {
return null;
}
List<Group> groups = new ArrayList<Group>();
List<Role> roleList = new ArrayList<Role>();
Optional<ActUser> optionalUser = actUserRepository.findOneWithEagerRelationships(Long.valueOf(userId));
if (optionalUser.isPresent()) {
com.mycompany.myapp.domain.ActUser user = optionalUser.get();
Set<Role> roles = user.getRoles();
roles.forEach((s) -> {
Optional<Role> optionalRole = roleRepository.findById(s.getId());
if (!optionalRole.isPresent()) {
return;
}
Role role = optionalRole.get();
roleList.add(role);
});
groups = ActivitiUserUtils.toActivitiGroups(roleList);
}
return groups;
}
// @Override
// public List<Group> findPotentialStarterUsers(String proceDefId) {
// return super.findPotentialStarterUsers(proceDefId);
// }
}
2. CustomUserManager 繼承 UserEntityManager
package com.mycompany.myapp.activiti;
import com.mycompany.myapp.activiti.util.ActivitiUserUtils;
import com.mycompany.myapp.domain.Role;
import com.mycompany.myapp.repository.ActUserRepository;
import com.mycompany.myapp.repository.RoleRepository;
import org.activiti.engine.identity.Group;
import org.activiti.engine.identity.User;
import org.activiti.engine.impl.Page;
import org.activiti.engine.impl.UserQueryImpl;
import org.activiti.engine.impl.persistence.entity.IdentityInfoEntity;
import org.activiti.engine.impl.persistence.entity.UserEntity;
import org.activiti.engine.impl.persistence.entity.UserEntityManager;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Set;
/**
* @author [email protected]
* @version 1.0
* @date 2019-10-09 09:44
*/
@Component
public class CustomUserManager extends UserEntityManager {
private static final Log logger = LogFactory
.getLog(CustomUserManager.class);
@Autowired
private ActUserRepository actUserRepository;
@Autowired
private RoleRepository roleRepository;
/**
* 查詢單個用戶
*
* @param userId
* @return
*/
@Override
public User findUserById(String userId) {
//return super.findUserById(userId);
User userEntity = new UserEntity();
Optional<com.mycompany.myapp.domain.ActUser> optionalUser = actUserRepository.findById(Long.valueOf(userId));
if (!optionalUser.isPresent()) {
return userEntity;
}
com.mycompany.myapp.domain.ActUser user = optionalUser.get();
userEntity = ActivitiUserUtils.toActivitiUser(user);
return userEntity;
}
@Override
public List<User> findUserByQueryCriteria(UserQueryImpl query, Page page) {
// TODO Auto-generated method stub
return super.findUserByQueryCriteria(query, page);
}
@Override
public long findUserCountByQueryCriteria(UserQueryImpl query) {
// TODO Auto-generated method stub
return super.findUserCountByQueryCriteria(query);
}
/**
* 查詢用戶擁有的角色
*
* @param userId
* @return
*/
@Override
public List<Group> findGroupsByUser(String userId) {
// TODO Auto-generated method stub
//return super.findGroupsByUser(userId);
if (userId == null) {
return null;
}
List<Group> gs = null;
List<Role> roleList = new ArrayList<Role>();
Optional<com.mycompany.myapp.domain.ActUser> optionalUser = actUserRepository.findById(Long.valueOf(userId));
if (optionalUser.isPresent()) {
com.mycompany.myapp.domain.ActUser user = optionalUser.get();
Set<Role> roles = user.getRoles();
roles.forEach((s) -> {
Optional<Role> optionalRole = roleRepository.findById(s.getId());
if (!optionalRole.isPresent()) {
return;
}
Role role = optionalRole.get();
roleList.add(role);
});
gs = ActivitiUserUtils.toActivitiGroups(roleList);
return gs;
}
return gs;
}
@Override
public IdentityInfoEntity findUserInfoByUserIdAndKey(String userId,
String key) {
// TODO Auto-generated method stub
return super.findUserInfoByUserIdAndKey(userId, key);
}
@Override
public List<String> findUserInfoKeysByUserIdAndType(String userId,
String type) {
// TODO Auto-generated method stub
return super.findUserInfoKeysByUserIdAndType(userId, type);
}
@Override
public Boolean checkPassword(String userId, String password) {
// TODO Auto-generated method stub
return super.checkPassword(userId, password);
}
@Override
public List<User> findPotentialStarterUsers(String proceDefId) {
// TODO Auto-generated method stub
return super.findPotentialStarterUsers(proceDefId);
}
}
3. CustomGroupManagerFactory 實現 SessionFactory
package com.mycompany.myapp.activiti;
/**
* 自定義的Activiti用戶組會話工廠
*
* @author [email protected]
* @version 1.0
* @date 2019-10-09 09:42
*/
import org.activiti.engine.impl.interceptor.Session;
import org.activiti.engine.impl.interceptor.SessionFactory;
import org.activiti.engine.impl.persistence.entity.GroupIdentityManager;
import javax.annotation.Resource;
public class CustomGroupManagerFactory implements SessionFactory {
//private GroupEntityManager groupEntityManager;
@Resource
private CustomGroupManager customGroupManager;
//@Autowired
public void setCustomGroupEntityManager(CustomGroupManager customGroupEntityManager) {
this.customGroupManager = customGroupEntityManager;
}
public Class<?> getSessionType() {
// 返回原始的GroupManager類型
return GroupIdentityManager.class;
}
public Session openSession() {
// 返回自定義的GroupManager實例
return customGroupManager;
}
}
4. CustomUserManagerFactory 實現 SessionFactory
package com.mycompany.myapp.activiti;
/**
* 自定義的Activiti用戶會話工廠
*
* @author [email protected]
* @version 1.0
* @date 2019-10-09 09:50
*/
import org.activiti.engine.impl.interceptor.Session;
import org.activiti.engine.impl.interceptor.SessionFactory;
import org.activiti.engine.impl.persistence.entity.UserIdentityManager;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service
public class CustomUserManagerFactory implements SessionFactory {
//private UserEntityManager userEntityManager;
@Resource
private CustomUserManager customUserManager;
// @Autowired
public void setCustomUserEntityManager(CustomUserManager customUserEntityManager) {
this.customUserManager = customUserEntityManager;
}
public Class<?> getSessionType() {
// activiti原生類型
return UserIdentityManager.class;
}
public Session openSession() {
// 返回自定義的UserManager實例
return customUserManager;
}
}
activitiConfig.xml中配置一下:
注意:別忘了啓動項上面掃描一下activitiConfig.xml
什麼時候調用自定義的管理器?
答:查詢待辦task信息的時候會用到。
TaskUtil
package com.mycompany.myapp.activiti.util;
import org.activiti.engine.task.Task;
import java.util.HashMap;
import java.util.Map;
/**
* Task轉換類
*
* @author [email protected]
* @version 1.0
* @date 2019-10-10 13:46
*/
public class TaskUtil {
/**
* 自定義查詢返回屬性
*
* @param task
* @return
*/
public static Map<String, Object> taskMap(Task task) {
Map<String, Object> map = new HashMap<>();
map.put("startTime", task.getCreateTime());
map.put("assignee", task.getAssignee());
map.put("taskName", task.getName());
map.put("taskId", task.getId());
map.put("parentTaskId", task.getParentTaskId());
map.put("processInstanceId", task.getProcessInstanceId());
map.put("processDefinitionId", task.getProcessDefinitionId());
map.put("executionId", task.getExecutionId());
map.put("description", task.getDescription());
return map;
}
}
如果指派了處理人,任務就會到指派人那裏,如果未定義指派人,定義了候選組,在候選組中的每個人都可以查詢到該流程。如下:taskId:75002任務就是候選組