本次整合过程全程使用了Bean方式的配置,因为是初学者,配置可能有问题,还忘指出,感谢感谢感谢
使用到的技术栈:mybatis-plus、springboot、activiti和druid连接池
依赖
// 版本
// springboot :'2.4.3', // SpringBoot版本号
// activiti :'7.0.0.Beta5', // activiti 版本
// mybatis :'3.5.6', // mybatis 版本
// mybatisSpringBoot :'2.2.0', // mybatis-spring-boot
// mybatisPlus :'3.4.3', // mybatisPlus 版本
project('anyboot-web') {
dependencies { // 配置子模块依赖
compile(project(':anyboot-common')) // 引入其他子模块
compile('org.springframework.boot:spring-boot-starter-actuator') //引入springboot actuator依赖
compile('org.springframework.boot:spring-boot-starter-aop') //引入springboot aop相关依赖
// compile('org.springframework.boot:spring-boot-starter-data-redis') // redis
// 引入activiti 依赖
compile(libraries.'activiti-engine')
compile(libraries.'activiti-spring')
// 引入连接mysql的依赖
compile(libraries.'mysql-connector-java')
// 引入druid的依赖
compile(libraries.'druid')
// 引入mybatis的依赖
compile(libraries.'mybatis')
compile(libraries.'mybatis-spring-boot-starter')
compile(libraries.'mybatis-plus')
compile(libraries.'fastjson')
}
}
application.yml 的基本信息
server:
port: 80 # 配置端口
# 日志配置
logging:
config: classpath:logback/logback-spring.xml
shiro:
userNativeSessionManager: true # 允许采用非HTTP的模式进行访问
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/study-springboot-activiti
username: root
password: 123456
druid: # druid相关配置
initial-size: 5 # 初始化连接池大小
min-idle: 10 # 最小维持的连接池大小
max-active: 50 # 最大支持的连接池大小
max-wait: 60000 # 最大等待时间(毫秒)
time-between-eviction-runs-millis: 60000 # 关闭空闲连接间隔(毫秒)
min-evictable-idle-time-millis: 30000 # 连接最小生存时间(毫秒)
validation-query: SELECT 1 FROM dual # 数据库状态检测
test-while-idle: true # 申请连接的时候检测连接是否有效
test-on-borrow: false # 申请连接时检测连接是否有效
test-on-return: false # 归还连接时检测连接是否有效
pool-prepared-statements: false # PSCache缓存
max-pool-prepared-statement-per-connection-size: 20 # 配置PS缓存
mybatis-plus:
config-location: classpath:META-INF/mybatis/mybatis.cfg.xml
type-aliases-package: com.any.entity
mapper-locations: classpath:META-INF/mybatis/mapper/**/*.xml # 所有的mapper映射文件
global-config:
db-config:
logic-not-delete-value: 0 # 数据删除前
logic-delete-value: 1 # 数据删除后
druid数据源的配置类
package com.any.config;
import com.alibaba.druid.filter.Filter;
import com.alibaba.druid.filter.logging.Slf4jLogFilter;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.ArrayList;
import java.util.List;
/**
* DruidDataSourceConfiguration
*
* @author 15821
* @date 13:11 2021/12/11
*/
@Configuration
public class DruidDataSourceConfiguration {
@Bean("defaultDruidDataSource")
public DruidDataSource getDruidDataSource(
@Value("${spring.datasource.driver-class-name}")
String driverClassName, // 数据库驱动程序
@Value("${spring.datasource.url}")
String url, // 数据库连接地址
@Value("${spring.datasource.username}")
String username, // 数据库的用户名
@Value("${spring.datasource.password}")
String password, // 数据库的用户名
@Value("${spring.datasource.druid.initial-size}")
int initialSize, // 初始化连接数
@Value("${spring.datasource.druid.min-idle}")
int minIdle, // 最小维持连接数
@Value("${spring.datasource.druid.max-active}")
int maxActive, // 最大连接数
@Value("${spring.datasource.druid.max-wait}")
long maxWait, // 最长等待时间
@Value("${spring.datasource.druid.time-between-eviction-runs-millis}")
long timeBetweenEvictionRunsMillis, // 关闭空闲连接间隔
@Value("${spring.datasource.druid.min-evictable-idle-time-millis}")
long minEvictableIdleTimeMillis, // 最小存活时间
@Value("${spring.datasource.druid.validation-query}")
String validationQuery, // 验证查询
@Value("${spring.datasource.druid.test-while-idle}")
boolean testWhileIdle, // 测试空闲连接是否可用
@Value("${spring.datasource.druid.test-on-borrow}")
boolean testOnBorrow, // 测试后返回连接
@Value("${spring.datasource.druid.test-on-return}")
boolean testOnReturn, // 测试后归还
@Value("${spring.datasource.druid.pool-prepared-statements}")
boolean poolPreparedStatements, // 是否缓存PSTMT
@Value("${spring.datasource.druid.max-pool-prepared-statement-per-connection-size}")
int maxPoolPreparedStatementPerConnectionSize, // PSTMT缓存个数
@Autowired Slf4jLogFilter slf4jLogFilter
) {
DruidDataSource dataSource = new DruidDataSource(); // 实例化DataSource子类对象
dataSource.setDriverClassName(driverClassName); // 数据库驱动程序
dataSource.setUrl(url); // 数据库的连接地址
dataSource.setUsername(username); // 数据库用户名
dataSource.setPassword(password); // 数据库密码
dataSource.setInitialSize(initialSize); // 连接池初始化大小
dataSource.setMinIdle(minIdle); // 最小维持的连接数量
dataSource.setMaxActive(maxActive); // 最大的连接数量
dataSource.setMaxWait(maxWait); // 最大等待时间
dataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis); // 检查的间隔时间
dataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis); // 存活时间
dataSource.setValidationQuery(validationQuery); // 验证SQL
dataSource.setTestWhileIdle(testWhileIdle); // 测试连接是否可用
dataSource.setTestOnBorrow(testOnBorrow); // 获取时检测
dataSource.setTestOnReturn(testOnReturn); // 归还时检测
dataSource.setPoolPreparedStatements(poolPreparedStatements); // 是否缓存PSTMT
dataSource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize); // 缓存个数
List<Filter> filterList = new ArrayList<>();
filterList.add(slf4jLogFilter);
dataSource.setProxyFilters(filterList);
return dataSource;
}
/**
* Druid 日志监控配置类
*
* @author nni
* @date 10:24 2021/10/25
*/
@Bean("logFilter")
public Slf4jLogFilter getLogFilter(){
Slf4jLogFilter slf4jLogFilter = new Slf4jLogFilter();
slf4jLogFilter.setDataSourceLogEnabled(true);
slf4jLogFilter.setStatementExecuteAfterLogEnabled(true);
return slf4jLogFilter;
}
}
mybatis-plus的配置类
package com.any.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.core.config.GlobalConfig;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import org.mybatis.spring.boot.autoconfigure.SpringBootVFS;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import javax.sql.DataSource;
/**
* 单数据源,mybatisplus 配置
*
* @author nni
* @date 14:57 2021/10/25
*/
@Configuration
public class MybatisPlusConfig {
private ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
@Bean
public MybatisPlusInterceptor getMybatisPlusInterceptor(){ // 创建分页拦截器
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
mybatisPlusInterceptor.addInnerInterceptor(
new PaginationInnerInterceptor(DbType.MYSQL)
);
return mybatisPlusInterceptor;
}
@Bean("mybatisSqlSessionFactoryBean")
public MybatisSqlSessionFactoryBean getMybatisSqlSessionFactoryBean(
@Autowired DataSource dataSource, // 配置数据源
@Value("${mybatis-plus.config-location}")Resource configLocaltion, // 配置 mybatis.xml 位置
@Value("${mybatis-plus.type-aliases-package}") String typeAliasesPackage, // 配置需要扫描的实体
@Value("${mybatis-plus.mapper-locations}") String mapperLocations, // 配置mapper文件
@Value("${mybatis-plus.global-config.db-config.logic-not-delete-value}") String logicNotDeleteValue,// 配置逻辑删除前
@Value("${mybatis-plus.global-config.db-config.logic-delete-value}") String logicDeleteValue // 配置逻辑删除后
) throws Exception {
MybatisSqlSessionFactoryBean factoryBean = new MybatisSqlSessionFactoryBean();
factoryBean.setDataSource(dataSource);// 配置数据源
factoryBean.setVfs(SpringBootVFS.class); //配置程序的扫描类
factoryBean.setConfigLocation(configLocaltion);
factoryBean.setTypeAliasesPackage(typeAliasesPackage);// 配置需要扫描的实体
Resource[] mappings = this.resourcePatternResolver.getResources(mapperLocations);
factoryBean.setMapperLocations(mappings);
GlobalConfig.DbConfig dbConfig = new GlobalConfig.DbConfig();
dbConfig.setLogicNotDeleteValue(logicNotDeleteValue);// 配置逻辑删除前
dbConfig.setLogicDeleteField(logicDeleteValue);// 配置逻辑删除后
GlobalConfig globalConfig = new GlobalConfig();
globalConfig.setDbConfig(dbConfig); // 注入 dbConfig
factoryBean.setGlobalConfig(globalConfig); // 注入 globalConfig
return factoryBean;
}
}
事务的配置
package com.any.config;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionManager;
import org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource;
import org.springframework.transaction.interceptor.RuleBasedTransactionAttribute;
import org.springframework.transaction.interceptor.TransactionAttribute;
import org.springframework.transaction.interceptor.TransactionInterceptor;
import java.util.HashMap;
import java.util.Map;
/**
* 事务处理类
* @return
* @throws
* @update 2021-11-01 10:42 by 15821
*/
@Configuration
public class TransactionConfig { // 事务配置类
private static final int TRANSACTION_METHOD_TIMEOUT = 5; // 事务处理的超时时间
private static final String AOP_POINTCUT_EXPRESSION = "execution (* com.any..service.*.*(..))";
@Autowired
private TransactionManager transactionManager; // 事务管理器
@Bean("txAdvice")
public TransactionInterceptor transactionInterceptorConfig() {
// 配置数据读取事务规则
RuleBasedTransactionAttribute readOnlyAttribute = new RuleBasedTransactionAttribute();
readOnlyAttribute.setReadOnly(true); // 只读事务
readOnlyAttribute.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED); // 非事务运行
// 配置了数据更新事务规则
RuleBasedTransactionAttribute requiredAttribute = new RuleBasedTransactionAttribute();
requiredAttribute.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); // 事务开启
requiredAttribute.setTimeout(TRANSACTION_METHOD_TIMEOUT); // 事务处理超时时间
// 配置所有要进行事务处理的方法名称定义
Map<String, TransactionAttribute> transactionAttributeMap = new HashMap<>();
transactionAttributeMap.put("add*", requiredAttribute);
transactionAttributeMap.put("edit*", requiredAttribute);
transactionAttributeMap.put("delete*", requiredAttribute);
transactionAttributeMap.put("list*", readOnlyAttribute);
transactionAttributeMap.put("get*", readOnlyAttribute);
NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource();
source.setNameMap(transactionAttributeMap); // 配置方法名称的映射
TransactionInterceptor interceptor = new TransactionInterceptor(transactionManager, source);
return interceptor;
}
@Bean("txAdvisor")
public Advisor transactionAdvisor(
@Autowired @Qualifier("txAdvice") TransactionInterceptor interceptor
) {
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression(AOP_POINTCUT_EXPRESSION);
return new DefaultPointcutAdvisor(pointcut, interceptor);
}
}
Activiti的配置
package com.any.config;
import com.alibaba.druid.pool.DruidDataSource;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.spring.ProcessEngineFactoryBean;
import org.activiti.spring.SpringProcessEngineConfiguration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.transaction.PlatformTransactionManager;
import java.io.IOException;
/**
* ActivitiConfiguration
*
* @author 15821
*/
@Configuration
public class ActivitiConfiguration {
@Autowired
@Qualifier("defaultDruidDataSource")
private DruidDataSource druidDataSource;
@Autowired
private PlatformTransactionManager platformTransactionManager;
/**
* 注册 activiti的配置信息
*/
@Bean("processEngineConfiguration")
public SpringProcessEngineConfiguration getProcessEngineConfiguration(){
SpringProcessEngineConfiguration configuration
= new SpringProcessEngineConfiguration();
configuration.setDataSource(druidDataSource); // 添加数据源
configuration.setTransactionManager(platformTransactionManager); // 添加事务
configuration.setDatabaseSchemaUpdate("true"); // 如果有表则不创建
configuration.setDbHistoryUsed(true); // 允许查看历史信息
// 自动部署 bpmn文件
Resource[] resources = null;
try {
resources= new PathMatchingResourcePatternResolver().getResources("classpath*:bpmn/*.bpmn");
} catch (IOException e) {
e.printStackTrace();
}
configuration.setDeploymentResources(resources);
return configuration;
}
/**
* 注册 ProcessEngineFactoryBean
*/
@Bean
public ProcessEngineFactoryBean processEngine(){
ProcessEngineFactoryBean factoryBean = new ProcessEngineFactoryBean();
factoryBean.setProcessEngineConfiguration(getProcessEngineConfiguration());
return factoryBean;
}
/**
* 注册 RepositoryService
*/
@Bean
public RepositoryService repositoryService() throws Exception{
return processEngine().getObject().getRepositoryService();
}
/**
* 注册 RuntimeService
*/
@Bean
public RuntimeService runtimeService() throws Exception{
return processEngine().getObject().getRuntimeService();
}
/**
* 注册 TaskService
*/
@Bean
public TaskService taskService() throws Exception{
return processEngine().getObject().getTaskService();
}
/**
* 注册 HistoryService
*/
@Bean
public HistoryService historyService() throws Exception{
return processEngine().getObject().getHistoryService();
}
}
测试
开始流程
@Autowired
private RuntimeService runtimeService;
/**
* 测试启动流程
*
* @update 2021-12-11 17:17 by 15821
*/
@RequestMapping("startProcess")
public ServerResponse testStartProcess() {
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(key);
return ServerResponse.createBySuccess(processInstance.getId());
}
查看个人任务
/**
* 查看个人任务
*
* @update 2021-12-11 17:17 by 15821
*/
@RequestMapping("queryTask")
public ServerResponse testQueryPersonalTask(String assigness) {
// 流程实例 的KEY
System.out.println(assigness);
Task task = taskService.createTaskQuery()
.processDefinitionKey(key)
.taskAssignee(assigness)
.singleResult();
return ServerResponse.createBySuccess(
Map.of("流程实例id", task.getProcessInstanceId()
, "任务id", task.getId()
, "任务负责人", task.getAssignee()
)
);
}
查看组任务
/**
* 查看组任务
*
* @update 2021-12-11 17:17 by 15821
*/
@RequestMapping("queryGroupTask")
public ServerResponse testQueryGroupTask(String candidateUser) {
Task task = taskService.createTaskQuery()
.processDefinitionKey(key)
.taskCandidateUser(candidateUser)
.singleResult();
System.out.println("流程实例的ID:"+task.getProcessInstanceId());
System.out.println("任务ID:"+task.getId());
System.out.println("任务负责人:"+task.getAssignee());
return ServerResponse.createBySuccess(
Map.of("流程实例的ID",task.getProcessInstanceId()
,"任务Id",task.getId()));
}
拾取任务
/**
* 拾取任务
*
* @update 2021-12-11 17:17 by 15821
*/
@RequestMapping("chaim")
public ServerResponse testClaimTask(String taskId, String candidateUser) {
taskService.claim(taskId,candidateUser);
return ServerResponse.createBySuccess("taskId : " + taskId + "、用户:'" + candidateUser + "'拾取任务成功");
}
完成任务
/**
* 完成任务
*
* @update 2021-12-11 17:17 by 15821
*/
@RequestMapping("complete")
public ServerResponse testComplete(String assigness) {
List<Task> tasks = taskService.createTaskQuery()
.processDefinitionKey("evectionGroup")
.taskAssignee(assigness)
.list();
for (Task task : tasks){
taskService.complete(task.getId());
}
return ServerResponse.createBySuccess("、用户:'" + assigness + "'完成任务");
}