我们先来看一下一个请求到Tomcat是怎么处理的
一个请求到达Tomcat后,便会分配tomcat中的一个线程去处理这个请求,但是,Tomcat中的请求是有限的,如果业务请求耗时过长,导致Tomcat中的线程一直被占用,最终导致用户的请求无法被tomcat处理,严重影响业务,如果说一个请求到了业务层之后,可以释放掉Tomcat中的线程,那么就可以解决这个问题了,Servlet异步请求便是实现了这个功能,我么来简单的看一个demo
@RestController@RequestMapping("async")public class AsyncController { @Autowired private AsyncService asyncService; @RequestMapping("getStudent") public void getStudent(Long id, HttpServletRequest request) { asyncService.getAsyncStudent(id, request); }}@Servicepublic class AsyncService { @Autowired private StudentDao studentDao; private ThreadPoolExecutor executor = new ThreadPoolExecutor(4, 8, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(100)); public void getAsyncStudent(Long id, HttpServletRequest request) { // 异步请求,释放Tomcat线程 AsyncContext asyncContext = request.startAsync(); // 通过线程池创建异步任务,将耗时的操作放到线程中执行 executor.submit(new AsyncTask(asyncContext, id)); } public class AsyncTask implements Runnable { private AsyncContext asyncContext; private Long id; public AsyncTask(AsyncContext asyncContext, Long id) { this.asyncContext = asyncContext; this.id = id; } @Override public void run() { // 执行耗时操作 Student student = studentDao.getStudent(id); // 获取response ServletResponse response = asyncContext.getResponse(); // 直接将结果通过response返回 ResponseUtils.generatorResponse((HttpServletResponse) response, student); // 请求完成 asyncContext.complete(); } }}@Slf4jpublic class ResponseUtils { public static final void generatorResponse(HttpServletResponse response, Object data) { generatorResponseString(response, JSON.toJSONString(data)); } public static final void generatorResponseString(HttpServletResponse response, String data) { try { response.setHeader("Pragma", "no-cache"); response.setDateHeader("Expires", 0); response.setHeader("Cache-Control", "no-cache,no-store"); //json格式 response.setContentType("application/json;charset=UTF-8"); response.setStatus(HttpServletResponse.SC_OK); response.getWriter().println(data); } catch (Exception e) { log.error("返回结果出现异常", e); } }}通过示例我们发现,Servlet实现异步请求还是很简单的,第一步,我们只需要调用request.startAsync()将请求异步,然后执行业务请求获取对应的结果,最后将请求的结果通过response返回给客户端。
我们再来看一下Spring支持的异步请求
@RestController@RequestMapping("spring/async")public class SpringAsyncController { @Autowired private SpringAsyncService springAsyncService; @RequestMapping("getStudent") public DeferredResult getStudent(Long id) { DeferredResult deferredResult = new DeferredResult<>(); springAsyncService.getAsyncStudent(id, deferredResult); return deferredResult; }}@Servicepublic class SpringAsyncService { @Autowired private StudentDao studentDao; private ThreadPoolExecutor executor = new ThreadPoolExecutor(4, 8, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(100)); public void getAsyncStudent(Long id, DeferredResult deferredResult) { // 异步请求 executor.submit(() -> { Student student = studentDao.getStudent(id); // 将请求结果返回 deferredResult.setResult(student); }); }} | 留言与评论(共有 0 条评论) “” |