Commit e97e352e authored by 赵啸非's avatar 赵啸非

一件事统一办

parent 5b62206d

Too many changes to show.

To preserve performance only 1000 of 1000+ files are displayed.

This diff is collapsed.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>government-flowable</artifactId>
<packaging>jar</packaging>
<description>工作流程引擎服务</description>
<parent>
<groupId>com.mortals.xhx</groupId>
<artifactId>government-platform</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring.cloud.alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>com.mortals.xhx</groupId>
<artifactId>common-lib</artifactId>
</dependency>
<!-- 引入 SpringMVC 相关依赖,并实现对其的自动配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-spring-boot-starter-basic</artifactId>
</dependency>
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-engine</artifactId>
<version>${flowable.version}</version>
</dependency>
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-ui-modeler-rest</artifactId>
<version>${flowable.version}</version>
</dependency>
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-ui-modeler-logic</artifactId>
<version>${flowable.version}</version>
</dependency>
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-ui-modeler-conf</artifactId>
<version>${flowable.version}</version>
<exclusions>
<exclusion>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- &lt;!&ndash;flowable工作流依赖&ndash;&gt;
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-spring-boot-starter</artifactId>
<version>${flowable.version}</version>
</dependency>
&lt;!&ndash; flowable-engine &ndash;&gt;
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-engine</artifactId>
<version>${flowable.version}</version>
</dependency>
&lt;!&ndash; flowable 集成依赖 rest,logic,conf &ndash;&gt;
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-ui-modeler-rest</artifactId>
<version>${flowable.version}</version>
</dependency>
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-ui-modeler-logic</artifactId>
<version>${flowable.version}</version>
</dependency>
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-ui-modeler-conf</artifactId>
<version>${flowable.version}</version>
<exclusions>
<exclusion>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
</exclusion>
</exclusions>
</dependency>-->
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
<version>4.3.1</version>
</dependency>
<dependency>
<groupId>org.eweb4j</groupId>
<artifactId>fel</artifactId>
<version>0.8</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>false</filtering>
<includes>
<include>*</include>
<include>*/**</include>
</includes>
</resource>
</resources>
</build>
</project>
#!/bin/sh
RETVAL=$?
. /etc/profile #加载环境变量(Jenkins远程启动程序报找不到Java文件问题,需加载环境变量)
export CATALINA_BASE="$PWD"
case "$1" in
start)
if [ -f $CATALINA_BASE/start.sh ];then
$CATALINA_BASE/start.sh 17022 &
fi
;;
stop)
if [ -f $CATALINA_BASE/stop.sh ];then
$CATALINA_BASE/stop.sh 17022
fi
;;
*)
echo $"Usage: $0 {start|stop}"
exit 1
;;
esac
exit $RETVAL
\ No newline at end of file
#!/bin/sh
PORT=$1
BASEDIR=`dirname $0`/..
BASEDIR=`(cd "$BASEDIR"; pwd)`
PROJECT_NAME="@project.artifactId@";
MAIN_CLASS="$PROJECT_NAME-@project.version@.jar";
ENCRYPT_KEY="foobar";
LOG_PATH="@profiles.log.path@/$PROJECT_NAME"
GC_PATH=$LOG_PATH/$PORT"-gc.log"
HS_ERR_PATH=$LOG_PATH/$PORT"-hs_err.log"
HEAP_DUMP_PATH=$LOG_PATH/$PORT"-heap_dump.hprof"
TEMP_PATH=$LOG_PATH/temp/
SUCCESS=0
FAIL=9
if [ ! -n "$PORT" ]; then
echo $"Usage: $0 {port}"
exit $FAIL
fi
if [ ! -d $LOG_PATH ];
then
mkdir -p $LOG_PATH;
fi
if [ ! -d $TEMP_PATH ];
then
mkdir -p $TEMP_PATH;
fi
if [ -z "$JAVACMD" ] ; then
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
else
JAVACMD=`which java > /dev/null 2>&1`
echo "Error: JAVA_HOME is not defined correctly."
exit $ERR_NO_JAVA
fi
fi
if [ ! -x "$JAVACMD" ] ; then
echo "We cannot execute $JAVACMD"
exit $ERR_NO_JAVA
fi
if [ -e "$BASEDIR" ]
then
JAVA_OPTS="-Xms512M -Xmx1024M -Xss256K -XX:+UseAdaptiveSizePolicy -XX:+UseParallelGC -XX:+UseParallelOldGC -XX:GCTimeRatio=39 -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:$GC_PATH -XX:+HeapDumpOnOutOfMemoryError -XX:ErrorFile=$HS_ERR_PATH -XX:HeapDumpPath=$HEAP_DUMP_PATH"
fi
CLASSPATH=$CLASSPATH_PREFIX:
EXTRA_JVM_ARGUMENTS=""
cd "$BASEDIR/boot";
echo "starting application $PROJECT_NAME......"
exec "$JAVACMD" $JAVA_OPTS \
$EXTRA_JVM_ARGUMENTS \
-Dapp.name="$PROJECT_NAME" \
-Dapp.port="$PORT" \
-Dbasedir="$BASEDIR" \
-Djava.io.tmpdir=$TEMP_PATH \
-Dloader.path="file://$BASEDIR/conf,file://$BASEDIR/lib" \
-jar $MAIN_CLASS \
--server.port="$PORT" \
--encrypt.key="$ENCRYPT_KEY" \
> /dev/null &
for i in {1..60}
do
jcpid=`ps -ef | grep -v "grep" | grep "$MAIN_CLASS" | grep "app.port=$PORT" | sed -n '1P' | awk '{print $2}'`
if [ $jcpid ]; then
echo "The $PROJECT_NAME start finished, PID is $jcpid"
exit $SUCCESS
else
echo "starting the application .. $i"
sleep 1
fi
done
echo "$PROJECT_NAME start failure!"
\ No newline at end of file
#! /bin/sh
PORT=$1
BASEDIR=`dirname $0`
BASEDIR=`(cd "$BASEDIR"; pwd)`
PROJECT_NAME="@project.artifactId@"
MAIN_CLASS="$PROJECT_NAME";
SECURITY_USERNAME="admin";
SECURITY_PASSWORD="1";
if [ ! -n "$PORT" ]; then
echo $"Usage: $0 {port}"
exit $FAIL
fi
echo "stoping application $PROJECT_NAME......"
jcpid=`ps -ef | grep -v "grep" | grep "$MAIN_CLASS" | grep "app.port=$PORT" | sed -n '1P' | awk '{print $2}'`
if [ -z $jcpid ]; then
echo "$PROJECT_NAME is not started or has been stopped!"
else
curl -X POST -i -u $SECURITY_USERNAME:$SECURITY_PASSWORD http://127.0.0.1:$PORT/xxx_manager/shutdown
for i in {1..60}
do
jcpid=`ps -ef | grep -v "grep" | grep "$MAIN_CLASS" | grep "app.port=$PORT" | sed -n '1P' | awk '{print $2}'`
if [ -z $jcpid ]; then
echo "$PROJECT_NAME has been stopped!"
break
else
echo "stoping the application .. $i"
sleep 1
fi
done
jcpid=`ps -ef | grep -v "grep" | grep "$MAIN_CLASS" | grep "app.port=$PORT" | sed -n '1P' | awk '{print $2}'`
if [ $jcpid ]; then
[ -z $jcpid ] || kill -15 $jcpid
for i in {1..30}
do
jcpid=`ps -ef | grep -v "grep" | grep "$MAIN_CLASS" | grep "app.port=$PORT" | sed -n '1P' | awk '{print $2}'`
if [ -z $jcpid ]; then
echo "$PROJECT_NAME has been stopped!"
break
else
echo "stoping the application .. $i"
sleep 1
fi
done
fi
jcpid=`ps -ef | grep -v "grep" | grep "$MAIN_CLASS" | grep "app.port=$PORT" | sed -n '1P' | awk '{print $2}'`
if [ $jcpid ]; then
[ -z $jcpid ] || kill -9 $jcpid
[ $? -eq 0 ] && echo "Stop $PROJECT_NAME OK!" || echo "Stop $PROJECT_NAME Fail!"
fi
fi
\ No newline at end of file
package com.mortals.flowable.common.config;
import com.sun.prism.paint.Color;
import org.flowable.bpmn.model.AssociationDirection;
import org.flowable.image.impl.DefaultProcessDiagramCanvas;
import java.awt.*;
import java.awt.geom.Line2D;
import java.awt.geom.RoundRectangle2D;
/**
* 自定义流程图
*
* @author: finegirl
* @date: 2021/7/31 12:06
* @description:
*/
public class MyDefaultProcessDiagramCanvas extends DefaultProcessDiagramCanvas {
//设置高亮线的颜色 这里我设置成绿色
protected static Color HIGHLIGHT_SEQUENCEFLOW_COLOR = Color.GREEN;
public MyDefaultProcessDiagramCanvas(int width, int height, int minX, int minY, String imageType, String activityFontName, String labelFontName, String annotationFontName, ClassLoader customClassLoader) {
super(width, height, minX, minY, imageType, activityFontName, labelFontName, annotationFontName, customClassLoader);
}
public MyDefaultProcessDiagramCanvas(int width, int height, int minX, int minY, String imageType) {
super(width, height, minX, minY, imageType);
}
/**
* 画线颜色设置
*/
@Override
public void drawConnection(int[] xPoints, int[] yPoints, boolean conditional, boolean isDefault, String connectionType,
AssociationDirection associationDirection, boolean highLighted, double scaleFactor) {
Paint originalPaint = g.getPaint();
Stroke originalStroke = g.getStroke();
g.setPaint(CONNECTION_COLOR);
if (connectionType.equals("association")) {
g.setStroke(ASSOCIATION_STROKE);
} else if (highLighted) {
//设置线的颜色
g.setPaint(originalPaint);
g.setStroke(HIGHLIGHT_FLOW_STROKE);
}
for (int i = 1; i < xPoints.length; i++) {
Integer sourceX = xPoints[i - 1];
Integer sourceY = yPoints[i - 1];
Integer targetX = xPoints[i];
Integer targetY = yPoints[i];
Line2D.Double line = new Line2D.Double(sourceX, sourceY, targetX, targetY);
g.draw(line);
}
if (isDefault) {
Line2D.Double line = new Line2D.Double(xPoints[0], yPoints[0], xPoints[1], yPoints[1]);
drawDefaultSequenceFlowIndicator(line, scaleFactor);
}
if (conditional) {
Line2D.Double line = new Line2D.Double(xPoints[0], yPoints[0], xPoints[1], yPoints[1]);
drawConditionalSequenceFlowIndicator(line, scaleFactor);
}
if (associationDirection == AssociationDirection.ONE || associationDirection == AssociationDirection.BOTH) {
Line2D.Double line = new Line2D.Double(xPoints[xPoints.length - 2], yPoints[xPoints.length - 2], xPoints[xPoints.length - 1], yPoints[xPoints.length - 1]);
drawArrowHead(line, scaleFactor);
}
if (associationDirection == AssociationDirection.BOTH) {
Line2D.Double line = new Line2D.Double(xPoints[1], yPoints[1], xPoints[0], yPoints[0]);
drawArrowHead(line, scaleFactor);
}
g.setPaint(originalPaint);
g.setStroke(originalStroke);
}
/**
* 高亮节点设置
*/
@Override
public void drawHighLight(int x, int y, int width, int height) {
Paint originalPaint = g.getPaint();
Stroke originalStroke = g.getStroke();
//设置高亮节点的颜色
g.setPaint(HIGHLIGHT_COLOR);
g.setStroke(THICK_TASK_BORDER_STROKE);
RoundRectangle2D rect = new RoundRectangle2D.Double(x, y, width, height, 20, 20);
g.draw(rect);
g.setPaint(originalPaint);
g.setStroke(originalStroke);
}
}
package com.mortals.flowable.common.constant;
/**
* 流程常量信息
*
* @author: finegirl
* @date: 2021/7/31 12:04
* @description:
*/
public class ProcessConstants {
/**
* 动态数据
*/
public static final String DATA_TYPE = "dynamic";
/**
* 单个审批人
*/
public static final String USER_TYPE_ASSIGNEE = "assignee";
/**
* 候选人
*/
public static final String USER_TYPE_USERS = "candidateUsers";
/**
* 审批组
*/
public static final String USER_TYPE_ROUPS = "candidateGroups";
/**
* 单个审批人
*/
public static final String PROCESS_APPROVAL = "approval";
/**
* 会签人员
*/
public static final String PROCESS_MULTI_INSTANCE_USER = "userList";
/**
* nameapace
*/
public static final String NAMASPASE = "http://flowable.org/bpmn";
/**
* 会签节点
*/
public static final String PROCESS_MULTI_INSTANCE = "multiInstance";
/**
* 自定义属性 dataType
*/
public static final String PROCESS_CUSTOM_DATA_TYPE = "dataType";
/**
* 自定义属性 userType
*/
public static final String PROCESS_CUSTOM_USER_TYPE = "userType";
/**
* 初始化人员
*/
public static final String PROCESS_INITIATOR = "INITIATOR";
/**
* 流程跳过
*/
public static final String FLOWABLE_SKIP_EXPRESSION_ENABLED = "_FLOWABLE_SKIP_EXPRESSION_ENABLED";
}
package com.mortals.flowable.common.enums;
/**
* 流程意见类型
*
* @author: finegirl
* @date: 2021/7/31 12:05
* @description:
*/
public enum FlowComment {
/**
* 说明
*/
NORMAL("1", "正常意见"),
REBACK("2", "退回意见"),
REJECT("3", "驳回意见"),
DELEGATE("4", "委派意见"),
ASSIGN("5", "转办意见"),
STOP("6", "终止流程");
/**
* 类型
*/
private final String type;
/**
* 说明
*/
private final String remark;
FlowComment(String type, String remark) {
this.type = type;
this.remark = remark;
}
public String getType() {
return type;
}
public String getRemark() {
return remark;
}
}
package com.mortals.flowable.factory;
import lombok.Getter;
import org.flowable.engine.*;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* flowable 引擎注入封装
*
* @author: finegirl
* @date: 2021/7/31 12:20
*/
@Component
@Getter
public class FlowServiceFactory {
@Resource
protected RepositoryService repositoryService;
@Resource
protected RuntimeService runtimeService;
@Resource
protected IdentityService identityService;
@Resource
protected TaskService taskService;
@Resource
protected FormService formService;
@Resource
protected HistoryService historyService;
@Resource
protected ManagementService managementService;
@Qualifier("processEngine")
@Resource
protected ProcessEngine processEngine;
}
package com.mortals.flowable.flow;
import com.greenpineyu.fel.FelEngine;
import com.greenpineyu.fel.FelEngineImpl;
import com.greenpineyu.fel.context.FelContext;
import org.flowable.bpmn.model.Process;
import org.flowable.bpmn.model.*;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.repository.ProcessDefinition;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
public class FindNextNodeUtil {
/**
* 获取下一步骤的用户任务
*
* @param repositoryService
* @param map
* @return
*/
public static List<UserTask> getNextUserTasks(RepositoryService repositoryService, org.flowable.task.api.Task task, Map<String, Object> map) {
List<UserTask> data = new ArrayList<>();
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult();
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId());
Process mainProcess = bpmnModel.getMainProcess();
Collection<FlowElement> flowElements = mainProcess.getFlowElements();
String key = task.getTaskDefinitionKey();
FlowElement flowElement = bpmnModel.getFlowElement(key);
next(flowElements, flowElement, map, data);
return data;
}
public static void next(Collection<FlowElement> flowElements, FlowElement flowElement, Map<String, Object> map, List<UserTask> nextUser) {
//如果是结束节点
if (flowElement instanceof EndEvent) {
//如果是子任务的结束节点
if (getSubProcess(flowElements, flowElement) != null) {
flowElement = getSubProcess(flowElements, flowElement);
}
}
//获取Task的出线信息--可以拥有多个
List<SequenceFlow> outGoingFlows = null;
if (flowElement instanceof Task) {
outGoingFlows = ((Task) flowElement).getOutgoingFlows();
} else if (flowElement instanceof Gateway) {
outGoingFlows = ((Gateway) flowElement).getOutgoingFlows();
} else if (flowElement instanceof StartEvent) {
outGoingFlows = ((StartEvent) flowElement).getOutgoingFlows();
} else if (flowElement instanceof SubProcess) {
outGoingFlows = ((SubProcess) flowElement).getOutgoingFlows();
} else if (flowElement instanceof CallActivity) {
outGoingFlows = ((CallActivity) flowElement).getOutgoingFlows();
}
if (outGoingFlows != null && outGoingFlows.size() > 0) {
//遍历所有的出线--找到可以正确执行的那一条
for (SequenceFlow sequenceFlow : outGoingFlows) {
//1.有表达式,且为true
//2.无表达式
String expression = sequenceFlow.getConditionExpression();
if (expression == null ||
Boolean.parseBoolean(
String.valueOf(
result(map, expression.substring(expression.lastIndexOf("{") + 1, expression.lastIndexOf("}")))))) {
//出线的下一节点
String nextFlowElementID = sequenceFlow.getTargetRef();
if (checkSubProcess(nextFlowElementID, flowElements, nextUser)) {
continue;
}
//查询下一节点的信息
FlowElement nextFlowElement = getFlowElementById(nextFlowElementID, flowElements);
//调用流程
if (nextFlowElement instanceof CallActivity) {
CallActivity ca = (CallActivity) nextFlowElement;
if (ca.getLoopCharacteristics() != null) {
UserTask userTask = new UserTask();
userTask.setId(ca.getId());
userTask.setId(ca.getId());
userTask.setLoopCharacteristics(ca.getLoopCharacteristics());
userTask.setName(ca.getName());
nextUser.add(userTask);
}
next(flowElements, nextFlowElement, map, nextUser);
}
//用户任务
if (nextFlowElement instanceof UserTask) {
nextUser.add((UserTask) nextFlowElement);
}
//排他网关
else if (nextFlowElement instanceof ExclusiveGateway) {
next(flowElements, nextFlowElement, map, nextUser);
}
//并行网关
else if (nextFlowElement instanceof ParallelGateway) {
next(flowElements, nextFlowElement, map, nextUser);
}
//接收任务
else if (nextFlowElement instanceof ReceiveTask) {
next(flowElements, nextFlowElement, map, nextUser);
}
//服务任务
else if (nextFlowElement instanceof ServiceTask) {
next(flowElements, nextFlowElement, map, nextUser);
}
//子任务的起点
else if (nextFlowElement instanceof StartEvent) {
next(flowElements, nextFlowElement, map, nextUser);
}
//结束节点
else if (nextFlowElement instanceof EndEvent) {
next(flowElements, nextFlowElement, map, nextUser);
}
}
}
}
}
/**
* 判断是否是多实例子流程并且需要设置集合类型变量
*/
public static boolean checkSubProcess(String Id, Collection<FlowElement> flowElements, List<UserTask> nextUser) {
for (FlowElement flowElement1 : flowElements) {
if (flowElement1 instanceof SubProcess && flowElement1.getId().equals(Id)) {
SubProcess sp = (SubProcess) flowElement1;
if (sp.getLoopCharacteristics() != null) {
String inputDataItem = sp.getLoopCharacteristics().getInputDataItem();
UserTask userTask = new UserTask();
userTask.setId(sp.getId());
userTask.setLoopCharacteristics(sp.getLoopCharacteristics());
userTask.setName(sp.getName());
nextUser.add(userTask);
return true;
}
}
}
return false;
}
/**
* 查询一个节点的是否子任务中的节点,如果是,返回子任务
*
* @param flowElements 全流程的节点集合
* @param flowElement 当前节点
* @return
*/
public static FlowElement getSubProcess(Collection<FlowElement> flowElements, FlowElement flowElement) {
for (FlowElement flowElement1 : flowElements) {
if (flowElement1 instanceof SubProcess) {
for (FlowElement flowElement2 : ((SubProcess) flowElement1).getFlowElements()) {
if (flowElement.equals(flowElement2)) {
return flowElement1;
}
}
}
}
return null;
}
/**
* 根据ID查询流程节点对象, 如果是子任务,则返回子任务的开始节点
*
* @param Id 节点ID
* @param flowElements 流程节点集合
* @return
*/
public static FlowElement getFlowElementById(String Id, Collection<FlowElement> flowElements) {
for (FlowElement flowElement : flowElements) {
if (flowElement.getId().equals(Id)) {
//如果是子任务,则查询出子任务的开始节点
if (flowElement instanceof SubProcess) {
return getStartFlowElement(((SubProcess) flowElement).getFlowElements());
}
return flowElement;
}
if (flowElement instanceof SubProcess) {
FlowElement flowElement1 = getFlowElementById(Id, ((SubProcess) flowElement).getFlowElements());
if (flowElement1 != null) {
return flowElement1;
}
}
}
return null;
}
/**
* 返回流程的开始节点
*
* @param flowElements 节点集合
* @description:
*/
public static FlowElement getStartFlowElement(Collection<FlowElement> flowElements) {
for (FlowElement flowElement : flowElements) {
if (flowElement instanceof StartEvent) {
return flowElement;
}
}
return null;
}
/**
* 校验el表达示例
*
* @param map
* @param expression
* @return
*/
public static Object result(Map<String, Object> map, String expression) {
FelEngine fel = new FelEngineImpl();
FelContext ctx = fel.getContext();
for (Map.Entry<String, Object> entry : map.entrySet()) {
ctx.set(entry.getKey(), entry.getValue());
}
Object result = fel.eval(expression);
return result;
}
}
package com.mortals.flowable.flow;
import org.flowable.spring.SpringProcessEngineConfiguration;
import org.flowable.spring.boot.EngineConfigurationConfigurer;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FlowableConfig implements EngineConfigurationConfigurer<SpringProcessEngineConfiguration> {
@Override
public void configure(SpringProcessEngineConfiguration engineConfiguration) {
engineConfiguration.setActivityFontName("宋体");
engineConfiguration.setLabelFontName("宋体");
engineConfiguration.setAnnotationFontName("宋体");
}
}
package com.mortals.flowable.listener;
import org.flowable.engine.delegate.TaskListener;
import org.flowable.task.service.delegate.DelegateTask;
/**
*
*
* @author: finegirl
* @date: 2021/7/31 12:19
*/
public class UserTaskListener implements TaskListener{
@Override
public void notify(DelegateTask delegateTask) {
}
}
package com.mortals.xhx;
import com.mortals.framework.springcloud.boot.BaseWebApplication;
import com.mortals.xhx.exception.GlobalExceptionHandler;
import com.mortals.xhx.flowable.conf.AppDispatcherServletConfiguration;
import com.mortals.xhx.flowable.conf.ApplicationConfiguration;
import org.apache.commons.configuration.DatabaseConfiguration;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
import org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.ImportResource;
@Import(value={GlobalExceptionHandler.class,
// 引入修改的配置
ApplicationConfiguration.class,
AppDispatcherServletConfiguration.class,
// 引入 DatabaseConfiguration 表更新转换
DatabaseConfiguration.class
// 引入 DatabaseConfiguration 表更新转换
//DatabaseAutoConfiguration.class
})
@EnableFeignClients
@ComponentScan(basePackages = {"com.mortals.*"})
@MapperScan("com.mortals.*.dao")
@SpringBootApplication(exclude={SecurityAutoConfiguration.class, ManagementWebSecurityAutoConfiguration.class, SecurityFilterAutoConfiguration.class})
@ImportResource(locations = { "classpath:config/spring-config.xml" })
public class FlowableApplication extends BaseWebApplication {
public static void main(String[] args) {
SpringApplication.run(FlowableApplication.class, args);
}
}
package com.mortals.xhx.base.framework.config;
import java.io.IOException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
import java.util.stream.Collectors;
import javax.sql.DataSource;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ibatis.io.VFS;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
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.ResourceLoader;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import com.mortals.framework.springcloud.config.SpringBootVFS;
import org.springframework.core.io.support.ResourcePatternUtils;
//@Configuration
public class MybatisConfiguration {
private static Log logger = LogFactory.getLog(MybatisConfiguration.class);
// 配置类型别名
@Value("${spring.application.name}")
private String name;
// 配置类型别名
@Value("${mybatis.root-path}")
private String rootPath;
private static final String ROOT_PATH_SPLIT = ",";
// 配置类型别名
@Value("${mybatis.type-aliases-package}")
private String typeAliasesPackage;
// 配置mapper的扫描,找到所有的mapper.xml映射文件
@Value("${mybatis.mapper-locations}")
private String mapperLocations;
// 加载全局的配置文件
@Value("${mybatis.config-location}")
private String configLocation;
private final String PATH_SEPARATOR = "/";
@Autowired
protected ResourceLoader resourceLoader;
// 提供SqlSeesion
@Bean(name = "sqlSessionFactory")
public SqlSessionFactory sqlSessionFactoryBean(@Qualifier("dataSource") DataSource dataSource) {
return getSqlSessionFactoryBean(dataSource);
}
public SqlSessionFactory getSqlSessionFactoryBean(DataSource dataSource) {
try {
// 解决myBatis下 不能从嵌套jar文件中读取class的问题
VFS.addImplClass(SpringBootVFS.class);
SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
sessionFactoryBean.setDataSource(dataSource);
// 读取配置
sessionFactoryBean.setTypeAliasesPackage(getTypeAliasesPackage());
//
// Resource[] resources = new PathMatchingResourcePatternResolver().getResources(mapperLocations);
// sessionFactoryBean.setMapperLocations(resources);
// //
Resource[] configLocations = new PathMatchingResourcePatternResolver().getResources(configLocation);
sessionFactoryBean.setConfigLocation(configLocations[0]);
Properties properties = new Properties();
properties.put("prefix", "");
properties.put("blobType", "BLOB");
properties.put("boolValue", "TRUE");
sessionFactoryBean.setConfigurationProperties(properties);
sessionFactoryBean.setMapperLocations(resolveMapperLocations());
//sessionFactoryBean.setMapperLocations(ResourcePatternUtils.getResourcePatternResolver(this.resourceLoader).getResources("classpath:/META-INF/modeler-mybatis-mappings/*.xml"));
//sessionFactoryBean.setMapperLocations(ResourcePatternUtils.getResourcePatternResolver(this.resourceLoader).getResources("classpath*:mapper/*.xml"));
//sessionFactoryBean.afterPropertiesSet();
//sessionFactoryBean.afterPropertiesSet();
// 添加插件 (改为使用配置文件加载了)
// sqlSessionFactoryBean.setPlugins(new
// Interceptor[]{pageHelper()});
return sessionFactoryBean.getObject();
} catch (IOException e) {
logger.error("mybatis resolver mapper*xml is error", e);
return null;
} catch (Exception e) {
logger.error("mybatis sqlSessionFactoryBean create error", e);
return null;
}
}
public Resource[] resolveMapperLocations() {
ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver();
List<String> mapperLocations = Arrays.stream(this.mapperLocations.split(",")).collect(Collectors.toList());
List<Resource> resources = new ArrayList();
if (mapperLocations != null) {
for (String mapperLocation : mapperLocations) {
try {
Resource[] mappers =ResourcePatternUtils.getResourcePatternResolver(this.resourceLoader).getResources(mapperLocation.trim());
//Resource[] mappers = resourceResolver.getResources(mapperLocation);
resources.addAll(Arrays.asList(mappers));
} catch (IOException e) {
// ignore
}
}
}
return resources.toArray(new Resource[resources.size()]);
}
public String getTypeAliasesPackage() {
if (StringUtils.isEmpty(typeAliasesPackage)) {
return "";
}
rootPath = rootPath.trim().replace(".", PATH_SEPARATOR);
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
StringBuffer typeAliasesPackageStringBuffer = new StringBuffer();
try {
for (String location : typeAliasesPackage.split(ROOT_PATH_SPLIT)) {
if (StringUtils.isEmpty(location)) {
continue;
}
if (location.contains("*")) {
location = "classpath*:" + location.trim().replace(".", PATH_SEPARATOR);
location = getResources(resolver, location);
}
if (location.endsWith(PATH_SEPARATOR)) {
location = location.substring(0, location.length() - 1);
}
typeAliasesPackageStringBuffer.append(location + ROOT_PATH_SPLIT);
}
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
if (typeAliasesPackageStringBuffer.length() == 0) {
throw new RuntimeException(
"mybatis typeAliasesPackage 路径扫描错误!请检查applicationContext.xml@sqlSessionFactory配置!");
}
String allTypeAliasesPackage = typeAliasesPackageStringBuffer.toString().replace(PATH_SEPARATOR, ".");
logger.info("allTypeAliasesPackage:" + allTypeAliasesPackage);
return allTypeAliasesPackage;
}
private String getResources(ResourcePatternResolver resolver, String location) throws IOException {
StringBuffer resourcePathStringBuffer = new StringBuffer();
for (Resource resource : resolver.getResources(location)) {
if (resource == null || resource.getURL() == null) {
continue;
}
String path = resource == null ? "" : resource.getURL().getPath();
path = URLDecoder.decode(path, "UTF-8");// 对URL进行解码
path = path.replaceAll("\\\\", PATH_SEPARATOR);// 将所有反斜杠(\)替换成正斜杠(/)
if (StringUtils.isEmpty(path) || path.indexOf(rootPath) == -1) {
continue;
}
if (path.endsWith(PATH_SEPARATOR)) {
path = path.substring(0, path.length() - 1);
}
resourcePathStringBuffer.append(path.substring(path.indexOf(rootPath))).append(ROOT_PATH_SPLIT);
}
return resourcePathStringBuffer.toString();
}
}
\ No newline at end of file
package com.mortals.xhx.base.framework.exception;
import com.mortals.framework.exception.AppException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import com.alibaba.fastjson.JSONObject;
/**
* 统一异常处理
*/
@ControllerAdvice
public class ExceptionHandle {
private final static Logger log = LoggerFactory.getLogger(ExceptionHandle.class);
public static final String KEY_RESULT_CODE = "code";
public static final String KEY_RESULT_MSG = "msg";
public static final String KEY_RESULT_DATA = "data";
public static final int VALUE_RESULT_FAILURE = -1;
@ExceptionHandler(value = Exception.class)
@ResponseBody
public String handle(Exception e) {
JSONObject ret = new JSONObject();
ret.put(KEY_RESULT_CODE, VALUE_RESULT_FAILURE);
if (e instanceof AppException) {
StackTraceElement stack = e.getStackTrace()[0];
log.error("[business error]=========stack message[{}],[{},method:{},line{}][{}]", e.getMessage(),
stack.getClassName(), stack.getMethodName(), stack.getLineNumber(), e.getClass().getName());
AppException ex = (AppException) e;
ret.put(KEY_RESULT_MSG, ex.getMessage());
} else {
log.error("[system error]{}", e);
ret.put(KEY_RESULT_MSG, "unknown exception!");
}
return ret.toJSONString();
}
}
package com.mortals.xhx.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.CacheManager;
import org.springframework.cache.support.CompositeCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.DependsOn;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheManager;
@DependsOn({"redisCacheManager", "ehcacheCacheManager"})
public class CacheConfig {
@Autowired
private RedisCacheManager redisCacheManager;
@Bean("cacheManager")
@Primary
public CacheManager compositeCacheManager() {
CompositeCacheManager compositeCacheManager = new CompositeCacheManager(redisCacheManager);
return compositeCacheManager;
}
}
package com.mortals.xhx.config;
import com.mortals.xhx.interceptor.CorsInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CorssDomainConfig implements WebMvcConfigurer {
@Autowired
private CorsInterceptor corsInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
InterceptorRegistration registration = registry.addInterceptor(corsInterceptor);
registration.addPathPatterns("/**");
}
}
//package com.mortals.xhx.config;
//
//import com.alibaba.druid.filter.config.ConfigTools;
//import com.alibaba.druid.pool.DruidDataSource;
//import lombok.Data;
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//import org.springframework.beans.factory.annotation.Value;
//import org.springframework.boot.context.properties.ConfigurationProperties;
//import org.springframework.context.annotation.Bean;
//import org.springframework.context.annotation.Configuration;
//import org.springframework.context.annotation.Primary;
//
//import javax.sql.DataSource;
//import java.sql.SQLException;
//import java.util.Properties;
//
//
//@Configuration
//@Data
//public class DruidDatsSourceConfig {
//
// private Logger logger = LoggerFactory.getLogger(DruidDatsSourceConfig.class);
//
// @Value("${spring.datasource.url}")
// private String url;
//
// @Value("${spring.datasource.driver-class-name}")
// private String driverClassName;
//
// @Value("${spring.datasource.username}")
// private String username;
//
// @Value("${spring.datasource.password}")
// private String password;
//
// @Value("${spring.datasource.type}")
// private String type;
//
//// @Value("${spring.datasource.publicKey}")
//// private String publicKey;
//
// @Value("${spring.datasource.druid.initial-size}")
// private Integer initialSize;
//
// @Value("${spring.datasource.druid.min-idle}")
// private Integer minIdle;
//
// @Value("${spring.datasource.druid.max-active}")
// private Integer maxActive;
//
// @Value("${spring.datasource.druid.max-wait}")
// private Integer maxWait;
//
// @Value("${spring.datasource.druid.time-between-eviction-runs-millis}")
// private Integer timeBetweenEvictionRunsMillis;
//
// @Value("${spring.datasource.druid.min-evictable-idle-time-millis}")
// private Integer minEvictableIdleTimeMillis;
//
// @Value("${spring.datasource.druid.validation-query}")
// private String validationQuery;
//
// @Value("${spring.datasource.druid.test-while-idle}")
// private Boolean testWhileIdle;
//
// @Value("${spring.datasource.druid.test-on-borrow}")
// private Boolean testOnBorrow;
//
// @Value("${spring.datasource.druid.test-on-return}")
// private Boolean testOnReturn;
//
// @Value("${spring.datasource.druid.pool-prepared-statements}")
// private Boolean poolPreparedStatements;
//
// @Value("${spring.datasource.druid.max-pool-prepared-statement-per-connection-size}")
// private Integer maxPoolPreparedStatementPerConnectionSize;
//
// @Value("${spring.datasource.druid.filters}")
// private String filters;
//
// @Value("${spring.datasource.druid.use-global-data-source-stat}")
// private Boolean useGlobalDataSourceStat;
//
// @Value("${spring.datasource.druid.connect-properties}")
// private Properties connectProperties;
//
// @Bean
// @Primary
// public DataSource druidDataSource() throws Exception {
// DruidDataSource datasource = new DruidDataSource();
// datasource.setUrl(url);
// datasource.setDriverClassName(driverClassName);
// datasource.setUsername(username);
// datasource.setPassword(password);
// // logger.info("密码:" + ConfigTools.decrypt(publicKey, password));
// datasource.setInitialSize(initialSize);
// datasource.setMinIdle(minIdle);
// datasource.setMaxActive(maxActive);
// datasource.setMaxWait(maxWait);
// datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
// datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
// datasource.setValidationQuery(validationQuery);
// datasource.setTestWhileIdle(testWhileIdle);
// datasource.setTestOnBorrow(testOnBorrow);
// datasource.setTestOnReturn(testOnReturn);
// datasource.setUseGlobalDataSourceStat(useGlobalDataSourceStat);
// datasource.setConnectProperties(connectProperties);
//
// try {
// datasource.setFilters(filters);
// } catch (SQLException e) {
// logger.error("========druid configuration initialization filter========", e);
// }
// return datasource;
// }
//
//
// public static void main(String[] args) throws Exception {
// String password = "xxxx";
// String[] arr = ConfigTools.genKeyPair(512);
// System.out.println("password:" + password);
// System.out.println("privateKey:" + arr[0]);
// System.out.println("publicKey:" + arr[1]);
// System.out.println("password:" + ConfigTools.encrypt(arr[0], password));
// }
//}
package com.mortals.xhx.config;
import lombok.Data;
import lombok.extern.apachecommons.CommonsLog;
import org.flowable.engine.ProcessEngine;
import org.flowable.engine.ProcessEngineConfiguration;
import org.flowable.engine.impl.cfg.StandaloneProcessEngineConfiguration;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
/**
* 流程引擎配置文件
*/
@Configuration
@ConfigurationProperties(prefix = "spring.datasource")
@Data
@CommonsLog
public class ProcessEngineConfig {
@Value("${spring.datasource.url}")
private String url;
@Value("${spring.datasource.driver-class-name}")
private String driverClassName;
@Value("${spring.datasource.username}")
private String username;
@Value("${spring.datasource.password}")
private String password;
/**
* 初始化流程引擎
* @return
*/
@Primary
@Bean(name = "processEngine")
public ProcessEngine initProcessEngine() {
log.info("=============================ProcessEngineBegin=============================");
// 流程引擎配置
ProcessEngineConfiguration cfg = null;
try {
cfg = new StandaloneProcessEngineConfiguration()
.setJdbcUrl(url)
.setJdbcUsername(username)
.setJdbcPassword(password)
.setJdbcDriver(driverClassName)
// 初始化基础表,不需要的可以改为 DB_SCHEMA_UPDATE_FALSE
//.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_CREATE)
.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_FALSE)
// 默认邮箱配置
// 发邮件的主机地址,先用 QQ 邮箱
.setMailServerHost("smtp.qq.com")
// POP3/SMTP服务的授权码
.setMailServerPassword("hergynqfusnsbbdf")
// 默认发件人
.setMailServerDefaultFrom("836369078@qq.com")
// 设置发件人用户名
.setMailServerUsername("管理员")
// 解决流程图乱码
.setActivityFontName("宋体")
.setLabelFontName("宋体")
.setAnnotationFontName("宋体");
} catch (Exception e) {
e.printStackTrace();
}
// 初始化流程引擎对象
ProcessEngine processEngine = cfg.buildProcessEngine();
log.info("=============================ProcessEngineEnd=============================");
return processEngine;
}
}
//package com.mortals.xhx.config;
//
//import com.fasterxml.jackson.annotation.JsonAutoDetect;
//import com.fasterxml.jackson.annotation.PropertyAccessor;
//import com.fasterxml.jackson.databind.ObjectMapper;
//import lombok.Data;
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.cache.Cache;
//import org.springframework.cache.annotation.CachingConfigurerSupport;
//import org.springframework.cache.interceptor.CacheErrorHandler;
//import org.springframework.cache.interceptor.SimpleCacheErrorHandler;
//import org.springframework.context.annotation.Bean;
//import org.springframework.context.annotation.Configuration;
//import org.springframework.data.redis.connection.RedisConnectionFactory;
//import org.springframework.data.redis.core.RedisTemplate;
//import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
//
///**
// * @Author: linqj
// * @Date: 2019/3/6 10:36
// */
//@Data
//@Configuration
//public class RedisCacheConfig extends CachingConfigurerSupport {
//
// /**
// * 配置文件设置redis配置之后自动生成连接工厂类(使用lettuce)
// */
// @Autowired
// private RedisConnectionFactory redisConnectionFactory;
//
// /**
// * 生成RedisTemplate
// *
// * @return
// */
// @Bean("redisTemplate")
// public RedisTemplate redisTemplate() {
// Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
// ObjectMapper om = new ObjectMapper();
// om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
// om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
// jackson2JsonRedisSerializer.setObjectMapper(om);
// RedisTemplate redisTemplate = new RedisTemplate<>();
// redisTemplate.setConnectionFactory(redisConnectionFactory);
// redisTemplate.setKeySerializer(jackson2JsonRedisSerializer);
// redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
// redisTemplate.setHashKeySerializer(jackson2JsonRedisSerializer);
// redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
// redisTemplate.afterPropertiesSet();
// return redisTemplate;
// }
//
//// @Bean("redisCacheManager")
//// public RedisCacheManager redisCacheManager() {
//// RedisCacheWriter writer = RedisCacheWriter.lockingRedisCacheWriter(redisConnectionFactory);
//// RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
//// // 设置默认缓存过期时间
//// if (!StringUtils.isEmpty(expiresTime)) {
//// config.entryTtl(Duration.ofMinutes(Long.valueOf(expiresTime))).disableCachingNullValues();
//// } else {
//// config.entryTtl(Duration.ofMinutes(10)).disableCachingNullValues();
//// }
//// // 设置缓存空间
//// if (StringUtils.isEmpty(names)) {
//// names = "default-redis";
//// }
//// // 使用自定义配置初始化cacheManager
//// RedisCacheManager redisCacheManager = new RedisCacheManager(writer, config, names.split(","));
//// return redisCacheManager;
//// }
//
//
//
// /**
// * 如果cache出错, 我们会记录在日志里,方便排查,比如反序列化异常
// */
// @Override
// public CacheErrorHandler errorHandler() {
// return new LoggingCacheErrorHandler();
// }
//
// static class LoggingCacheErrorHandler extends SimpleCacheErrorHandler {
// private final Logger LOGGER = LoggerFactory.getLogger(this.getClass());
//
// @Override
// public void handleCacheGetError(RuntimeException exception, Cache cache, Object key) {
// LOGGER.error(String.format("cacheName:%s,cacheKey:%s",
// cache == null ? "unknown" : cache.getName(), key), exception);
// super.handleCacheGetError(exception, cache, key);
// }
//
// @Override
// public void handleCachePutError(RuntimeException exception, Cache cache, Object key,
// Object value) {
// LOGGER.error(String.format("cacheName:%s,cacheKey:%s",
// cache == null ? "unknown" : cache.getName(), key), exception);
// super.handleCachePutError(exception, cache, key, value);
// }
//
// @Override
// public void handleCacheEvictError(RuntimeException exception, Cache cache, Object key) {
// LOGGER.error(String.format("cacheName:%s,cacheKey:%s",
// cache == null ? "unknown" : cache.getName(), key), exception);
// super.handleCacheEvictError(exception, cache, key);
// }
//
// @Override
// public void handleCacheClearError(RuntimeException exception, Cache cache) {
// LOGGER.error(String.format("cacheName:%s", cache == null ? "unknown" : cache.getName()),
// exception);
// super.handleCacheClearError(exception, cache);
// }
// }
//
//}
package com.mortals.xhx.entity;
import lombok.Data;
/**
* 统一返回结果集实体类
* @param <T> 返回数据对象
*/
@Data
public class ErrorMsg<T> {
//错误码
private Integer errorCode;
//错误信息,一般为前端提示信息
private String errorMsg;
//返回值,一般为成功后返回的数据
private T data;
//错误详情,一般为失败后的详细原因,如空指针之类的
private String errorDetail;
public ErrorMsg() {}
public ErrorMsg(Integer errorCode, String errorMsg) {
this.errorCode = errorCode;
this.errorMsg = errorMsg;
}
public ErrorMsg(Integer errorCode, String errorMsg, T data) {
this.errorCode = errorCode;
this.errorMsg = errorMsg;
this.data = data;
}
/**
* 配合静态对象直接设置 data 参数
* @param data
* @return
*/
public ErrorMsg setNewData(T data) {
ErrorMsg error = new ErrorMsg();
error.setErrorCode(this.errorCode);
error.setErrorMsg(this.errorMsg);
error.setErrorDetail(this.errorDetail);
error.setData(data);
return error;
}
/**
* 配合静态对象直接设置 errorMsg 参数
* @param errorMsg
* @return
*/
public ErrorMsg setNewErrorMsg(String errorMsg) {
ErrorMsg error = new ErrorMsg();
error.setErrorCode(this.errorCode);
error.setErrorMsg(errorMsg);
error.setErrorDetail(this.errorDetail);
error.setData(this.data);
return error;
}
public static final ErrorMsg SUCCESS = new ErrorMsg(200, "成功");
public static final ErrorMsg INSERT_SUCCESS = new ErrorMsg(200, "新增成功");
public static final ErrorMsg UPDATE_SUCCESS = new ErrorMsg(200, "更新成功");
public static final ErrorMsg SAVE_SUCCESS = new ErrorMsg(200, "保存成功");
public static final ErrorMsg DELETE_SUCCESS = new ErrorMsg(200, "删除成功");
public static final ErrorMsg UPLOAD_SUCCESS = new ErrorMsg(200, "上传成功");
public static final ErrorMsg DOWNLOAD_SUCCESS = new ErrorMsg(200, "下载成功");
public static final ErrorMsg LOGIN_SUCCESS = new ErrorMsg(200, "登陆成功");
public static final ErrorMsg LOGOUT_SUCCESS = new ErrorMsg(200, "登出成功");
public static final ErrorMsg LOGIN_ERROR = new ErrorMsg(201, "登陆错误");
public static final ErrorMsg LOGIN_EXPIRE = new ErrorMsg(202, "登陆过期");
public static final ErrorMsg ACCESS_LIMITED = new ErrorMsg(301, "访问受限");
public static final ErrorMsg ARGS_ERROR = new ErrorMsg(501, "参数错误");
public static final ErrorMsg UNKOWN_ERROR = new ErrorMsg(502, "系统异常");
public static final ErrorMsg ERROR = new ErrorMsg(503, "失败");
public static final ErrorMsg SAVE_ERROR = new ErrorMsg(503, "保存错误");
public static final ErrorMsg SELECT_ERROR = new ErrorMsg(503, "查询错误");
public static final ErrorMsg INSERT_ERROR = new ErrorMsg(503, "新增错误");
public static final ErrorMsg UPDATE_ERROR = new ErrorMsg(503, "更新错误");
public static final ErrorMsg DELETE_ERROR = new ErrorMsg(503, "删除错误");
public static final ErrorMsg UPLOAD_ERROR = new ErrorMsg(503, "上传错误");
public static final ErrorMsg DOWNLOAD_ERROR = new ErrorMsg(503, "下载错误");
public static final ErrorMsg OTHER_SYSTEM_ERROR = new ErrorMsg(504, "调用系统异常");
}
package com.mortals.xhx.entity;
import lombok.Data;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* 分页实体类,通过配置文件对 page, limit 进行默认值注入
*/
@Data
@Component
public class PageEntity<T> {
// 数据
private T data;
// 页码
private Integer page;
// 每页条数
private Integer limit;
// 数据总条数
private Long total;
// 总页数
private Integer totalPage;
public PageEntity() {}
public PageEntity(Integer page, Integer limit, Long total) {
this.page = page;
this.limit = limit;
this.total = total;
}
public PageEntity(Integer page, Integer limit, Integer total) {
this.page = page;
this.limit = limit;
this.total = total.longValue();
}
/**
* 计算分页起始索引
* @param page
* @param limit
* @return
*/
public static Integer startIndex(Integer page, Integer limit) {
return (page - 1) * limit;
}
/**
* 计算分页结束索引
* @param page
* @param limit
* @param total
* @return
*/
public static Integer endIndex(Integer page, Integer limit, Integer total) {
Integer endDataIndexAddOne;
if ((page - 1) * limit + limit > total) {
endDataIndexAddOne = total;
} else {
endDataIndexAddOne = (page - 1) * limit + limit;
}
return endDataIndexAddOne;
}
/**
* 计算总页数
*/
public Integer calculateTotalPage() {
if (this.limit != null && this.total != null) {
this.totalPage = (this.total.intValue() - 1) / this.limit + 1;
}
return this.totalPage;
}
/**
* 人工分页
* @param page 第几页
* @param limit 每页几条
* @param dataList 数据总列表
* @return
*/
public List<T> pageData(Integer page, Integer limit, Integer total, List<T> dataList) {
// 起始数据索引
Integer startDataIndex = startIndex(page, limit);
// 结束索引,最后一位不会被算进去
Integer endDataIndexAddOne = endIndex(page, limit, total);
return dataList.subList(startDataIndex, endDataIndexAddOne);
}
}
package com.mortals.xhx.exception;
import com.mortals.xhx.entity.ErrorMsg;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* 全局异常拦截器
**/
@ControllerAdvice
@ResponseBody
@Configuration
public class GlobalExceptionHandler {
@ExceptionHandler(value = Exception.class)
public ErrorMsg exceptionHandler(Exception e){
e.printStackTrace();
ErrorMsg errorMsg = ErrorMsg.UNKOWN_ERROR;
errorMsg.setErrorDetail(e.toString());
return errorMsg;
}
}
\ No newline at end of file
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mortals.xhx.flowable.conf;
import org.flowable.ui.modeler.rest.app.EditorGroupsResource;
import org.flowable.ui.modeler.rest.app.EditorUsersResource;
import org.flowable.ui.modeler.rest.app.StencilSetResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcRegistrations;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
import org.springframework.web.servlet.i18n.SessionLocaleResolver;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
@Configuration
@ComponentScan(value = { "org.flowable.ui.modeler.rest.app",
// 不加载 rest,因为 getAccount 接口需要我们自己实现
// "org.flowable.ui.common.rest"
},excludeFilters = {
// 移除 EditorUsersResource 与 EditorGroupsResource,因为不使用 IDM 部分
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = EditorUsersResource.class),
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = EditorGroupsResource.class),
// 配置文件用自己的
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = StencilSetResource.class),
}
)
@EnableAsync
public class AppDispatcherServletConfiguration implements WebMvcRegistrations {
private static final Logger LOGGER = LoggerFactory.getLogger(AppDispatcherServletConfiguration.class);
@Bean
public SessionLocaleResolver localeResolver() {
return new SessionLocaleResolver();
}
@Bean
public LocaleChangeInterceptor localeChangeInterceptor() {
LOGGER.debug("Configuring localeChangeInterceptor");
LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
localeChangeInterceptor.setParamName("language");
return localeChangeInterceptor;
}
@Override
public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
LOGGER.debug("Creating requestMappingHandlerMapping");
RequestMappingHandlerMapping requestMappingHandlerMapping = new RequestMappingHandlerMapping();
requestMappingHandlerMapping.setUseSuffixPatternMatch(false);
requestMappingHandlerMapping.setRemoveSemicolonContent(false);
Object[] interceptors = { localeChangeInterceptor() };
requestMappingHandlerMapping.setInterceptors(interceptors);
return requestMappingHandlerMapping;
}
}
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mortals.xhx.flowable.conf;
import org.flowable.ui.common.service.idm.RemoteIdmService;
import org.flowable.ui.modeler.properties.FlowableModelerAppProperties;
import org.flowable.ui.modeler.servlet.ApiDispatcherServletConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
@Configuration
@EnableConfigurationProperties(FlowableModelerAppProperties.class)
@ComponentScan(basePackages = {
// "org.flowable.ui.modeler.conf",
"org.flowable.ui.modeler.repository",
"org.flowable.ui.modeler.service",
// "org.flowable.ui.modeler.security", //授权方面的都不需要
// "org.flowable.ui.common.conf", // flowable 开发环境内置的数据库连接
// "org.flowable.ui.common.filter", // IDM 方面的过滤器
"org.flowable.ui.common.service",
"org.flowable.ui.common.repository",
//
// "org.flowable.ui.common.security",//授权方面的都不需要
"org.flowable.ui.common.tenant" },excludeFilters = {
// 移除 RemoteIdmService
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = RemoteIdmService.class),
}
)
public class ApplicationConfiguration {
@Bean
public ServletRegistrationBean modelerApiServlet(ApplicationContext applicationContext) {
AnnotationConfigWebApplicationContext dispatcherServletConfiguration = new AnnotationConfigWebApplicationContext();
dispatcherServletConfiguration.setParent(applicationContext);
dispatcherServletConfiguration.register(ApiDispatcherServletConfiguration.class);
DispatcherServlet servlet = new DispatcherServlet(dispatcherServletConfiguration);
ServletRegistrationBean registrationBean = new ServletRegistrationBean(servlet, "/api/*");
registrationBean.setName("Flowable Modeler App API Servlet");
registrationBean.setLoadOnStartup(1);
registrationBean.setAsyncSupported(true);
return registrationBean;
}
}
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mortals.xhx.flowable.conf;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.flowable.ui.common.service.exception.InternalServerErrorException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/app")
public class FlowableStencilSetResource {
private static final Logger LOGGER = LoggerFactory.getLogger(FlowableStencilSetResource.class);
@Autowired
protected ObjectMapper objectMapper;
@RequestMapping(value = "/rest/stencil-sets/editor", method = RequestMethod.GET, produces = "application/json")
public JsonNode getStencilSetForEditor() {
try {
JsonNode stencilNode = objectMapper.readTree(this.getClass().getClassLoader().getResourceAsStream("stencilset/stencilset_bpmn.json"));
return stencilNode;
} catch (Exception e) {
LOGGER.error("Error reading bpmn stencil set json", e);
throw new InternalServerErrorException("Error reading bpmn stencil set json");
}
}
@RequestMapping(value = "/rest/stencil-sets/cmmneditor", method = RequestMethod.GET, produces = "application/json")
public JsonNode getCmmnStencilSetForEditor() {
try {
JsonNode stencilNode = objectMapper.readTree(this.getClass().getClassLoader().getResourceAsStream("stencilset/stencilset_cmmn.json"));
return stencilNode;
} catch (Exception e) {
LOGGER.error("Error reading bpmn stencil set json", e);
throw new InternalServerErrorException("Error reading bpmn stencil set json");
}
}
}
spring:
main:
allow-bean-definition-overriding: true
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment