SpringBoot手动取消接口执行方案

实际开发中经常会遇到比较耗时的接口操作,但页面强制刷新或主动取消接口调用后后台还是会继续运行,特别是有大量数据库操作时会增加服务器压力,所以进行研究测试后总结了一套主动取消接口调用的解决方案

自定义注解用于标记耗时接口

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Inherited
public @interface HandleCancel {
}

自定义切面对注解的接口调用线程进行记录

@Aspect
@Component
public class HandleCacelAspect {

    @Pointcut("@annotation(org.springframework.web.bind.annotation.PostMapping) " +
            "|| @within(org.springframework.web.bind.annotation.PostMapping)"+
            "@annotation(org.springframework.web.bind.annotation.GetMapping) " +
            "|| @within(org.springframework.web.bind.annotation.GetMapping)")
    public void handleCacelAspect() {

    }

    @Around("handleCacelAspect()")
    public Object around(ProceedingJoinPoint point) throws Throwable {

        boolean handleCacel = false;
        Object result = null;
        try{
            HandleCancel handleCancelAnnotation = method.getAnnotation(HandleCancel.class);
            if (handleCancelAnnotation != null) {
                handleCacel = true;
            }
            if(handleCacel){
                //这里将对应的耗时接口请求线程名称和token关联存储到redis中,请安实际情况编写
                TokenModel userModel = authService.getTokenModel();
                userModel.addThread(Thread.currentThread().getName());
                authService.updateToken(authService.getTokenString(),userModel);
            }
             result = point.proceed();
        }finally {
            if(handleCacel){
                //这里在耗时接口执行完毕后删除对应存储的线程名称,请安实际情况编写
                TokenModel userModel = authService.getTokenModel();
                userModel.removeThread(Thread.currentThread().getName());
                authService.updateToken(authService.getTokenString(),userModel);
            }
        }

        return result;
    }
}

提供统一取消调用的接口

    @PostMapping("/killUserHandleThread")
    @ResponseBody
    public Object killUserHandleThread(@RequestBody Map<String, Object> params) {
        Result result = Result.okResult();
        TokenModel userModel = authService.getTokenModel();
        List<String> threadNameList = userModel.getThreadList();

        ThreadGroup currentGroup = Thread.currentThread().getThreadGroup();
        int noThreads = currentGroup.activeCount();
        Thread[] lstThreads = new Thread[noThreads];
        currentGroup.enumerate(lstThreads);

        for (int i = 0; i < noThreads; i++) {
            String threadName = lstThreads[i].getName();
            if (threadNameList.contains(threadName)) {
                System.out.println("中断线程:" + threadName);
                lstThreads[i].interrupt();
                userModel.removeThread(threadName);
                authService.updateToken(authService.getTokenString(),userModel);
            }
        }
        return result;
    }

热门相关:我真的是正派   甜蜜婚令:首长的影后娇妻   寒门状元   来自异世界的诺诺   世界第一校长