1. 不要使用7.1.0.M4,+经测试7.1.0.M6可用
    2. 检查list是否为空,用CollectionUtil.isNotEmpty

      1. List<SequenceFlow> sequenceFlows = userTask.getIncomingFlows();//获取入线信息-->获取所有上级节点
      2. if (CollectionUtil.isNotEmpty(sequenceFlows)) {}
    3. 流程回退基本思路:

    取得当前节点的信息取得当前节点的上一个节点的信息
    保存当前节点的流向
    新建流向,由当前节点指向上一个节点
    将当前节点的流向设置为上面新建的流向
    当前节点完成任务
    将当前节点的流向还原
    取得之前上个节点的执行人
    设置上个节点的assignee为之前的执行人

    1. 在Activiti7之前的版本中可以使用FormService去获取bpmn中的自定义表单信息,在Activiti7中删除了FormService,可以使用如下方法去获取:

      1. ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(processBtnDto.getDeploymentId()).singleResult();
      2. ProcessInstance processInstance = runtimeService.startProcessInstanceById(processDefinition.getId());
      3. Task task = taskService.createTaskQuery().processInstanceId(processInstance.getProcessInstanceId()).singleResult();
      4. //获取task对应的表单内容
      5. UserTask userTask = (UserTask)repositoryService.getBpmnModel(processDefinition.getId())
      6. .getFlowElement(task.getTaskDefinitionKey());
      7. List<FormProperty> formProperties = userTask.getFormProperties();
    2. 获取流程上一节点信息的两种方式 ```bash /**

      • 根据流程实例id获取上一个节点的信息 *
      • @param proInsId
      • @param historyService
      • @return */ public static HistoricTaskInstance queryUpOneNodeMessage(String proInsId, HistoryService historyService) { //上一个节点 List list = historyService

        1. .createHistoricTaskInstanceQuery()
        2. .processInstanceId(proInsId)
        3. .orderByHistoricTaskInstanceEndTime()
        4. .desc()
        5. .list();

        HistoricTaskInstance taskInstance = null; if (!list.isEmpty()) {

        1. if (list.get(0).getEndTime() != null) {
        2. taskInstance = list.get(0);
        3. }

        } return taskInstance; }

        /**

      • 根据任务id获取上一个节点的信息 *
      • @param taskId
      • @return */ public static HistoricTaskInstance queryUpOneNode(String taskId, HistoryService historyService) { //上一个节点 List list = historyService
        1. .createHistoricTaskInstanceQuery()
        2. .taskId(taskId).orderByHistoricTaskInstanceEndTime()
        3. .desc()
        4. .list();
        HistoricTaskInstance taskInstance = null; if (!list.isEmpty()) {
        1. if (list.get(0).getEndTime() != null) {
        2. taskInstance = list.get(0);
        3. }
        } return taskInstance; }
    1. 6. File.separator
    2. File.separator 的作用相当于 ' \ '<br />在 windows 文件文件分隔符 ' \ ' 或者 ' / ' 都可以<br />但是在 Linux 中,是不识别 ' \ ' 的,而 File.separator 是系统默认的文件分隔符号,在 UNIX 系统上,此字段的值为 ' / '
    3. Microsoft Windows 系统上,它为 ' \ ' 屏蔽了这些系统的区别。
    4. 所以用 File.separator 保证了在任何系统下不会出错<br />此外 File 类还有:<br />1separatorChar
    5. 与系统有关的默认名称分隔符,为了方便,它被表示为一个字符串。此字符串只包含一个字符
    6. 2pathSeparatorChar
    7. 与系统有关的路径分隔符,为了方便,它被表示为一个字符串
    8. 3pathSeparator
    9. 此字符用于分隔以路径列表形式给定的文件序列中的文件名
    10. UNIX 系统上此字段为 ' : '
    11. Microsoft Windows 系统上,它为 ' ; '
    12. 7. file.getParentFile().mkdirs()
    13. ```bash
    14. public static void main(String[] args) throws IOException {
    15. // 文件的路径
    16. String path = "C:\\Users\\immortal\\Desktop\\other_temp\\csdn_test\\pers\\immort\\test\\temp";
    17. // 创建一个file对象,指向其文件
    18. File file = new File(path);
    19. // 为了避免文件创建失败(其所在的文件夹不存在
    20. // 所以创建它所在的文件目录)
    21. if (null != file.getParentFile()) {
    22. // 创建它所在的文件夹的目录,(该文件夹不存在的话,创建)
    23. file.getParentFile().mkdirs();
    24. }
    25. // 最后创建文件。这样创建文件,会更保险
    26. file.createNewFile();//因为我们没有指定扩展名,所以此文件没有扩展名
    27. }
    1. FileUtils copy方法

      1. //复制文件
      2. FileCopyUtils.copy(resourceNameInputStream, new FileOutputStream(resourcePath));
    2. Java stream()流

      1. .distinct() //去重
      2. public Page<ActTaskDTO> getTaskAll() {
      3. Page<ActTaskDTO> actTaskDTOs = new Page<ActTaskDTO>();
      4. List<Task> taskList = taskService.createTaskQuery().list();
      5. List<ActTaskDTO> actTaskDTOList = new ArrayList<>();
      6. Set<String> processInstanceIDSet = taskList.parallelStream().map(t -> t.getProcessInstanceId()).distinct().collect(Collectors.toSet());
      7. List<ProcessInstance> processInstanceList = runtimeService.createProcessInstanceQuery()
      8. .processInstanceIds(processInstanceIDSet)
      9. .list();
      10. actTaskDTOList = taskList.parallelStream()
      11. .map(t -> new ActTaskDTO(t, processInstanceList.parallelStream()
      12. .filter(pi -> t.getProcessInstanceId().equals(pi.getId())).findAny().get())).collect(Collectors.toList());
      13. actTaskDTOs.setRecords(actTaskDTOList);
      14. return actTaskDTOs;
      15. }
    3. .singleResult() 获取一条记录 .list() 获取 记录list集合 .findAny() 返回任意一条记录 .findFirst() 返回第一条记录

      1. ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId("ddd").singleResult();
      2. List<ProcessInstance> processInstance = runtimeService.createProcessInstanceQuery().processInstanceId("ddd").list();
      3. actTaskDTOList = taskList.stream()
      4. .map(t -> new ActTaskDTO(t, processInstanceList.parallelStream()
      5. .filter(pi -> t.getProcessInstanceId().equals(pi.getId())).findAny().get())).collect(Collectors.toList());
    4. listpage() 分页方法

    5. instanceof

    instanceof 是 Java 的保留关键字。它的作用是测试它左边的对象是否是它右边的类的实例,返回 boolean 的数据类型

    1. @GetMapping、@PostMapping、@PutMapping、@DeleteMapping、@PatchMapping、@RequestMapping详解最近写项目中突然发现有人再controller层写@PostMapping,这对于经常用@RequestMapping的我来说,感到跟奇怪,网上搜寻了一些资料,特在此整合一下:

    Spring4.3中引进了{@GetMapping、@PostMapping、@PutMapping、@DeleteMapping、@PatchMapping} 来帮助简化常用的HTTP方法的映射 并更好地表达被注解方法的语义

    @GetMapping: 处理get请求,传统的RequestMapping来编写应该是@RequestMapping(value = “/get/{id}”, method = RequestMethod.GET)
    新方法可以简写为:
    @GetMapping(“/get/{id}”)
    @PostMapping: 处理post请求,传统的RequestMapping来编写应该是@RequestMapping(value = “/get/{id}”,method = RequestMethod.POST)
    新方法可以简写为:
    @PostMapping(“/get/{id}”)
    @PutMapping: 和PostMapping作用等同,都是用来向服务器提交信息。如果是添加信息,倾向于用@PostMapping,如果是更新信息,倾向于用@PutMapping。两者差别不是很明显。
    @DeleteMapping 删除URL映射,具体没有再实践中用过,不知道好在什么地方
    @PatchMapping 至今不知如何用,再什么场景下用。。。有知道的欢迎留言或私信
    上面所有的mapping归根到底就是两种请求,即:post和get,Spinrg官方引进众多请求的原因个人感觉是,简化配置。post和get两者的区别如下:
    首先,什么情况下是get请求呢:

    直接在浏览器地址栏输入某个地址
    表单默认的提交方式
    什么情况下是post请求呢:

    设置表单method = “post”
    ajax type: ‘post’,
    浏览器通过url处理的请求为get请求,如果后台限制只能用post请求会发生如下错误:

    method not allowed, The specified HTTP method is not allowed for the requested resource.
    1
    get请求特点:
    a. 请求参数会添加到请求资源路径的后面,只能添加少量参数(因为请求行只有一行,大约只能存放2K左右的数据)
    b. 请求参数会显示在浏览器地址栏,路由器会记录请求地址 (极为的不安全)
    c.如果传输中文,必定会乱码(原因:get请求默认编码格式为:IIO-8859-1,后台编码格式一般为:GBK或者UTF-8)
    post请求的特点:
    a. 请求参数添加到实体内容里面,可以添加大量的参数(也解释了为什么浏览器地址栏不能发送post请求,在地址栏里我们只能填写URL,并不能进入到Http包的实体当中)
    b. 相对安全,但是,post请求不会对请求参数进行加密处理(可以使用https协议来保证数据安全)

    1. @GetMapping、@PostMapping、@PutMapping、@DeleteMapping的区别

    https://blog.csdn.net/qq_42828912/article/details/109716170

    1. equals()方法会比较值和精度(1.0 与 1.00 返回结果为 false),而 compareTo()则会忽略精度。
    2. string.trim()函数:去掉字符串首尾的空格