Avtiviti用户组与用户
作为流程中的基础数据,Activiti提供了一套控制用户组与用户的API,通过这些API,可以对流程的基础数据进行管理。本章将详细讲解Activiti中用户组和用户的设计,并且使用这些API来完成工作。在Activiti中,管理这些数据的服务组件为IdentityService,其对应的表结构如下:
1、用户组管理
某些企业会将相同职能的人作为一类人进行管理,也会有某些企业,将相同的角色(职能不同)作为一类人进行管理,这些类别就是用户组。Activiti中用户组对应的表为
ACT_ID_GROUP
,该表只有4个字段。
1.1、Group对象
Group是一个接口,一个Group实例表示一条用户组数据,对应的表为ACT_ID_GROUP。该接口只提供了相应字段的getter和setter方法,这种数据与对象的映射关系,在各个ORM框架中使用很普遍,例如Hibernate、MyBatis等。
在Activiti中,每个实体会有自己的接口与实现类,以Group接口为例,有一个GroupEntity的子接口,还有一个GroupEntityImpl的实现类。在Activiti的API文档中,并没有开放GroupEntity与GroupEntityImpl的API,创建Group实例,要调用业务组件方法。Activiti不希望使用者去关心这些实体的创建,这样做的好处是,即使Activiti在以后版本中发生设计的变化,也可以减少对使用者的影响。GroupEntity中包含以下映射属性。
- id:主键,对应ACT_ID_GROUP表的ID_列。
- name:用户组名称,对应ACT_ID_GROUP表的NAME_列。
- type:用户组类型,对应ACT_ID_GROUP表的TYPE_列。
- revision:该用户组数据的版本,对应ACT_ID_GROUP表的REV_列。
1.2、创建用户组
IdentityService提供了newGroup方法来创建Group实例,得到由IdentityService创建的实例后,可以调用相应的setter方法设置相应字段,最后调用saveGroup方法,将Group保存到数据库中。
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
IdentityService identityService = engine.getIdentityService();
//生成UUID
String uuid = UUID.randomUUID().toString();
//创建Group实例
Group group = identityService.newGroup(uuid);
group.setName("经理组");
group.setType("manager");
//保存到数据库
identityService.saveGroup(group);
//查询用户组
Group g = identityService.createGroupQuery().groupId(uuid).singleResult();
System.out.println("Group ID:" + g.getId() + ",Name:" + g.getName());
需要注意的是,调用newGroup方法需要提供Group的ID值如果将ID值设置为null,则调用newGroup方法时会抛出ActivitiException,异常信息为:groupld is null.
IdentityService的saveGroup方法会判断Group的revision属性(对应ACT_ID_GROUP表的REV字段)是否为0,版本号为0则做新增处理,反之则做修改处理。Goup接口并不提供设置与获取revision的方法,因此该属性的变化,我们不需要关心。
调用newGroup时,需要指定ID值,由于ID字段是ACT_ID_GROUP表的主键,因此如果让使用者来设定ID值,可能会出现ID重复的问题。
解决主键重复的问题,可以让Activiti生成主键,但不提供主键,newGroup方法又会抛出异常,以下代码可以解决该问题:
//生成UUID
String uuid = UUID.randomUUID().toString();
//创建Group实例
Group group = identityService.newGroup(uuid);
group.setName("经理组");
group.setType("manager");
group.setId(null);
//保存到数据库
identityService.saveGroup(group);
1.3、修改用户组
修改用户组,同样调用saveGroup方法,只需要在调用该方法前,将相应的用户组对象查询出来,然后设置相应字段的值即可。第二次调用saveGroup方法时,会判断Group的REV值,如果该值不为0,会被视作修改操作。
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
IdentityService identityService = engine.getIdentityService();
Group group = identityService.createGroupQuery().groupName("经理组").singleResult();
group.setName("经理2组");
identityService.saveGroup(group);
1.4、删除用户组
IdentityService提供了一个deleteGroup方法用于删除用户组数据,用户与用户组数据属于Activiti中的基础数据,这些数据会被流程中的各类数据引用(一般使用ID列作为外键关联),此时要删除这些基础数据,可以使用以下两种设计方案。
- 第一种方案:做外键关联,所有使用到用户或者用户组的地方,使用相应的字段做外键关联,该外键指向用户组或者用户表的ID列。
- 第二种方案:不做外键关联,除了身份等模块外,其他使用到用户组或者用户数据的模块,同样提供一个字段来保存用户组或用户数据的外键,但该字段不关联任何表。
采用第一种方案,在删除基础数据时,会导致无法删除或者级联删除,这种方式会加强模块间的耦合。采用第二种方案,其他使用基础数据的模块中,都要考虑这些引用的数据ID是否已经被删除。
Activiti各模块间的数据引用,采用的是第二种方案,与用户组关联的数据表,仅仅提供一个字段来记录用户组id,没有做外键关联。Activiti的用户组与用户的关系表,就做了外键关联。这里所说的关系表,是用于保存用户组和用户关系的表(ACT_ID_MEMBERSHIP)。由于一个用户有可能属于多个用户组,一个用户组下会有多个用户,对于这种多对多的关系,很多系统都采用中间表的方式来记录它们
之间的关系。
由于用户组与用户的关系表做了用户组的外键关联,因此删除用户组的deleteGroup方法在执行时,会先将这些关联数据删除,然后再删除用户组数据。
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
IdentityService identityService = engine.getIdentityService();
String uuid = UUID.randomUUID().toString();
Group group = identityService.newGroup(uuid);
group.setName("经理组");
group.setType("manager");
identityService.saveGroup(group);
//查询
System.out.println("保存后用户组数量:" + identityService.createGroupQuery().count());
//根据id删除用户组
identityService.deleteGroup(uuid);
System.out.println("删除后用户组数量:" + identityService.createGroupQuery().count());
2、Avtiviti数据查询
Activiti提供了一套数据查询API供开发者使用,可以使用各个服务组件的createXXXQuery方法来获取这些查询对象。本节将结合用户组数据来讲解Activiti的数据查询设计,这些设计可应用于整个Activiti的数据查询体系。
2.1、查询对象
Activiti的各个服务组件(XXXService)均提供了createXXXQuery方法,例如IdentityService中的createGroupQuery方法和createUserQuery方法,TaskService中的craeteTaskQuery方法等。这些方法返回一个Query实例,例如createGroupQuery返回GroupQuery,GroupQuery是Query的子接口。
Query是所有查询对象的父接口,该接口中定义了若干个基础方法,各个查询对象均可以使用这些公共方法,包括设置排序方式、数据量统计(cout)、列表、分页和唯一记录查询。这些方法描述如下。
- asc:设置查询结果的排序方式为升序。
- count:计算查询结果的数据量。
- desc:设置查询结果的排序方式为降序。
- 1ist:封装查询结果,返回相应类型的集合。
- listPage:分页返回查询结果。
- singleResult::查询单条符合条件的数据,如果查询不到,则返回null;如果查询到多条记录,则抛出异常。
2.2、list方法
Quey接口的ist方法,将查询对象对应的实体数据以集合形式返回,对于返回的集合需要指定元素类型。如果没有查询条件,则会将表中全部的数据查出,默认按照主键(ID列)
升序排序。
@Test
public void list() {
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
IdentityService identityService = engine.getIdentityService();
//写入5条数据
createGroup(identityService, "1", "GroupA", "typeA");
createGroup(identityService, "2", "GroupB", "typeB");
createGroup(identityService, "3", "GroupC", "typeC");
createGroup(identityService, "4", "GroupD", "typeD");
createGroup(identityService, "5", "GroupF", "typeF");
//使用list方法查询
List<Group> datas = identityService.createGroupQuery().list();
for (Group data : datas) {
System.out.println(data.getId() + "-->" + data.getName());
}
}
private void createGroup(IdentityService identityService, String id, String name, String type) {
Group group = identityService.newGroup(id);
group.setName(name);
group.setType(type);
identityService.saveGroup(group);
}
2.3、listPage方法
listPage方法与Iist方法类似,最终也是以主键升序排序返回结果集,与list方法不一样的是,listPage方法需要提供两个int参数,第一个参数为数据的开始索引,从0开始,第二个参数为结果数量,不难看出,该方法适用于分页查询。
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
IdentityService identityService = engine.getIdentityService();
List<Group> datas = identityService.createGroupQuery().listPage(2, 3);
for (Group data : datas) {
System.out.println(data.getId() + "-->" + data.getName());
}
2.4、count方法
该方法用于计算查询结果的数据量,类似于SQL中的SELECT COUNT语句,如果不加任何条件,将会统计整个表的数据量。
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
IdentityService identityService = engine.getIdentityService();
long count = identityService.createGroupQuery().count();
System.out.println(count);
2.5、排序方法
Quey中提供了asc和desc方法,使用这两个方法可以设置查询结果的排序方式,但是调用这两个方法的前提是,必须告诉Quey对象,按何种条件进行排序,例如要按照D排序,就要调用相应查询对象的orderByXXX方法,或者GroupQuery的orderByGroupld、orderByGroupName等方法,如果不调用这些方法而直接使用asc或者desc方法,则会抛出ActivitiException,异常信息为:You should call any of the orderBy methods first before specifying a direction.。要求Activiti进行排序,却不告诉它以哪个字段进行排序,因此会抛出异常。
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
IdentityService identityService = engine.getIdentityService();
//按照id升序排序
List<Group> list = identityService.createGroupQuery().orderByGroupId().asc().list();
for (Group g : list) {
System.out.println(g.getId() + "-->" + g.getName());
}
2.6、多字段排序
在进行数据查询时,如果想对多个字段进行排序,例如按名称降序、ID升序排序,那么在调用asc和desc方法时就需要注意,asc和desc方法会根据Query实例(AbstractQuery)
中的orderProperty属性来决定排序的字段,由于orderProperty是AbstractQuery的类属性,因此在第二次调用orderByXXX方法后,会覆盖第一次调用时所设置的值。
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
IdentityService identityService = engine.getIdentityService();
//先按ID排序、名称升序排序
List<Group> list = identityService.createGroupQuery()
.orderByGroupId().desc()
.orderByGroupName().asc().list();
for (Group g : list) {
System.out.println(g.getId() + "-->" + g.getName());
}
//按名称排序
List<Group> groups = identityService.createGroupQuery().orderByGroupId().orderByGroupName().desc().list();
for (Group g : groups) {
System.out.println(g.getId() + "-->" + g.getName());
}
在第二个查询中,虽然也调用了orderByGroupId方法,但是由于没有马上调用desc方法,而是调用了其他的orderBy方法,因此原来的orderByGroupld方法所设置的排序属性(Query的orderProperty属性)将会被orderByGroupName替换。
2.7、singleResult方法
该方法根据查询条件,到数据库中查询唯一的数据记录,如果没有找到符合条件的数据,则返回null,如果找到多于一条的记录,则抛出异常,异常信息为:Query return2 results insteadof max1。
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
IdentityService identityService = engine.getIdentityService();
//写入一条名称为GroupA的记录
createGroup(identityService, UUID.randomUUID().toString(), "GroupA", "typeF");
//查询名为GroupB的记录
Group groupB = identityService.createGroupQuery().groupName("GroupB").singleResult();
System.out.println(groupB.getId() + "-->" + groupB.getName());
//查询名为GroupZ的记录
Group groupZ = identityService.createGroupQuery().groupName("GroupZ").singleResult();
System.out.println(groupZ == null);
//查询名为GroupA的记录,这里将抛出异常,因为查询到2条记录
try {
Group groupA = identityService.createGroupQuery().groupName("GroupA").singleResult();
} catch (Exception e) {
e.printStackTrace();
}
2.8、用户组数据查询
Activiti的每种数据均有对应的查询对象,例如用户组的查询对象为GroupQuery,它继承了AbstractQuery,除了拥有基类的方法(asc、count、desc、list、ListPage及singleResult方法)外,它还拥有自己的查询及排序方法。
- groupld(String groupld):根据ID查询与参数值一致的记录。
- groupMember(String groupMemberUserld):根据用户ID查询用户所在的用户组,用户组与用户为多对多关系,因此一个用户有可能属于多个用户组。
- groupName(String groupName):根据用户组名称查询用户组。
- groupNameLike(String groupName):根据用户组名称模糊查询用户组数据。
- groupType(String groupType):根据用户组类型查询用户组数据。
- orderByGroupId():设置排序条件为根据D排序。
- orderByGroupName():设置排序条件为根据名称排序。
- orderByGroupType():设置排序条件为根据类型排序。
- potentialStarter(String procDefId):根据流程定义的ID查询有权限启动该流程定义的用户组。
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
IdentityService identityService = engine.getIdentityService();
//groupId
Group g1 = identityService.createGroupQuery().groupId("1").singleResult();
System.out.println("groupId method:" + g1);
//groupName
Group g2 = identityService.createGroupQuery().groupName("GroupB").singleResult();
System.out.println("groupName method:" + g2);
//groupType
Group g3 = identityService.createGroupQuery().groupType("typeC").singleResult();
System.out.println("groupType method:" + g3);
//groupNameLike
List<Group> list = identityService.createGroupQuery().groupNameLike("%group%").list();
System.out.println("groupNameLike method:" + list);
2.9、原生SQL查询
在各个服务组件中,都提供了createNativeXXXQuery方法,该方法返回NativeXXXQuery的实例,这些对象均是NativeQuery的子接口。使用NativeQuery的方法,可以传入原生的SQL进行数据查询,主要使用sql方法传入SQL语句,使用parameter方法设置查询参数。
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
IdentityService identityService = engine.getIdentityService();
//使用原生SQL查询
List<Group> list = identityService.createNativeGroupQuery()
.sql("select * from ACT_ID_GROUP").list();
System.out.println(list);
list = identityService.createNativeGroupQuery()
.sql("select * from ACT_ID_GROUP where NAME_ = 'GroupC'").list();
System.out.println(list);
//使用parameter方法设置查询参数
list = identityService.createNativeGroupQuery()
.sql("select * from ACT_ID_GROUP where NAME_ = #{name}")
.parameter("name", "GroupD").list();
System.out.println(list);
3、用户管理
作为流程基本元素之一,Activiti同样为用户数据提供了一套管理的API,用户数据保存在ACT_ID_USER表中,除了该表外,Activiti还提供了ACT_ID_USER表用于保存用户信息
数据。
3.1、User对象
与Group对象一样,User对象同样为一个接口,其有一个子接口UserEntity,实现类为UserEntityImpl。
UserEntityImpl包含以下映射属性。
- id:用户D,对应ACT_ID_USER表的D列。
- firstName:用户的姓,对应ACT_ID_USER表的FIRST列。
- lastName:用户的名,对应ACT_ID_USER表的LAST列。
- email::用户邮箱,对应ACT_ID_USER表的EMAIL列。
- password:用户密码,对应ACT_ID_USER表的PWD列。
- pictureByteArrayId:用户图片的数据记录ID,对应ACT_ID_USER表的PICTURE_ID列,该列保存ACT_GE_BYTEARRAY表数据的D。
- revision:该用户数据的版本,对应ACT_ID_USER表的REV列。
3.2、添加用户
添加用户与创建用户组类似,Activiti也提供了一个创建User实例的方法(newUser),还提供了一个保存用户数据的方法(saveUser),类似于用户组的newGroup与saveGroup方法。
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
IdentityService identityService = engine.getIdentityService();
String id = UUID.randomUUID().toString();
User user = identityService.newUser(id);
user.setFirstName("acton");
user.setLastName("zhang");
user.setEmail("xx@qq.com");
user.setPassword("123");
identityService.saveUser(user);
//查询
user = identityService.createUserQuery().userId(id).singleResult();
System.out.println(user.getEmail());
3.3、修改用户
修改用户同样需要调用saveUser方法,调用该方法前需要查询相应的用户数据,为其设置需要修改的属性值,最后执行保存操作即可。
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
IdentityService identityService = engine.getIdentityService();
User user = identityService.createUserQuery().userEmail("xx@qq.com").singleResult();
user.setPassword("88888");
identityService.saveUser(user);
3.4、删除用户
用户是流程基本的元素,与用户组同属于Activiti的基础数据,一旦流程或者其他数据引用了用户的外键,同样会带来无法删除用户的问题,删除用户,会先删除本模块中与用户关联的数据,例如图片、用户信息、用户(用户组》
中间表。删除用户时,Activiti选择了删除这些它“知道”的数据。
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
IdentityService identityService = engine.getIdentityService();
System.out.println(identityService.createUserQuery().count());
identityService.deleteUser("c48ada8f-77ff-4470-b964-eda1003b487a");
System.out.println(identityService.createUserQuery().count());
3.5、验证用户密码
IdentityService中提供了一个checkPassword方法来验证用户的密码。在用户模块,需要分清用户与账号的概念。对于Activiti来说,用户是一类数据,而账号则是从属于某个用户的数据。此处所说的验证密码,是指验证用户的密码(ACT_ID_USER表的PWD字段),而不是用户账号的密码。关于用户账号:
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
IdentityService identityService = engine.getIdentityService();
String id = UUID.randomUUID().toString();
User user = identityService.newUser(id);
user.setFirstName("acton");
user.setLastName("zhang");
user.setEmail("xx@qq.com");
user.setPassword("123");
identityService.saveUser(user);
//验证用户密码
System.out.println(identityService.checkPassword(id, "abc"));//false
System.out.println(identityService.checkPassword(id, "123"));//true
3.6、用户数据查询
与用户组类似,用户同样有一个UserQuery查询对象,并且该对象也提供了相应的查询与排序方法,我们也可以调用list或者singleResult方法返回查询数据。UserQuery中包括了如下这些方法。
- userEamil((String email):根据Email值查询用户数据。
- usreEmailLike(String emailLike):根据Email值模糊查询用户数据。
- userFirstName(String firstName):根据用户的姓查询用户数据。
- userFirstNameLike(String firstNameLike):根据用户的姓模糊查询用户数据。
- userId(String id):根据用户ID查询用户数据。
- userLastName(String lastName):根据用户的名查询用户数据。
- userLastNameLike(String lastNameLike):根据用户的名模糊查询用户数据。
- memberOfGroup(String groupld):根据用户组ID查询属于该组的全部用户数据。
- orderByUserEmail():设置根据Email进行排序。
- orderByUserFirstName():设置根据用户的姓进行排序。
- orderByUserId():设置根据D进行排序。
- orderByUserLastName():设置根据用户的名进行排序。
- potentialStarter(String procDefId):根据流程定义的ID查询有权限启动流程定义的用户。
@Test
public void queryUser() {
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
IdentityService identityService = engine.getIdentityService();
String id1 = UUID.randomUUID().toString();
String id2 = UUID.randomUUID().toString();
//创建两个用户
creatUser(identityService,id1,"angus","young",
"yangenxiong@163.com","abc");
creatUser(identityService,id2,"angus2","young2","abc@163.com",
"123");
//调用UserQuery的各个查询方法
//userId
User user = identityService.createUserQuery().userId(id1).singleResult();
System.out.println("userId:"+user.getFirstName());
//userFirstName
user = identityService.createUserQuery().userFirstName("angus").singleResult();
System.out.println ("userFirstName:"+user.getFirstName());
//userFirstNameLike
List<User> datas = identityService.createUserQuery().userFirstNameLike("angus").list();
System.out.println("createUserQuery:" + datas.size());
//userLastName
user = identityService.createUserQuery().userLastName("young").singleResult();
System.out.println("userLastName:"+user.getFirstName ());
//userLastNameLike
datas = identityService.createUserQuery().userLastNameLike("young3").list();
System.out.println ("userLastNameLike:" + datas.size());
//userEmail
user = identityService.createUserQuery().userEmail("abc@163.com").singleResult();
System.out.println("userEmail:"+user.getFirstName());
//userEmailLike
datas = identityService.createUserQuery().userEmailLike("$163.com").list();
System.out.println ("userEmailLike:"+datas.size());
//使用NativeQuery
datas = identityService.createNativeUserQuery()
.sql("select * from ACT_ID_USER where EMAIL_ = #{email}")
.parameter("email","yangenxiong@163.com").list();
System.out.println("native query:" + datas.get(0).getEmail());
}
//创建用户方法
private void creatUser(IdentityService identityService,String id,
String first,String last,String email,String passwd){
//使用newUser方法创建User实例
User user = identityService.newUser(id);
//设置用户的各个属性
user.setFirstName(first);
user.setLastName(last);
user.setEmail (email);
user.setPassword(passwd);
//使用saveUser方法保存用户
identityService.saveUser(user);
}
3.7、设置认证用户
IdentityService中提供了一个setAuthenticatedUserId方法来将用户ID设置到当前的线程中,setAuthenticatedUserld方法最终调用的是ThreadLocal的set方法。这意味着,如果启动两条线程,在线程中分别调用setAuthenticatedUserId方法,则在相应线程中会输出不同的结果:
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
final IdentityService identityService = engine.getIdentityService();
//设置当前线程的userID为1
identityService.setAuthenticatedUserId("3");
System.out.println("当前线程userId:" + Authentication.getAuthenticatedUserId());
//启动两条线程
new Thread() {
@Override
public void run() {
identityService.setAuthenticatedUserId("1");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程1的userId:" + Authentication.getAuthenticatedUserId());
}
}.start();
new Thread() {
@Override
public void run() {
identityService.setAuthenticatedUserId("2");
System.out.println("线程2的userId:" + Authentication.getAuthenticatedUserId());
}
}.start();
4、用户信息管理
Activiti将一些用户相关的信息抽象出来,使用单独的一个数据表来保存。这些用户相关的信息包括账号信息和自定义的用户信息,这些信息均保存在ACT_ID_INFO表中。除了这些用户信息外,还有用户的图片资源,图片被保存在Activiti公共的资源表ACT_GE_BYTEARRAY中。
4.1、添加和删除用户信息
就像用户组与用户的数据一样,同样有一个实体与用户信息映射,对应的实体类为IdentityInfoEntityImpl,但是与用户和用户组不一样的是,Activiti并没有为其提供相应的Query
对象,因为这个表的数据结构是key-value形式,只需要知道key就可以查询到相应的数据。
以下为添加和删除用户方法的描述。
- setUserInfo(String userld,String key,String value):为用户添加用户信息,第一个参数为用户数据的D,第二个参数为用户信息的名称,第三个参数为该用户信息的值。
- deleteUserInfo(String userId,String key):删除用户信息,第一个参数为用户ID,第二个参数为用户信息的名称。
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
IdentityService identityService = engine.getIdentityService();
String id = UUID.randomUUID().toString();
//创建用户
creatUser(identityService, id, "tom", "zhang", "xx@qq.com", "123");
//创建用户信息
identityService.setUserInfo(id, "age", "18");
identityService.setUserInfo(id, "height", "100cm");
//删除用户信息
identityService.deleteUserInfo(id, "height");
4.2、查询用户信息
成功将用户信息保存到数据库后,如果需要使用这些信息,则可以调用IdentityService的getUserInfo方法来查找这些信息,使用该方法需要提供用户的ID与信息的键值。调用该方法后,将返回相应信息的字符串。
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
IdentityService identityService = engine.getIdentityService();
String id = UUID.randomUUID().toString();
//创建用户
creatUser(identityService, id, "tom", "zhang", "xx@qq.com", "123");
//创建用户信息
identityService.setUserInfo(id, "age", "18");
identityService.setUserInfo(id, "height", "100cm");
//查询用户信息
String age = identityService.getUserInfo(id, "age");
System.out.println(age);
4.3、设置用户图片
Activiti专门提供了一个数据表来保存文件数据,即ACT_GE_BYTEARRAY表。Activiti会读取文件,并将这些文件转换为byte数组,然后保存到表中。IdentityService提供了setUserPicture和getUserPicture方法用来设置和查找用户图片数据,其中对setUserPicture方法需要设置两个参数:用户ID和Picture实例。
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
IdentityService identityService = engine.getIdentityService();
String id = UUID.randomUUID().toString();
//创建用户
creatUser(identityService, id, "tom", "zhang", "xx@qq.com", "123");
//读取图片并转换为byte数组
FileInputStream fis = new FileInputStream(new File("/Users/acton_zhang/J2EE/IdeaWrokSpace/activiti_demo/src/main/resources/522.jpg"));
BufferedImage img = ImageIO.read(fis);
ByteArrayOutputStream output = new ByteArrayOutputStream();
ImageIO.write(img, "jpg", output);
//获取图片的byte数组
byte[] picArray = output.toByteArray();
//创建Picture实例
Picture picture = new Picture(picArray, "tom_image");
//设置用户图片
identityService.setUserPicture(id, picture);
5、用户组与用户的关系
在Activiti中,一个用户可以被分配到多个用户组中,一个用户组中可以包含多个用户,针对这种情况,Activiti使用了中间表来保存这两种数据间的关系。通过关系表的数据,可以清楚地看到用户组与用户之间的关系,Activiti也提供了相应的API来操作这种关系。这个中间表为ACT_ID_MEMBERSHIP表,这里需要注意的是,Activiti并没有为这个表做实体的映射。
5.1、绑定关系
绑定关系,意味着向ACT_ID_MEMBERSHIP表写入一条关系数据,只需要指定这个关系的用户ID和用户组ID,再调用IdentityService的createMembership方法即可,该方法第
个参数为用户ID,第二个参数为用户组ID。
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
IdentityService identityService = engine.getIdentityService();
String userId = UUID.randomUUID().toString();
String groupId = UUID.randomUUID().toString();
//保存用户
creatUser(identityService, userId, "a", "b", "ss@aa.com", "123");
//保存用户组
createGroup(identityService, groupId, "mike", "hr");
//绑定关系
identityService.createMembership(userId, groupId);
5.2、解除绑定
解除用户组与用户的关系绑定,无非是将ACT_ID_MEMBERSHIP表中的关系数据删除,
IdentityService提供了一个deleteMembership方法用于将ACT_ID_MEMBERSHIP表中的数据删除。使用该方法需要提供用户ID与用户组ID,该方法的使用如以下代码所示:
identityService.deleteMembership(user.getId(),group.getId());
在此需要说明的是,如果用户ID和用户组ID对应的数据并不存在于数据库中,执行deleteMembership方法也不会抛出任何异常,也不会对数据库中的数据产生任何的影响。
5.3、查询用户组下的用户
根据中间表的设计,大致可以猜到memberOfGroup方法的实现过程,先到ACT_ID_MEMBERSHIP表中根据groupld进行查询,获取全部的userId后,再到ACT_ID_USER表中查询用户数据。
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
IdentityService identityService = engine.getIdentityService();
String userId1 = UUID.randomUUID().toString();
String userId2 = UUID.randomUUID().toString();
String groupId = UUID.randomUUID().toString();
//保存两个用户
creatUser(identityService, userId1, "f1", "l1", "aa@aa.com", "123");
creatUser(identityService, userId2, "f2", "l2", "aa@aa.com", "123");
//保存一个用户组
createGroup(identityService, groupId, "经理组", "manager");
//分配
identityService.createMembership(userId1, groupId);
identityService.createMembership(userId2, groupId);
//查询
List<User> users = identityService.createUserQuery().memberOfGroup(groupId).list();
for (User u : users) {
System.out.println(u.getFirstName());
}
5.4、查询用户所属的用户组
与memberOfGroup方法类似,groupMember方法会根据用户的ID,查询该用户所属的用户组。同样,该方法会到中间表中查询该用户的全部关系数据并且得到groupId,然后根据这些groupId再到用户组的表中查询用户组数据。
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
IdentityService identityService = engine.getIdentityService();
String userId = UUID.randomUUID().toString();
String groupId1 = UUID.randomUUID().toString();
String groupId2 = UUID.randomUUID().toString();
//创建一个用户
creatUser(identityService, userId, "张三", "young", "aaa@aa.com", "123");
//创建两个用户组
createGroup(identityService, groupId1, "人事组", "hr");
createGroup(identityService, groupId2, "业务组", "emp");
//分配
identityService.createMembership(userId, groupId1);
identityService.createMembership(userId, groupId2);
//查询
List<Group> groups = identityService.createGroupQuery().groupMember(userId).list();
for (Group g : groups) {
System.out.println(g.getName());
}