SpringBoot手動取消介面執行方案

code2roc發表於2024-03-26

實際開發中經常會遇到比較耗時的介面操作,但頁面強制重新整理或主動取消介面呼叫後後臺還是會繼續執行,特別是有大量資料庫操作時會增加伺服器壓力,所以進行研究測試後總結了一套主動取消介面呼叫的解決方案

自定義註解用於標記耗時介面

@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;
    }

相關文章