update - 优化重复提交注解,以支持动态配置,默认的防重提交时间为 5秒

This commit is contained in:
wangli 2024-01-19 17:08:00 +08:00
parent b46466d583
commit 60125059aa
7 changed files with 64 additions and 5 deletions

View File

@ -22,7 +22,9 @@ public @interface RepeatSubmit {
/**
* 间隔时间(ms)小于此时间视为重复提交
*/
int interval() default 3000;
int interval() default 5000;
String intervalExpression() default "${workflow.repeatSubmit.interval}";
TimeUnit timeUnit() default TimeUnit.MILLISECONDS;

View File

@ -2,6 +2,7 @@ package cn.axzo.workflow.server.common.aspectj;
import cn.axzo.workflow.core.common.exception.WorkflowEngineException;
import cn.axzo.workflow.server.common.annotation.RepeatSubmit;
import cn.axzo.workflow.server.common.config.RepeatSubmitResolver;
import cn.axzo.workflow.server.common.util.RedisUtils;
import cn.azxo.framework.common.model.CommonResponse;
import cn.hutool.core.util.ArrayUtil;
@ -9,11 +10,13 @@ import cn.hutool.core.util.ObjectUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.http.HttpStatus;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindingResult;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
@ -34,17 +37,24 @@ import static cn.axzo.workflow.core.common.code.OtherRespCode.REPEAT_SUBMIT_TIME
*
* @author wangli
*/
@Component
@Aspect
@Slf4j
public class RepeatSubmitAspect {
private final RepeatSubmitResolver repeatSubmitResolver;
private static final ThreadLocal<String> KEY_CACHE = new ThreadLocal<>();
private static final String REPEAT_SUBMIT_KEY = "global:repeat_submit:";
public RepeatSubmitAspect(RepeatSubmitResolver repeatSubmitResolver) {this.repeatSubmitResolver =
repeatSubmitResolver;}
@Before("@annotation(repeatSubmit)")
public void doBefore(JoinPoint point, RepeatSubmit repeatSubmit) throws Throwable {
// 如果注解不为0 则使用注解数值
long interval = repeatSubmit.timeUnit().toMillis(repeatSubmit.interval());
// 获取注解中的 SpEL 表达式
interval = repeatSubmitResolver.resolveExpression(repeatSubmit.intervalExpression(), interval);
log.info("interval: {}", interval);
if (interval < 1000) {
throw new WorkflowEngineException(REPEAT_SUBMIT_TIME_ERROR_TIPS,
String.valueOf((repeatSubmit.interval() / 1000)));

View File

@ -70,8 +70,8 @@ public class RedisConfiguration {
public static class IdempotentAutoConfiguration {
@Bean
public RepeatSubmitAspect repeatSubmitAspect() {
return new RepeatSubmitAspect();
public RepeatSubmitAspect repeatSubmitAspect(RepeatSubmitResolver resolver) {
return new RepeatSubmitAspect(resolver);
}
}

View File

@ -0,0 +1,40 @@
package cn.axzo.workflow.server.common.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import java.util.Objects;
/**
* 重复提交的时间参数动态处理
*
* @author wangli
* @since 2024/1/19 16:49
*/
@Component
@RefreshScope
@Slf4j
public class RepeatSubmitResolver {
private final Environment environment;
public RepeatSubmitResolver(Environment environment) {this.environment = environment;}
public long resolveExpression(String expression, long interval) {
// 使用 Environment 解析表达式
String resolved = environment.resolvePlaceholders(expression);
try {
if (Objects.equals("${workflow.repeatSubmit.interval}", resolved)) {
return interval;
}
return Integer.parseInt(resolved);
} catch (NumberFormatException e) {
// 处理异常或使用默认值
log.error("@RepeatSubmit 注解的 intervalExpression 属性请使用 Spel 表达式获取环境变量中的超时时间配置, 当前的表达式存在问题, 以使用默认的超时时间, " +
"Spel= {}", expression);
return interval; // 默认值
}
}
}

View File

@ -138,6 +138,7 @@ public class BpmnProcessInstanceController implements ProcessInstanceApi {
*/
@GetMapping("/get")
@Override
@RepeatSubmit
public CommonResponse<BpmnProcessInstanceVO> getProcessInstanceVO(@Validated @RequestBody BpmnProcessInstanceQueryDTO dto) {
log.info("获得历史的流程实例 getProcessInstanceVO===>>>参数:{}", JSON.toJSONString(dto));
BpmnProcessInstanceVO result = bpmnProcessInstanceService.getProcessInstanceVO(dto);

View File

@ -10,6 +10,7 @@ import cn.axzo.workflow.common.model.response.bpmn.model.BpmnModelDetailVO;
import cn.axzo.workflow.common.model.response.bpmn.model.BpmnModelExtVO;
import cn.axzo.workflow.core.service.BpmnProcessModelService;
import cn.axzo.workflow.core.service.ExtAxReModelService;
import cn.axzo.workflow.server.common.annotation.RepeatSubmit;
import cn.azxo.framework.common.model.CommonResponse;
import com.alibaba.fastjson.JSON;
import io.swagger.v3.oas.annotations.Operation;
@ -66,6 +67,7 @@ public class BpmnProcessModelController implements ProcessModelApi {
@Operation(summary = "创建流程模型")
@PostMapping("/create")
@Override
@RepeatSubmit
public CommonResponse<String> create(@Validated @RequestBody BpmnModelCreateDTO dto) {
log.info("创建流程createBpmModel===>>>参数:{}", JSON.toJSONString(dto));
String result = bpmnProcessModelService.createBpmModel(dto);

View File

@ -11,6 +11,7 @@ import cn.axzo.workflow.common.model.response.category.CategoryConfigItemVO;
import cn.axzo.workflow.common.model.response.category.CategoryItemVO;
import cn.axzo.workflow.core.service.CategoryConfigService;
import cn.axzo.workflow.core.service.CategoryService;
import cn.axzo.workflow.server.common.annotation.RepeatSubmit;
import cn.azxo.framework.common.model.CommonResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
@ -90,6 +91,7 @@ public class ProcessCategoryController implements ProcessCategoryApi {
*/
@PostMapping("/create")
@Override
@RepeatSubmit
public CommonResponse<CategoryItemVO> create(@Validated @RequestBody CategoryCreateDTO req) {
return success(categoryService.createCategory(req));
}
@ -113,6 +115,7 @@ public class ProcessCategoryController implements ProcessCategoryApi {
*/
@DeleteMapping("/delete")
@Override
@RepeatSubmit
public CommonResponse<Boolean> delete(Long id) {
categoryService.deleteCategory(id);
return success(true);
@ -148,6 +151,7 @@ public class ProcessCategoryController implements ProcessCategoryApi {
*/
@PostMapping("/config/create")
@Override
@RepeatSubmit
public CommonResponse<Boolean> createConfig(@Validated @RequestBody CategoryConfigCreateDTO dto) {
categoryConfigService.create(dto);
return success(true);