Spring MVC异步请求Controller
Opened this issue · 0 comments
v5tech commented
AsyncTaskService 模拟后台耗时请求业务
import org.joda.time.LocalDateTime;
import org.springframework.stereotype.Service;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
@Service
public class AsyncTaskService {
public String uuid() {
try {
TimeUnit.MILLISECONDS.sleep(5000);
System.out.println(LocalDateTime.now().toString("yyyy-MM-dd HH:mm:ss:S") + "--->工作线程(" + Thread.currentThread().getName() + ")");
} catch (InterruptedException e) {
e.printStackTrace();
}
return UUID.randomUUID().toString();
}
}
AsyncController 异步请求几种写法
import org.joda.time.LocalDateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.util.concurrent.ListenableFutureTask;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.async.DeferredResult;
import org.springframework.web.context.request.async.WebAsyncTask;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 异步Controller
*/
@RestController
@EnableAsync
public class AsyncController {
@Autowired
private AsyncTaskService asyncTaskService;
/**
* 阻塞请求
* @return
*/
@GetMapping("blockingRequest")
public String blockingRequest() {
System.out.println(LocalDateTime.now().toString("yyyy-MM-dd HH:mm:ss:S") + "--->主线程开始");
String uuid = asyncTaskService.uuid();
System.out.println(LocalDateTime.now().toString("yyyy-MM-dd HH:mm:ss:S") + "--->主线程结束");
return uuid;
}
/**
* 使用Callable
* @return
*/
@GetMapping("callable")
public Callable<String> callable() {
System.out.println(LocalDateTime.now().toString("yyyy-MM-dd HH:mm:ss:S") + "--->主线程开始");
Callable<String> callable = () -> {
String uuid = asyncTaskService.uuid();
System.out.println(LocalDateTime.now().toString("yyyy-MM-dd HH:mm:ss:S") + "--->子任务线程("+Thread.currentThread().getName()+")");
return uuid;
};
System.out.println(LocalDateTime.now().toString("yyyy-MM-dd HH:mm:ss:S") + "--->主线程结束");
return callable;
}
/**
* 使用CompletableFuture
*
* 使用该方式时,切记自己创建执行器,不要使用内置的 ForkJoinPool线程池,会有性能问题
*
* @return
*/
@GetMapping("completableFuture")
public CompletableFuture<String> completableFuture() {
ExecutorService executor = Executors.newCachedThreadPool();
System.out.println(LocalDateTime.now().toString("yyyy-MM-dd HH:mm:ss:S") + "--->主线程开始");
CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(asyncTaskService::uuid,executor);
System.out.println(LocalDateTime.now().toString("yyyy-MM-dd HH:mm:ss:S") + "--->主线程结束");
return completableFuture;
}
/**
* 使用ListenableFuture
*
* 使用该方式时,切记自己创建执行器,不要使用内置的 ForkJoinPool线程池,会有性能问题
*
* @return
*/
@GetMapping("listenableFuture")
public ListenableFuture<String> listenableFuture() {
System.out.println(LocalDateTime.now().toString("yyyy-MM-dd HH:mm:ss:S") + "--->主线程开始");
ListenableFutureTask<String> listenableFuture = new ListenableFutureTask<>(()-> asyncTaskService.uuid());
Executors.newCachedThreadPool().execute(listenableFuture);
System.out.println(LocalDateTime.now().toString("yyyy-MM-dd HH:mm:ss:S") + "--->主线程结束");
return listenableFuture;
}
/**
* 使用WebAsyncTask
* @return
*/
@GetMapping("asynctask")
public WebAsyncTask asyncTask() {
SimpleAsyncTaskExecutor executor = new SimpleAsyncTaskExecutor();
System.out.println(LocalDateTime.now().toString("yyyy-MM-dd HH:mm:ss:S") + "--->主线程开始");
WebAsyncTask<String> task = new WebAsyncTask(10000L, executor, ()-> asyncTaskService.uuid());
task.onCompletion(()->{
System.out.println(LocalDateTime.now().toString("yyyy-MM-dd HH:mm:ss:S") + "--->调用完成");
});
task.onTimeout(()->{
System.out.println("onTimeout");
return "onTimeout";
});
System.out.println(LocalDateTime.now().toString("yyyy-MM-dd HH:mm:ss:S") + "--->主线程结束");
return task;
}
/**
* 使用DeferredResult
* @return
*/
@GetMapping("deferredResult")
public DeferredResult<String> deferredResult() {
System.out.println(LocalDateTime.now().toString("yyyy-MM-dd HH:mm:ss:S") + "--->主线程("+Thread.currentThread().getName()+")开始");
DeferredResult<String> deferredResult = new DeferredResult<>();
CompletableFuture.supplyAsync(()->{
String uuid = asyncTaskService.uuid();
// int abc = 2/0;
return uuid;
}, Executors.newFixedThreadPool(5)).whenCompleteAsync((result,throwable)->{
if (throwable!=null) {
deferredResult.setErrorResult(throwable.getMessage());
}else {
deferredResult.setResult(result);
}
});
// 异步请求超时时调用
deferredResult.onTimeout(()->{
System.out.println(LocalDateTime.now().toString("yyyy-MM-dd HH:mm:ss:S") + "--->onTimeout");
});
// 异步请求完成后调用
deferredResult.onCompletion(()->{
System.out.println(LocalDateTime.now().toString("yyyy-MM-dd HH:mm:ss:S") + "--->onCompletion");
});
System.out.println(LocalDateTime.now().toString("yyyy-MM-dd HH:mm:ss:S") + "--->主线程("+Thread.currentThread().getName()+")结束");
return deferredResult;
}
}
参考文档
https://www.javacodegeeks.com/2015/07/understanding-callable-and-spring-deferredresult.html
https://nickebbitt.github.io/blog/2017/03/22/async-web-service-using-completable-future