update - 添加防重提交功能
This commit is contained in:
parent
b2ac834a9f
commit
954f36d982
@ -334,7 +334,7 @@ public class BpmnProcessTaskServiceImpl implements BpmnProcessTaskService {
|
||||
taskService.complete(task.getId());
|
||||
}
|
||||
|
||||
//add by zuoqinbo 处理加签任务,分为向前加签和向后加签
|
||||
//add by zuoqinbo 处理加签[分为向前加签和向后加签]或转交的任务
|
||||
String parentTaskId = task.getParentTaskId();
|
||||
if (StringUtils.hasLength(parentTaskId)) {
|
||||
List<Task> subTasks = taskService.getSubTasks(parentTaskId);
|
||||
@ -356,13 +356,25 @@ public class BpmnProcessTaskServiceImpl implements BpmnProcessTaskService {
|
||||
this.createSubTask(taskEntity, parentTaskId, remainAssigner);
|
||||
taskService.setVariable(taskEntity.getId(), COUNTERSIGN_REMAIN_ASSIGNER_LIST, remainAssignerList);
|
||||
} else {
|
||||
// TODO 这里还需要递归上去直到没有 parentId
|
||||
taskService.complete(parentTaskId);
|
||||
// 递归上去直到没有 parentId
|
||||
recursionCompleteParentTask(parentTaskId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void recursionCompleteParentTask(String parentTaskId) {
|
||||
if (!StringUtils.hasLength(parentTaskId)) {
|
||||
return;
|
||||
}
|
||||
taskService.complete(parentTaskId);
|
||||
Task parentTask = getTask(parentTaskId, null, null);
|
||||
if (Objects.nonNull(parentTask)) {
|
||||
recursionCompleteParentTask(parentTaskId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 创建加签子任务
|
||||
* A加签给A A再加签给A
|
||||
|
||||
@ -0,0 +1,27 @@
|
||||
package cn.axzo.workflow.server.common.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* 自定义注解防止表单重复提交
|
||||
*
|
||||
* @author wangli
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface RepeatSubmit {
|
||||
/**
|
||||
* 间隔时间(ms),小于此时间视为重复提交
|
||||
*/
|
||||
int interval() default 5000;
|
||||
|
||||
/**
|
||||
* 提示消息
|
||||
*/
|
||||
String message() default "不允许重复提交,请稍后再试";
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
package cn.axzo.workflow.server.common.config;
|
||||
|
||||
import cn.axzo.workflow.server.common.intercepter.RepeatSubmitInterceptor;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* 通用配置
|
||||
*
|
||||
* @author wangli
|
||||
* @since 2023/12/9 22:18
|
||||
*/
|
||||
@Configuration
|
||||
public class ResourcesConfig implements WebMvcConfigurer {
|
||||
@Resource
|
||||
private RepeatSubmitInterceptor repeatSubmitInterceptor;
|
||||
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
registry.addInterceptor(repeatSubmitInterceptor).addPathPatterns("/**");
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,60 @@
|
||||
package cn.axzo.workflow.server.common.intercepter;
|
||||
|
||||
import cn.axzo.workflow.server.common.annotation.RepeatSubmit;
|
||||
import cn.azxo.framework.common.model.CommonResponse;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* 防止重复提交拦截器
|
||||
*
|
||||
* @author wangli
|
||||
*/
|
||||
@Component
|
||||
public abstract class RepeatSubmitInterceptor implements HandlerInterceptor {
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||
if (handler instanceof HandlerMethod) {
|
||||
HandlerMethod handlerMethod = (HandlerMethod) handler;
|
||||
Method method = handlerMethod.getMethod();
|
||||
RepeatSubmit annotation = method.getAnnotation(RepeatSubmit.class);
|
||||
if (annotation != null) {
|
||||
if (this.isRepeatSubmit(request, annotation)) {
|
||||
CommonResponse commonResponse = CommonResponse.error(annotation.message());
|
||||
renderString(response, JSON.toJSONString(commonResponse));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证是否重复提交由子类实现具体的防重复提交的规则
|
||||
*
|
||||
* @param request 请求对象
|
||||
* @param annotation 防复注解
|
||||
* @return 结果
|
||||
*/
|
||||
public abstract boolean isRepeatSubmit(HttpServletRequest request, RepeatSubmit annotation) throws Exception;
|
||||
|
||||
private static String renderString(HttpServletResponse response, String string) {
|
||||
try {
|
||||
response.setContentType("application/json");
|
||||
response.setCharacterEncoding("utf-8");
|
||||
response.getWriter().print(string);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,76 @@
|
||||
package cn.axzo.workflow.server.common.intercepter.impl;
|
||||
|
||||
import cn.axzo.workflow.server.common.annotation.RepeatSubmit;
|
||||
import cn.axzo.workflow.server.common.intercepter.RepeatSubmitInterceptor;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpSession;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 判断请求url和数据是否和上一次相同,
|
||||
* 如果和上次相同,则是重复提交表单。 有效时间为10秒内。
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Component
|
||||
public class SameUrlDataInterceptor extends RepeatSubmitInterceptor {
|
||||
public final String REPEAT_PARAMS = "repeatParams";
|
||||
|
||||
public final String REPEAT_TIME = "repeatTime";
|
||||
|
||||
public final String SESSION_REPEAT_KEY = "repeatData";
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public boolean isRepeatSubmit(HttpServletRequest request, RepeatSubmit annotation) throws Exception {
|
||||
// 本次参数及系统时间
|
||||
String nowParams = JSON.toJSONString(request.getParameterMap());
|
||||
Map<String, Object> nowDataMap = new HashMap<String, Object>();
|
||||
nowDataMap.put(REPEAT_PARAMS, nowParams);
|
||||
nowDataMap.put(REPEAT_TIME, System.currentTimeMillis());
|
||||
|
||||
// 请求地址(作为存放session的key值)
|
||||
String url = request.getRequestURI();
|
||||
|
||||
HttpSession session = request.getSession();
|
||||
Object sessionObj = session.getAttribute(SESSION_REPEAT_KEY);
|
||||
if (sessionObj != null) {
|
||||
Map<String, Object> sessionMap = (Map<String, Object>) sessionObj;
|
||||
if (sessionMap.containsKey(url)) {
|
||||
Map<String, Object> preDataMap = (Map<String, Object>) sessionMap.get(url);
|
||||
if (compareParams(nowDataMap, preDataMap) && compareTime(nowDataMap, preDataMap, annotation.interval())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
Map<String, Object> sessionMap = new HashMap<String, Object>();
|
||||
sessionMap.put(url, nowDataMap);
|
||||
session.setAttribute(SESSION_REPEAT_KEY, sessionMap);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断参数是否相同
|
||||
*/
|
||||
private boolean compareParams(Map<String, Object> nowMap, Map<String, Object> preMap) {
|
||||
String nowParams = (String) nowMap.get(REPEAT_PARAMS);
|
||||
String preParams = (String) preMap.get(REPEAT_PARAMS);
|
||||
return nowParams.equals(preParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断两次间隔时间
|
||||
*/
|
||||
private boolean compareTime(Map<String, Object> nowMap, Map<String, Object> preMap, int interval) {
|
||||
long time1 = (Long) nowMap.get(REPEAT_TIME);
|
||||
long time2 = (Long) preMap.get(REPEAT_TIME);
|
||||
if ((time1 - time2) < interval) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -3,6 +3,7 @@ package cn.axzo.workflow.server.controller.web;
|
||||
import cn.axzo.workflow.common.model.response.bpmn.process.ProcessNodeDetailVO;
|
||||
import cn.axzo.workflow.core.service.BpmnProcessInstanceService;
|
||||
import cn.axzo.workflow.core.service.support.FlowNodeForecastService;
|
||||
import cn.axzo.workflow.server.common.annotation.RepeatSubmit;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.flowable.bpmn.model.FlowElement;
|
||||
import org.flowable.common.engine.impl.util.IoUtil;
|
||||
@ -38,12 +39,14 @@ public class TestController {
|
||||
@Autowired
|
||||
private RepositoryService repositoryService;
|
||||
|
||||
@RepeatSubmit
|
||||
@GetMapping("/test")
|
||||
public void test(@RequestParam String processInstanceId) {
|
||||
List<FlowElement> flowElements = forecastService.performProcessForecasting(processInstanceId, null);
|
||||
System.out.println("flowElements = " + flowElements);
|
||||
}
|
||||
|
||||
@RepeatSubmit
|
||||
@GetMapping("/test2")
|
||||
public void test2(@RequestParam String processInstanceId) {
|
||||
List<ProcessNodeDetailVO> detailVOS = instanceService.getProcessInstanceNodeForecast(processInstanceId, "296");
|
||||
|
||||
@ -15,6 +15,7 @@ import cn.axzo.workflow.common.model.response.bpmn.task.BpmnTaskDonePageItemVO;
|
||||
import cn.axzo.workflow.common.model.response.bpmn.task.BpmnTaskInstanceVO;
|
||||
import cn.axzo.workflow.common.model.response.bpmn.task.BpmnTaskTodoPageItemVO;
|
||||
import cn.axzo.workflow.core.service.BpmnProcessTaskService;
|
||||
import cn.axzo.workflow.server.common.annotation.RepeatSubmit;
|
||||
import cn.azxo.framework.common.model.CommonResponse;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@ -71,6 +72,7 @@ public class BpmnProcessTaskController implements ProcessTaskApi {
|
||||
*/
|
||||
@PutMapping("/approve")
|
||||
@Override
|
||||
@RepeatSubmit
|
||||
public CommonResponse<Boolean> approveTask(@Validated @RequestBody BpmnTaskAuditDTO dto) {
|
||||
log.info("同意 approveTask===>>>参数:{}", dto);
|
||||
bpmnProcessTaskService.approveTask(dto);
|
||||
@ -82,6 +84,7 @@ public class BpmnProcessTaskController implements ProcessTaskApi {
|
||||
*/
|
||||
@PutMapping("/reject")
|
||||
@Override
|
||||
@RepeatSubmit
|
||||
public CommonResponse<Boolean> rejectTask(@Validated @RequestBody BpmnTaskAuditDTO dto) {
|
||||
log.info("驳回 rejectTask===>>>参数:{}", dto);
|
||||
bpmnProcessTaskService.rejectTask(dto);
|
||||
@ -94,6 +97,7 @@ public class BpmnProcessTaskController implements ProcessTaskApi {
|
||||
@Operation(summary = "直接修改审批任务的审批人")
|
||||
@PutMapping("/transfer")
|
||||
@Override
|
||||
@RepeatSubmit
|
||||
public CommonResponse<Boolean> transferTask(@Validated @RequestBody BpmnTaskAssigneeDTO dto) {
|
||||
bpmnProcessTaskService.transferTask(dto);
|
||||
return success(true);
|
||||
@ -102,7 +106,10 @@ public class BpmnProcessTaskController implements ProcessTaskApi {
|
||||
/**
|
||||
* 评论
|
||||
*/
|
||||
@Operation(summary = "审批流程评论")
|
||||
@PutMapping("/comment")
|
||||
@Override
|
||||
@RepeatSubmit
|
||||
public CommonResponse<Boolean> commentTask(@Validated @RequestBody BpmnTaskCommentDTO commentDTO) {
|
||||
bpmnProcessTaskService.commentTask(commentDTO);
|
||||
return success(true);
|
||||
@ -112,40 +119,30 @@ public class BpmnProcessTaskController implements ProcessTaskApi {
|
||||
/**
|
||||
* 加签
|
||||
*/
|
||||
@Operation(summary = "审批任务加签")
|
||||
@Override
|
||||
@PutMapping("/countersign")
|
||||
@RepeatSubmit
|
||||
public CommonResponse<Boolean> countersignTask(@Validated @RequestBody BpmnTaskCountersignDTO countersignDTO) {
|
||||
bpmnProcessTaskService.countersignTask(countersignDTO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 催办
|
||||
*
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
@Operation(summary = "审批流程催办")
|
||||
@PutMapping("/api/process/task/remind")
|
||||
@Override
|
||||
@RepeatSubmit
|
||||
public CommonResponse<Boolean> remindTask(@Validated @RequestBody BpmnTaskRemindDTO dto) {
|
||||
bpmnProcessTaskService.remindTask(dto);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public CommonResponse<Boolean> copyTask(BpmnTaskAssigneeDTO dto) {
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public CommonResponse<Boolean> rollbackTask(BpmnTaskAssigneeDTO dto) {
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public CommonResponse<Boolean> revocationTask(BpmnTaskAssigneeDTO dto) {
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public CommonResponse<Boolean> remindTask(BpmnTaskAssigneeDTO dto) {
|
||||
// return null;
|
||||
// }
|
||||
|
||||
|
||||
/**
|
||||
* 获取指定流程实例的审批过程信息
|
||||
* <p>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user