JBPM4.4总结-嵌入自己的用户体系(集成自定义用户表)
很多时候,JBPM自己提供的用户系统是不够用的,这时候就要求我们自己去扩展自己的用户体系。JBPM允许外挂一个用户体系。
如果想嵌入自己的用户体系,只需如下五步:
一:创建MesUser,MesGroup,MesMembership三个类,分别实现接口User,Group。由于类MesMembership是独立的,因此没有必要继承或实现其他接口。
Jbpm4提供了实现接口
interface User
interface Group
interface GroupMember
interface IdentitySession
想要集成自己的表,首先需要实现jbpm提供的接口,然后再进行配置。
MesUser.java 用户表
1 package com.amnet.jbpm.identify;
2
3 import java.io.Serializable;
4 import java.sql.Blob;
5 import org.jbpm.api.identity.User;
6
7 public class MesUser implements Serializable, User {
8
9 private static final long serialVersionUID = 1L;
10
11 protected long dbid; // 数据库内部自生成的ID
12
13 private String id;
14
15 private String userNo;// 员工工号
16
17 private String userName;// 员工姓名
18
19 private String userSex;// 性别
20
21 private String userPassword;// 密码
22
23 private String userType;// 类型
24
25 private String userMail;// 电子邮件
26
27 private String isValid;// 是否有效Y/N
28
29 private Blob signaturePic;// 电子签名
30
31 private String remarks;// 备注
32
33 protected int dbversion;
34
35 public int getDbversion() {
36
37 return dbversion;
38
39 }
40
41 public MesUser() {
42
43 }
44
45 public MesUser(String id, String userName, String userMail) {
46
47 this.id = id;
48
49 this.userName = userName;
50
51 this.userMail = userMail;
52
53 }
54
55 public void setDbversion(int dbversion) {
56
57 this.dbversion = dbversion;
58
59 }
60
61 public long getDbid() {
62
63 return dbid;
64
65 }
66
67 public void setDbid(long dbid) {
68
69 this.dbid = dbid;
70
71 }
72
73 public void setId(String id) {
74
75 this.id = id;
76
77 }
78
79 public String getUserNo() {
80
81 return userNo;
82
83 }
84
85 public void setUserNo(String userNo) {
86
87 this.userNo = userNo;
88
89 }
90
91 public String getUserName() {
92
93 return userName;
94
95 }
96
97 public void setUserName(String userName) {
98
99 this.userName = userName;
100
101 }
102
103 public String getUserSex() {
104
105 return userSex;
106
107 }
108
109 public void setUserSex(String userSex) {
110
111 this.userSex = userSex;
112
113 }
114
115 public String getUserPassword() {
116
117 return userPassword;
118
119 }
120
121 public void setUserPassword(String userPassword) {
122
123 this.userPassword = userPassword;
124
125 }
126
127 public String getUserType() {
128
129 return userType;
130
131 }
132
133 public void setUserType(String userType) {
134
135 this.userType = userType;
136
137 }
138
139 public String getUserMail() {
140
141 return userMail;
142
143 }
144
145 public void setUserMail(String userMail) {
146
147 this.userMail = userMail;
148
149 }
150
151 public String getIsValid() {
152
153 return isValid;
154
155 }
156
157 public void setIsValid(String isValid) {
158
159 this.isValid = isValid;
160
161 }
162
163 public Blob getSignaturePic() {
164
165 return signaturePic;
166
167 }
168
169 public void setSignaturePic(Blob signaturePic) {
170
171 this.signaturePic = signaturePic;
172
173 }
174
175 public String getRemarks() {
176
177 return remarks;
178
179 }
180
181 public void setRemarks(String remarks) {
182
183 this.remarks = remarks;
184
185 }
186
187 public String getDisplayName() {
188
189 return userName + "(" + id + ")";
190
191 }
192
193 // 实现User接口所必须实现的几个方法
194
195 public String getId() {
196
197 return this.id;
198
199 }
200
201 public String getGivenName() {
202
203 return null;
204
205 }
206
207 public String getFamilyName() {
208
209 return null;
210
211 }
212
213 public String getBusinessEmail() {
214
215 return this.userMail;
216
217 }
218
219 }
MesGroup.java 部门表
1 package com.amnet.jbpm.identify;
2
3 import java.io.Serializable;
4
5 import org.jbpm.api.identity.Group;
6
7 public class MesGroup implements Serializable, Group {
8
9 private static final long serialVersionUID = 1L;
10
11 private String id;
12
13 private String groupName;// 组织名称
14
15 private String groupType;// 组织类型
16
17 private MesGroup parentGroup;// 父组织
18
19 private String remarks;// 备注
20
21 protected long dbid;
22
23 protected int dbversion;
24
25 public int getDbversion() {
26
27 return dbversion;
28
29 }
30
31 public void setDbversion(int dbversion) {
32
33 this.dbversion = dbversion;
34
35 }
36
37 public long getDbid() {
38
39 return dbid;
40
41 }
42
43 public void setDbid(long dbid) {
44
45 this.dbid = dbid;
46
47 }
48
49 public String getParentGroupID() {
50
51 return parentGroup != null ? parentGroup.getId() : null;
52
53 }
54
55 public String getParentGroupName() {
56
57 return parentGroup == null ? "xxx" : parentGroup.getGroupName();
58
59 }
60
61 public void setId(String id) {
62
63 this.id = id;
64
65 }
66
67 public String getGroupName() {
68
69 return groupName;
70
71 }
72
73 public void setGroupName(String groupName) {
74
75 this.groupName = groupName;
76
77 }
78
79 public String getGroupType() {
80
81 return groupType;
82
83 }
84
85 public void setGroupType(String groupType) {
86
87 this.groupType = groupType;
88
89 }
90
91 public MesGroup getParentGroup() {
92
93 return parentGroup;
94
95 }
96
97 public void setParentGroup(MesGroup parentGroup) {
98
99 this.parentGroup = parentGroup;
100
101 }
102
103 public String getRemarks() {
104
105 return remarks;
106
107 }
108
109 public void setRemarks(String remarks) {
110
111 this.remarks = remarks;
112
113 }
114
115 // 实现Group接口必须的几个方法
116
117 public String getName() {
118
119 return this.groupName;
120
121 }
122
123 public String getType() {
124
125 return this.groupType;
126
127 }
128
129 public String getId() {
130
131 return id;
132
133 }
134
135 }
MesGroupMembership.java 用户部门关系表
1 package com.amnet.jbpm.identify;
2
3 import java.io.Serializable;
4
5 public class MesGroupMembership implements Serializable {
6
7 private static final long serialVersionUID = 1L;
8
9 protected long dbid;
10
11 protected int dbversion;
12
13 private MesUser user;
14
15 private MesGroup group;
16
17 protected String role;
18
19 public int getDbversion() {
20
21 return dbversion;
22
23 }
24
25 public void setDbversion(int dbversion) {
26
27 this.dbversion = dbversion;
28
29 }
30
31 public long getDbid() {
32
33 return dbid;
34
35 }
36
37 public String getRole() {
38
39 return role;
40
41 }
42
43 public void setRole(String role) {
44
45 this.role = role;
46
47 }
48
49 public void setDbid(long dbid) {
50
51 this.dbid = dbid;
52
53 }
54
55 public MesGroup getGroup() {
56
57 return group;
58
59 }
60
61 public void setGroup(MesGroup group) {
62
63 this.group = group;
64
65 }
66
67 public String getUserNo() {
68
69 return user.getUserNo();
70
71 }
72
73 public String getUserID() {
74
75 return user.getId();
76
77 }
78
79 public String getUserName() {
80
81 return user.getUserName();
82
83 }
84
85 public MesUser getUser() {
86
87 return user;
88
89 }
90
91 public void setUser(MesUser user) {
92
93 this.user = user;
94
95 }
96
97 }
二:第一步完成了,那么就开始第二步。第二步的主要任务就是将这些类映射到数据库里。由于JBPM的持久层的操作采用的是Hibernate进行的。所以我们必须编写一个Hibernate的映射文件将实体类映射到数据库。
jbpm.customize.identify.hbm.xml
1 <?xml version="1.0"?>
2
3 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
4
5 <hibernate-mapping>
6 <!-- ### USER ########################################################### -->
7 <class name="com.amnet.jbpm.identify.MesUser" table="JBPM4_CUSTOMIZE_USER">
8
9 <id name="dbid" column="DBID_">
10 <generator class="assigned" />
11 </id>
12
13 <version name="dbversion" column="DBVERSION_" />
14
15 <property name="id" column="USERID_" /> <!-- 登陆ID -->
16
17 <property name="userNo" column="USERNO_" /> <!-- 员工工号 -->
18
19 <property name="userName" column="USERNAME_" /> <!-- 姓名 -->
20
21 <property name="userSex" column="USERSEX_" /> <!-- 性别 -->
22
23 <property name="userPassword" column="USERPASSWORD_" /> <!-- 密码 -->
24
25 <property name="userType" column="USERTYPE_" /> <!-- 类型 -->
26
27 <property name="userMail" column="USERMAIL_" /> <!-- 电子邮件 -->
28
29 <property name="signaturePic" column="SIGNATUREPIC_" /> <!-- 电子签名 -->
30
31 <property name="remarks" column="REMARKS_" /> <!-- 备注 -->
32
33 </class>
34
35 <!-- ### MEMBERSHIP ##################################################### -->
36 <class name="com.amnet.jbpm.identify.MesGroupMembership" table="JBPM4_CUSTOMIZE_MEMBERSHIP">
37
38 <id name="dbid" column="DBID_">
39 <generator class="assigned" />
40 </id>
41
42 <version name="dbversion" column="DBVERSION_" />
43
44 <many-to-one name="user" column="USER_"
45 class="com.amnet.jbpm.identify.MesUser" foreign-key="FK_MEM_USER"
46 index="IDX_MEM_USER" />
47
48 <many-to-one name="group" column="GROUP_"
49 class="com.amnet.jbpm.identify.MesGroup" foreign-key="FK_MEM_GROUP"
50 index="IDX_MEM_GROUP" />
51
52 <property name="role" column="NAME_" />
53
54 </class>
55
56 <!-- ### GROUP ########################################################### -->
57 <class name="com.amnet.jbpm.identify.MesGroup" table="JBPM4_CUSTOMIZE_GROUP">
58
59 <id name="dbid" column="DBID_">
60 <generator class="assigned" />
61 </id>
62
63 <version name="dbversion" column="DBVERSION_" />
64
65 <!-- private String groupID;//数据库内部ID号 private String groupName;//组织名称
66 private String groupType;//组织类型 private MesGroup parentGroup;//父组织 private
67 String remarks;//备注 -->
68
69 <property name="id" column="ID_" />
70
71 <property name="groupName" column="NAME_" />
72
73 <property name="groupType" column="TYPE_" />
74
75 <property name="remarks" column="REMARKS_" />
76
77 <many-to-one name="parentGroup" column="PARENT_"
78 class="com.amnet.jbpm.identify.MesGroup" foreign-key="FK_GROUP_PARENT"
79 index="IDX_GROUP_PARENT" />
80 </class>
81
82 </hibernate-mapping>
上面的代码是仿照JBPM默认的映射文件jbpm.identity.hbm.xml写的。这个文件可以在JBPM的源代码里面找到,导入jar包时,它被封装在jbpm.jar里面。映射文件配置好了之后,在applicationContext.xml注入自己的mappingResources:
1 <property name="mappingResources">
2 <list>
3 <value>
4 com/amnet/jbpm/identify/jbpm.customize.identify.hbm.xml
5 </value>
6 </list>
7 </property>
三:通过以上两步,就完成了由实体类到数据库的映射,也就是说,当你启动tomcat运行JBPM的时候,数据库里就会多出三张表:JBPM4_CUSTOMIZE_USER,JBPM4_CUSTOMIZE_GROUP,JBPM4_CUSTOMIZE_MEMBERSHIP。虽然如此,但是这只是利用了hibernate的自动生成数据表的功能产生了三个表而已,JBPM凭什么知道我需要使用的是我新创建的这三张表,而不会去调用原来的那三张表呢?答案是,他不知道。所以我们要继续进行配置。找到jbpm的一个配置文件叫:spring-jbpm4.xml。在这个文件里面原来有一句话:
import resource="jbpm.identity.cfg.xml"。我们可以去查看spring-jbpm4.xml的实际内容,结果里面就一句话: <transaction-context><identity-session /></transaction-context>。有了这句话,就相当于告诉了JBPM,它将会去调用JBPM自带的关于用户体系操作的一个接口IdentitySession。这个类的实现IdentitySessionImpl里就会默认去调用JBPM自带的用户关系管理的数据表。所以为了改变JBPM的这种习惯,我们就必须自己创建一个类MesIdentitySessionImpl.java,并实现接口IdentitySession。这样JBPM就会去调用我们自己的实现,而不会再去调用它自己的东东。要实现这个只需要把他的配置文件spring-jbpm4.xml 的import resource="jbpm.identity.cfg.xml“注释掉,然后加上一句:
1 <transaction-context>
2 <hibernate-session current="true"/>
3 <object class="xxx . Xxx . xxx . MesIdentitySessionImpl">
4 </object>
5 </transaction-context>
在spring-jbpm4.xml注释掉jbpm4自己的cfg.xml文件
1 <!--
2 <import resource="jbpm.identity.cfg.xml" />
3 -->
spring-jbpm4.xml
1 <?xml version="1.0" encoding="UTF-8"?>
2 <jbpm-configuration>
3 <process-engine-context>
4 <string name="spring.cfg" value="spring-jbpm4.xml" />
5 </process-engine-context>
6 <import resource="jbpm.default.cfg.xml" />
7 <import resource="jbpm.tx.spring.cfg.xml" />
8 <import resource="jbpm.jpdl.cfg.xml" />
9 <import resource="jbpm.bpmn.cfg.xml" />
10 <import resource="jbpm.businesscalendar.cfg.xml" />
11 <import resource="jbpm.console.cfg.xml" />
12
13 <!-- <import resource="jbpm.identity.cfg.xml" /> -->
14 <!-- <import resource="jbpm.jobexecutor.cfg.xml" /> -->
15
16 <transaction-context>
17 <hibernate-session current="true" />
18 <object class="com.amnet.jbpm.identify.MesIdentitySessionImpl">
19 </object>
20 </transaction-context>
21 </jbpm-configuration>
这样就OK了。下面的任务就是去实现MesIdentitySessionImpl中的方法了。
四:实现MesIdentitySessionImpl中的方法
MesIdentitySessionImpl.java 实现类
1 package com.amnet.jbpm.identify;
2
3 import java.util.Arrays;
4 import java.util.List;
5 import org.hibernate.Session;
6 import org.hibernate.criterion.Projections;
7 import org.hibernate.criterion.Restrictions;
8 import org.jbpm.api.JbpmException;
9 import org.jbpm.api.identity.Group;
10 import org.jbpm.api.identity.User;
11 import org.jbpm.pvm.internal.env.BasicEnvironment;
12 import org.jbpm.pvm.internal.env.EnvironmentImpl;
13 import org.jbpm.pvm.internal.id.DbidGenerator;
14 import org.jbpm.pvm.internal.identity.spi.IdentitySession;
15
16 @SuppressWarnings("unchecked")
17 public class MesIdentitySessionImpl implements IdentitySession {
18
19 protected Session session;
20
21 public MesIdentitySessionImpl() {
22
23 this.session = BasicEnvironment.getFromCurrent(Session.class);
24
25 }
26
27 // public String createH() {
28 //
29 // Test t = new Test();
30 //
31 // long dbid = EnvironmentImpl.getFromCurrent(DbidGenerator.class)
32 //
33 // .getNextId();
34 //
35 // t.setDbid(dbid);
36 //
37 // t.setId("abc");
38 //
39 // return null;
40 //
41 // }
42
43 public String createUser(String id, String userName,
44
45 String businessEmail, String familName) {
46
47 MesUser user = new MesUser(id, userName, businessEmail);
48
49 long dbid = EnvironmentImpl.getFromCurrent(DbidGenerator.class)
50
51 .getNextId();
52
53 user.setDbid(dbid);
54
55 session.save(user);
56
57 return user.getId();
58
59 }
60
61 public MesUser findUserById(String userId) {
62
63 return (MesUser) session.createCriteria(MesUser.class).add(
64
65 Restrictions.eq("id", userId)).uniqueResult();
66
67 }
68
69 public List<User> findUsersById(String... userIds) {
70
71 List<User> users = session.createCriteria(MesUser.class).add(
72
73 Restrictions.in("id", userIds)).list();
74
75 if (userIds.length != users.size()) {
76
77 throw new JbpmException("not all users were found: "
78
79 + Arrays.toString(userIds));
80
81 }
82
83 return users;
84
85 }
86
87 public List<User> findUsers() {
88
89 return session.createCriteria(MesUser.class).list();
90
91 }
92
93 public void deleteUser(String userId) {
94
95 // lookup the user
96
97 MesUser user = findUserById(userId);
98
99 // cascade the deletion to the memberships
100
101 List<MesGroupMembership> memberships = session.createCriteria(
102
103 MesGroupMembership.class).add(Restrictions.eq("user", user)).list();
104
105 // delete the related memberships
106
107 for (MesGroupMembership membership : memberships) {
108
109 session.delete(membership);
110
111 }
112
113 // delete the user
114
115 session.delete(user);
116
117 }
118
119 public String createGroup(String groupName, String groupType,
120
121 String parentGroupId) {
122
123 MesGroup group = new MesGroup();
124
125 String groupId = groupType != null ? groupType + "." + groupName
126
127 : groupName;
128
129 group.setId(groupId);
130
131 long dbid = EnvironmentImpl.getFromCurrent(DbidGenerator.class)
132
133 .getNextId();
134
135 group.setDbid(dbid);
136
137 group.setGroupName(groupName);
138
139 group.setGroupType(groupType);
140
141 if (parentGroupId != null) {
142
143 MesGroup parentGroup = findGroupById(parentGroupId);
144
145 group.setParentGroup(parentGroup);
146
147 }
148
149 session.save(group);
150
151 return group.getId();
152
153 }
154
155 public List<User> findUsersByGroup(String groupId) {
156
157 return session.createCriteria(MesGroupMembership.class).createAlias(
158
159 "group", "g").add(Restrictions.eq("g.id", groupId))
160
161 .setProjection(Projections.property("user")).list();
162
163 }
164
165 public MesGroup findGroupById(String groupId) {
166
167 return (MesGroup) session.createCriteria(MesGroup.class).add(
168
169 Restrictions.eq("id", groupId)).uniqueResult();
170
171 }
172
173 public List<Group> findGroupsByUserAndGroupType(String userId,
174
175 String groupType) {
176
177 return session.createQuery(
178
179 "select distinct m.group" + " from "
180
181 + MesGroupMembership.class.getName()
182
183 + " as m where m.user.id = :userId"
184
185 + " and m.group.type = :groupType").setString("userId",
186
187 userId).setString("groupType", groupType).list();
188
189 }
190
191 public List<Group> findGroupsByUser(String userId) {
192
193 List<Group> gList = session.createQuery(
194
195 "select distinct m.group" + " from "
196
197 + MesGroupMembership.class.getName()
198
199 + " as m where m.user.id = :userId").setString(
200
201 "userId", userId).list();
202
203 return gList;
204
205 }
206
207 public List<Group> findGroups() {
208
209 return session.createCriteria(MesGroup.class).list();
210
211 }
212
213 public void deleteGroup(String groupId) {
214
215 // look up the group
216
217 MesGroup group = findGroupById(groupId);
218
219 // cascade the deletion to the memberships
220
221 List<MesGroupMembership> memberships = session.createCriteria(
222
223 MesGroupMembership.class).add(Restrictions.eq("group", group))
224
225 .list();
226
227 // delete the related memberships
228
229 for (MesGroupMembership membership : memberships) {
230
231 session.delete(membership);
232
233 }
234
235 // delete the group
236
237 session.delete(group);
238
239 }
240
241 public void createMembership(String userId, String groupId, String role) {
242
243 MesUser user = findUserById(userId);
244
245 if (user == null) {
246
247 throw new JbpmException("user " + userId + " doesn't exist");
248
249 }
250
251 MesGroup group = findGroupById(groupId);
252
253 if (group == null) {
254
255 throw new JbpmException("group " + groupId + " doesn't exist");
256
257 }
258
259 MesGroupMembership membership = new MesGroupMembership();
260
261 membership.setUser(user);
262
263 membership.setGroup(group);
264
265 membership.setRole(role);
266
267 long dbid = EnvironmentImpl.getFromCurrent(DbidGenerator.class)
268
269 .getNextId();
270
271 membership.setDbid(dbid);
272
273 session.save(membership);
274
275 }
276
277 public void deleteMembership(String userId, String groupId, String role) {
278
279 MesGroupMembership membership = (MesGroupMembership) session
280 .createCriteria(
281
282 MesGroupMembership.class).createAlias("user", "u").createAlias(
283
284 "group", "g").add(Restrictions.eq("u.id", userId)).add(
285
286 Restrictions.eq("g.id", groupId)).uniqueResult();
287
288 session.delete(membership);
289
290 }
291
292 }
五:测试类
集成自己的表就完成了。当你调用 identityService.createUser()方法时,就往你自定义的user表里插入了一条记录。
TestMesIdentitySession.java 新建用户和组
1 package com.amnet.action;
2
3 import org.jbpm.api.IdentityService;
4 import org.jbpm.api.ProcessEngine;
5 import org.springframework.context.support.ClassPathXmlApplicationContext;
6
7 public class TestMesIdentitySession {
8
9 /**
10 * @param args
11 */
12 public static void main(String[] args) {
13 ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(
14 "applicationContext.xml");
15 applicationContext.start();
16 ProcessEngine processEngine = (ProcessEngine) applicationContext
17 .getBean("processEngine");
18
19 // ExecutionService executionService = processEngine.getExecutionService();
20 //
21 // TaskService taskService = processEngine.getTaskService();
22
23 IdentityService identityService = processEngine.getIdentityService();
24
25 identityService.createGroup("user_dept"); // 部门
26
27 identityService.createUser("user1", "test1", "test1"); // 新建用户1
28
29 identityService.createUser("user2", "test2", "test2"); // 新建用户2
30
31 identityService.createMembership("user1", "user_dept"); // 绑定用户和部门的关系
32
33 identityService.createMembership("user2", "user_dept");
34 }
35 }
发布流程
1 ProcessEngine processEngine = Configuration.getProcessEngine();
2
3 RepositoryService repositoryService = processEngine
4
5 .getRepositoryService();
6
7 String deployId = repositoryService.createDeployment().addResourceFromClasspath("com/contract/contract.jpdl.xml").deploy();
删除流程
repositoryService.deleteDeploymentCascade(deployId));
开始流程实例
executionService.startProcessInstanceById(request.getParameter("id"));