實際開發中經常會遇到比較耗時的介面操作,但頁面強制重新整理或主動取消介面呼叫後後臺還是會繼續執行,特別是有大量資料庫操作時會增加伺服器壓力,所以進行研究測試後總結了一套主動取消介面呼叫的解決方案
自定義註解用於標記耗時介面
@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;
}