Activiti6(1)

46 阅读7分钟

tempMapList.add(map);

}

}

}

if (!CollectionUtils.isEmpty(tempMapList)) {

// 遍历匹配的集合,取得开始时间最早的一个

long earliestStamp = 0L;

String highLightedFlowId = null;

for (Map<String, Object> map : tempMapList) {

long highLightedFlowStartTime = Long.valueOf(map.get("highLightedFlowStartTime").toString());

if (earliestStamp == 0 || earliestStamp >= highLightedFlowStartTime) {

highLightedFlowId = map.get("highLightedFlowId").toString();

earliestStamp = highLightedFlowStartTime;

}

}

highLightedFlowIds.add(highLightedFlowId);

}

}

}

return highLightedFlowIds;

}

3.高亮正在进行中的节点+处理过的连接线+处理过的节点

在这里插入图片描述

// 获取流程中已经执行的节点,按照执行先后顺序排序

List historicActivityInstances = historyService.

createHistoricActivityInstanceQuery()

.processInstanceId(processInstanceId)

.orderByHistoricActivityInstanceId().asc().list();

// 高亮已经执行流程节点ID集合

List highLightedActivitiIds = new ArrayList<>();

for (HistoricActivityInstance historicActivityInstance : historicActivityInstances) {

highLightedActivitiIds.add(historicActivityInstance.getActivityId());

}

4.自定义商务范配色

绘图原理是调用下面的方法,扩展一波即可。

ProcessDiagramGenerator processDiagramGenerator = new DefaultProcessDiagramGenerator();

processDiagramGenerator.generateDiagram()

核心方法是,DefaultProcessDiagramGenerator.drawActivity 重写它吧

protected void drawActivity(DefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel,

FlowNode flowNode, List highLightedActivities, List highLightedFlows, double scaleFactor) {

在这里插入图片描述

全部代码如下:

涉及到2个类:

LakerProcessDiagramCanvas

继承了DefaultProcessDiagramCanvas

  • 重写定义了这2个值

HIGHLIGHT_COLOR = Color.cyan;// 默认颜色,之前是红色

THICK_TASK_BORDER_STROKE = new BasicStroke(6.0f);// 边框宽度 之前是3.0

  • 新定义了可以传入颜色的方法

public void drawHighLightColor(int x, int y, int width, int height, Color color) {

Paint originalPaint = g.getPaint();

Stroke originalStroke = g.getStroke();

g.setPaint(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);

}

LakerProcessDiagramGenerator

继承了DefaultProcessDiagramGenerator

  • 重写了initProcessDiagramCanvas让其返回我们扩展的LakerProcessDiagramCanvas

return new LakerProcessDiagramCanvas((int) maxX + 10, (int) maxY + 10, (int) minX, (int) minY,

imageType, activityFontName, labelFontName, annotationFontName, customClassLoader);

  • 重写了drawActivity,最后一个节点自定义颜色显示

// 画高亮的节点 TODO

if (highLightedActivities.contains(flowNode.getId())) {

if (highLightedActivities.get(highLightedActivities.size() - 1).equalsIgnoreCase(flowNode.getId())) {

LakerProcessDiagramCanvas lakerProcessDiagramCanvas = ((LakerProcessDiagramCanvas) processDiagramCanvas);

lakerProcessDiagramCanvas.drawHighLightColor((int) graphicInfo.getX(), (int) graphicInfo.getY(), (int) graphicInfo.getWidth(), (int) graphicInfo.getHeight(), Color.YELLOW);

} else {

processDiagramCanvas.drawHighLight((int) graphicInfo.getX(), (int) graphicInfo.getY(), (int) graphicInfo.getWidth(), (int) graphicInfo.getHeight());

}

}

全部源码
  • 继承DefaultProcessDiagramCanvas

package com.laker.workflow.controller;

import org.activiti.image.impl.DefaultProcessDiagramCanvas;

import java.awt.*;

import java.awt.geom.RoundRectangle2D;

public class LakerProcessDiagramCanvas extends DefaultProcessDiagramCanvas {

public LakerProcessDiagramCanvas(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);

HIGHLIGHT_COLOR = Color.cyan;

THICK_TASK_BORDER_STROKE = new BasicStroke(6.0f);

}

public LakerProcessDiagramCanvas(int width, int height, int minX, int minY, String imageType) {

super(width, height, minX, minY, imageType);

HIGHLIGHT_COLOR = Color.cyan;

THICK_TASK_BORDER_STROKE = new BasicStroke(6.0f);

}

public void drawHighLightColor(int x, int y, int width, int height, Color color) {

Paint originalPaint = g.getPaint();

Stroke originalStroke = g.getStroke();

g.setPaint(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);

}

}

  • 继承DefaultProcessDiagramGenerator

package com.laker.workflow.controller;

import org.activiti.bpmn.model.Process;

import org.activiti.bpmn.model.*;

import org.activiti.image.impl.DefaultProcessDiagramCanvas;

import org.activiti.image.impl.DefaultProcessDiagramGenerator;

import java.awt.*;

import java.awt.image.BufferedImage;

import java.util.List;

public class LakerProcessDiagramGenerator extends DefaultProcessDiagramGenerator {

private BufferedImage processDiagram;

@Override

protected DefaultProcessDiagramCanvas generateProcessDiagram(BpmnModel bpmnModel, String imageType,

List highLightedActivities, List highLightedFlows,

String activityFontName, String labelFontName, String annotationFontName, ClassLoader customClassLoader, double scaleFactor) {

{

prepareBpmnModel(bpmnModel);

DefaultProcessDiagramCanvas processDiagramCanvas = initProcessDiagramCanvas(bpmnModel, imageType, activityFontName, labelFontName, annotationFontName, customClassLoader);

// Draw pool shape, if process is participant in collaboration

for (Pool pool : bpmnModel.getPools()) {

GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(pool.getId());

processDiagramCanvas.drawPoolOrLane(pool.getName(), graphicInfo);

}

// Draw lanes

for (Process process : bpmnModel.getProcesses()) {

for (Lane lane : process.getLanes()) {

GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(lane.getId());

processDiagramCanvas.drawPoolOrLane(lane.getName(), graphicInfo);

}

}

// Draw activities and their sequence-flows

for (FlowNode flowNode : bpmnModel.getProcesses().get(0).findFlowElementsOfType(FlowNode.class)) {

drawActivity(processDiagramCanvas, bpmnModel, flowNode, highLightedActivities, highLightedFlows, scaleFactor);

}

for (Process process : bpmnModel.getProcesses()) {

for (FlowNode flowNode : process.findFlowElementsOfType(FlowNode.class)) {

drawActivity(processDiagramCanvas, bpmnModel, flowNode, highLightedActivities, highLightedFlows, scaleFactor);

}

}

// Draw artifacts

for (Process process : bpmnModel.getProcesses()) {

for (Artifact artifact : process.getArtifacts()) {

drawArtifact(processDiagramCanvas, bpmnModel, artifact);

}

List subProcesses = process.findFlowElementsOfType(SubProcess.class, true);

if (subProcesses != null) {

for (SubProcess subProcess : subProcesses) {

for (Artifact subProcessArtifact : subProcess.getArtifacts()) {

drawArtifact(processDiagramCanvas, bpmnModel, subProcessArtifact);

}

}

}

}

return processDiagramCanvas;

}

}

@Override

protected void drawActivity(DefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel,

FlowNode flowNode, List highLightedActivities, List highLightedFlows, double scaleFactor) {

{

ActivityDrawInstruction drawInstruction = activityDrawInstructions.get(flowNode.getClass());

if (drawInstruction != null) {

drawInstruction.draw(processDiagramCanvas, bpmnModel, flowNode);

// Gather info on the multi instance marker

boolean multiInstanceSequential = false, multiInstanceParallel = false, collapsed = false;

if (flowNode instanceof Activity) {

Activity activity = (Activity) flowNode;

MultiInstanceLoopCharacteristics multiInstanceLoopCharacteristics = activity.getLoopCharacteristics();

if (multiInstanceLoopCharacteristics != null) {

multiInstanceSequential = multiInstanceLoopCharacteristics.isSequential();

multiInstanceParallel = !multiInstanceSequential;

}

}

// Gather info on the collapsed marker

GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());

if (flowNode instanceof SubProcess) {

collapsed = graphicInfo.getExpanded() != null && !graphicInfo.getExpanded();

} else if (flowNode instanceof CallActivity) {

collapsed = true;

}

if (scaleFactor == 1.0) {

// Actually draw the markers

processDiagramCanvas.drawActivityMarkers((int) graphicInfo.getX(), (int) graphicInfo.getY(), (int) graphicInfo.getWidth(), (int) graphicInfo.getHeight(),

multiInstanceSequential, multiInstanceParallel, collapsed);

}

// 画高亮的节点 TODO

if (highLightedActivities.contains(flowNode.getId())) {

if (highLightedActivities.get(highLightedActivities.size() - 1).equalsIgnoreCase(flowNode.getId())) {

LakerProcessDiagramCanvas lakerProcessDiagramCanvas = ((LakerProcessDiagramCanvas) processDiagramCanvas);

lakerProcessDiagramCanvas.drawHighLightColor((int) graphicInfo.getX(), (int) graphicInfo.getY(), (int) graphicInfo.getWidth(), (int) graphicInfo.getHeight(), Color.YELLOW);

} else {

processDiagramCanvas.drawHighLight((int) graphicInfo.getX(), (int) graphicInfo.getY(), (int) graphicInfo.getWidth(), (int) graphicInfo.getHeight());

}

}

}

// Outgoing transitions of activity

for (SequenceFlow sequenceFlow : flowNode.getOutgoingFlows()) {

boolean highLighted = (highLightedFlows.contains(sequenceFlow.getId()));

String defaultFlow = null;

if (flowNode instanceof Activity) {

defaultFlow = ((Activity) flowNode).getDefaultFlow();

} else if (flowNode instanceof Gateway) {

defaultFlow = ((Gateway) flowNode).getDefaultFlow();

}

boolean isDefault = false;

if (defaultFlow != null && defaultFlow.equalsIgnoreCase(sequenceFlow.getId())) {

isDefault = true;

}

boolean drawConditionalIndicator = sequenceFlow.getConditionExpression() != null && !(flowNode instanceof Gateway);

String sourceRef = sequenceFlow.getSourceRef();

String targetRef = sequenceFlow.getTargetRef();

FlowElement sourceElement = bpmnModel.getFlowElement(sourceRef);

FlowElement targetElement = bpmnModel.getFlowElement(targetRef);

List graphicInfoList = bpmnModel.getFlowLocationGraphicInfo(sequenceFlow.getId());

if (graphicInfoList != null && graphicInfoList.size() > 0) {

graphicInfoList = connectionPerfectionizer(processDiagramCanvas, bpmnModel, sourceElement, targetElement, graphicInfoList);

int xPoints[] = new int[graphicInfoList.size()];

int yPoints[] = new int[graphicInfoList.size()];

for (int i = 1; i < graphicInfoList.size(); i++) {

GraphicInfo graphicInfo = graphicInfoList.get(i);

GraphicInfo previousGraphicInfo = graphicInfoList.get(i - 1);

if (i == 1) {

xPoints[0] = (int) previousGraphicInfo.getX();

yPoints[0] = (int) previousGraphicInfo.getY();

}

xPoints[i] = (int) graphicInfo.getX();

yPoints[i] = (int) graphicInfo.getY();

}

processDiagramCanvas.drawSequenceflow(xPoints, yPoints, drawConditionalIndicator, isDefault, highLighted, scaleFactor);

// Draw sequenceflow label

GraphicInfo labelGraphicInfo = bpmnModel.getLabelGraphicInfo(sequenceFlow.getId());

if (labelGraphicInfo != null) {

processDiagramCanvas.drawLabel(sequenceFlow.getName(), labelGraphicInfo, false);

}

}

}

// Nested elements

if (flowNode instanceof FlowElementsContainer) {

for (FlowElement nestedFlowElement : ((FlowElementsContainer) flowNode).getFlowElements()) {

if (nestedFlowElement instanceof FlowNode) {

drawActivity(processDiagramCanvas, bpmnModel, (FlowNode) nestedFlowElement,

highLightedActivities, highLightedFlows, scaleFactor);

}

}

}

}

}

protected static DefaultProcessDiagramCanvas initProcessDiagramCanvas(BpmnModel bpmnModel, String imageType,

String activityFontName, String labelFontName, String annotationFontName, ClassLoader customClassLoader) {

// We need to calculate maximum values to know how big the image will be in its entirety

double minX = Double.MAX_VALUE;

double maxX = 0;

double minY = Double.MAX_VALUE;

double maxY = 0;

for (Pool pool : bpmnModel.getPools()) {

GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(pool.getId());

minX = graphicInfo.getX();

maxX = graphicInfo.getX() + graphicInfo.getWidth();

minY = graphicInfo.getY();

maxY = graphicInfo.getY() + graphicInfo.getHeight();

}

List flowNodes = gatherAllFlowNodes(bpmnModel);

for (FlowNode flowNode : flowNodes) {

GraphicInfo flowNodeGraphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());

// width

if (flowNodeGraphicInfo.getX() + flowNodeGraphicInfo.getWidth() > maxX) {

maxX = flowNodeGraphicInfo.getX() + flowNodeGraphicInfo.getWidth();

}

if (flowNodeGraphicInfo.getX() < minX) {

minX = flowNodeGraphicInfo.getX();

}

// height

if (flowNodeGraphicInfo.getY() + flowNodeGraphicInfo.getHeight() > maxY) {

maxY = flowNodeGraphicInfo.getY() + flowNodeGraphicInfo.getHeight();

}

if (flowNodeGraphicInfo.getY() < minY) {

minY = flowNodeGraphicInfo.getY();

}

for (SequenceFlow sequenceFlow : flowNode.getOutgoingFlows()) {

List graphicInfoList = bpmnModel.getFlowLocationGraphicInfo(sequenceFlow.getId());

if (graphicInfoList != null) {

for (GraphicInfo graphicInfo : graphicInfoList) {

// width

if (graphicInfo.getX() > maxX) {

maxX = graphicInfo.getX();

}

if (graphicInfo.getX() < minX) {

minX = graphicInfo.getX();

}

// height

if (graphicInfo.getY() > maxY) {

maxY = graphicInfo.getY();

}

if (graphicInfo.getY() < minY) {

minY = graphicInfo.getY();

}

}

}

}

}

List artifacts = gatherAllArtifacts(bpmnModel);

for (Artifact artifact : artifacts) {

GraphicInfo artifactGraphicInfo = bpmnModel.getGraphicInfo(artifact.getId());

if (artifactGraphicInfo != null) {

// width

if (artifactGraphicInfo.getX() + artifactGraphicInfo.getWidth() > maxX) {

maxX = artifactGraphicInfo.getX() + artifactGraphicInfo.getWidth();

}

if (artifactGraphicInfo.getX() < minX) {

minX = artifactGraphicInfo.getX();

}

// height

if (artifactGraphicInfo.getY() + artifactGraphicInfo.getHeight() > maxY) {

maxY = artifactGraphicInfo.getY() + artifactGraphicInfo.getHeight();

}

if (artifactGraphicInfo.getY() < minY) {

minY = artifactGraphicInfo.getY();

}

}

List graphicInfoList = bpmnModel.getFlowLocationGraphicInfo(artifact.getId());

if (graphicInfoList != null) {

for (GraphicInfo graphicInfo : graphicInfoList) {

// width

if (graphicInfo.getX() > maxX) {

maxX = graphicInfo.getX();

}

if (graphicInfo.getX() < minX) {

minX = graphicInfo.getX();

}

// height

if (graphicInfo.getY() > maxY) {

maxY = graphicInfo.getY();

}

if (graphicInfo.getY() < minY) {

minY = graphicInfo.getY();

}

}

}

}

int nrOfLanes = 0;

for (Process process : bpmnModel.getProcesses()) {

for (Lane l : process.getLanes()) {

nrOfLanes++;

GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(l.getId());

// // width

if (graphicInfo.getX() + graphicInfo.getWidth() > maxX) {

maxX = graphicInfo.getX() + graphicInfo.getWidth();

}

if (graphicInfo.getX() < minX) {

minX = graphicInfo.getX();

}

// height

if (graphicInfo.getY() + graphicInfo.getHeight() > maxY) {

maxY = graphicInfo.getY() + graphicInfo.getHeight();

}

if (graphicInfo.getY() < minY) {

minY = graphicInfo.getY();

}

}

}

// Special case, see activiti.atlassian.net/browse/ACT-…

if (flowNodes.isEmpty() && bpmnModel.getPools().isEmpty() && nrOfLanes == 0) {

// Nothing to show

minX = 0;

minY = 0;

}

return new LakerProcessDiagramCanvas((int) maxX + 10, (int) maxY + 10, (int) minX, (int) minY,

imageType, activityFontName, labelFontName, annotationFontName, customClassLoader);

}

}

参考:blog.csdn.net/u010740917/…

【流程跟踪】流程的任务流转路径


List historicTaskInstances = historyService.createHistoricTaskInstanceQuery()

.processInstanceId("2515")

.orderByHistoricTaskInstanceEndTime().asc().list();

SELECT DISTINCT RES.*

FROM ACT_HI_TASKINST RES

WHERE RES.PROC_INST_ID_ = '2515'

ORDER BY RES.END_TIME_ ASC LIMIT '2147483647' OFFSET '0'

【流程跟踪】设置流程标题


例如流程标题为“张三的请假单”

runtimeService.setProcessInstanceName(processInstance.getId(),"张三的请假条");

最后的内容

在开头跟大家分享的时候我就说,面试我是没有做好准备的,全靠平时的积累,确实有点临时抱佛脚了,以至于我自己还是挺懊恼的。(准备好了或许可以拿个40k,没做准备只有30k+,你们懂那种感觉吗)

如何准备面试?

1、前期铺垫(技术沉积)

程序员面试其实是对于技术的一次摸底考试,你的技术牛逼,那你就是大爷。大厂对于技术的要求主要体现在:基础,原理,深入研究源码,广度,实战五个方面,也只有将原理理论结合实战才能把技术点吃透。

下面是我会看的一些资料笔记,希望能帮助大家由浅入深,由点到面的学习Java,应对大厂面试官的灵魂追问

这部分内容过多,小编只贴出部分内容展示给大家了,见谅见谅!

  • Java程序员必看《Java开发核心笔记(华山版)》

  • Redis学习笔记

  • Java并发编程学习笔记

四部分,详细拆分并发编程——并发编程+模式篇+应用篇+原理篇

  • Java程序员必看书籍《深入理解 ava虚拟机第3版》(pdf版)

  • 大厂面试必问——数据结构与算法汇集笔记

其他像Spring,SpringBoot,SpringCloud,SpringCloudAlibaba,Dubbo,Zookeeper,Kafka,RocketMQ,RabbitMQ,Netty,MySQL,Docker,K8s等等我都整理好,这里就不一一展示了。

2、狂刷面试题

技术主要是体现在平时的积累实用,面试前准备两个月的时间再好好复习一遍,紧接着就可以刷面试题了,下面这些面试题都是小编精心整理的,贴给大家看看。

①大厂高频45道笔试题(智商题)

②BAT大厂面试总结(部分内容截图)

③面试总结

3、结合实际,修改简历

程序员的简历一定要多下一些功夫,尤其是对一些字眼要再三斟酌,如“精通、熟悉、了解”这三者的区别一定要区分清楚,否则就是在给自己挖坑了。当然不会包装,我可以将我的简历给你参考参考,如果还不够,那下面这些简历模板任你挑选:

以上分享,希望大家可以在金三银四跳槽季找到一份好工作,但千万也记住,技术一定是平时工作种累计或者自学(或报班跟着老师学)通过实战累计的,千万不要临时抱佛脚。

另外,面试中遇到不会的问题不妨尝试讲讲自己的思路,因为有些问题不是考察我们的编程能力,而是逻辑思维表达能力;最后平时要进行自我分析与评价,做好职业规划,不断摸索,提高自己的编程能力和抽象思维能力。

相关阅读docs.qq.com/doc/DSmxTbFJ1cmN1R2dB