Activiti——用户组与用户IdentityService API详解

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());
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值