千家信息网

Java中Servelt3异步请求方式是什么

发表于:2026-11-03 作者:千家信息网编辑
千家信息网最后更新 2026年11月03日,本篇内容介绍了"Java中Servelt3异步请求方式是什么"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有
千家信息网最后更新 2026年11月03日Java中Servelt3异步请求方式是什么

本篇内容介绍了"Java中Servelt3异步请求方式是什么"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

用同步请求模型,所有动作都交给同一个 Tomcat 线程处理,所有动作处理完成,线程才会被释放回线程池。

想象一下如果业务需要较长时间处理,那么这个 Tomcat 线程其实一直在被占用,随着请求越来越多,可用 I/O 线程越来越少,直到被耗尽。这时后续请求只能等待空闲 Tomcat 线程,这将会加长了请求执行时间。

如果客户端不关心返回业务结果,这时我们可以自定义线程池,将请求任务提交给线程池,然后立刻返回。

也可以使用 Spring Async 任务,大家感兴趣可以自行查找一下资料

但是很多场景下,客户端需要处理返回结果,我们没办法使用上面的方案。在 Servlet2 时代,我们没办法优化上面的方案。

不过等到 Servlet3 ,引入异步 Servlet 新特性,可以完美解决上面的需求。

异步 Servlet 执行请求流程:

将请求信息解析为 HttpServletRequest

分发到具体 Servlet 处理,将业务提交给自定义业务线程池,请求立刻返回,Tomcat 线程立刻被释放

当业务线程将任务执行结束,将会将结果转交给 Tomcat 线程

通过 HttpServletResponse 将响应结果返回给等待客户端

引入异步 Servlet3 整体流程如下:

使用异步 Servelt,Tomcat 线程仅仅处理请求解析动作,所有耗时较长的业务操作全部交给业务线程池,所以相比同步请求, Tomcat 线程可以处理 更多请求。

虽然我们将业务处理交给业务线程池异步处理,但是对于客户端来讲,其还在同步等待响应结果。

可能有些同学会觉得异步请求将会获得更快响应时间,其实不是的,相反可能由于引入了更多线程,增加线程上下文切换时间。

虽然没有降低响应时间,但是通过请求异步化带来其他明显优点:

  • 可以处理更高并发连接数,提高系统整体吞吐量

  • 请求解析与业务处理完全分离,职责单一

  • 自定义业务线程池,我们可以更容易对其监控,降级等处理

  • 可以根据不同业务,自定义不同线程池,相互隔离,不用互相影响

所以具体使用过程,我们还需要进行的相应的压测,观察响应时间以及吞吐量等其他指标,综合选择。

异步 Servelt 使用方式

异步 Servelt 使用方式不是很难,阿粉总结就是下面三板斧:

  1. HttpServletRequest#startAsync 获取 AsyncContext 异步上下文对象

  2. 使用自定义的业务线程池处理业务逻辑

  3. 业务线程处理结束,通过 AsyncContext#complete 返回响应结果

下面的例子将会使用 SpringBoot ,Web 容器选择 Tomcat

示例代码如下:

ExecutorService executorService = Executors.newFixedThreadPool(10);  @RequestMapping("/hello") public void hello(HttpServletRequest request) {     AsyncContext asyncContext = request.startAsync();     // 超时时间     asyncContext.setTimeout(10000);     executorService.submit(() -> {         try {             // 休眠 5s,模拟业务操作             TimeUnit.SECONDS.sleep(5);             // 输出响应结果             asyncContext.getResponse().getWriter().println("hello world");             log.info("异步线程处理结束");         } catch (Exception e) {             e.printStackTrace();         } finally {             asyncContext.complete();         }     });     log.info("servlet 线程处理结束"); }

浏览器访问该请求将会同步等待 5s 得到输出响应,应用日志输出结果如下:

2020-03-24 07:27:08.997  INFO 79257 --- [nio-8087-exec-4] com.xxxx   : servlet 线程处理结束 2020-03-24 07:27:13.998  INFO 79257 --- [pool-1-thread-3] com.xxxx   : 异步线程处理结束

这里我们需要注意设置合理的超时时间,防止客户端长时间等待。

SpringMVC

Servlet3 API ,无法使用 SpringMVC 为我们提供的特性,我们需要自己处理响应信息,处理方式相对繁琐。

SpringMVC 3.2 基于 Servelt3 引入异步请求处理方式,我们可以跟使用同步请求一样,方便使用异步请求。

SpringMVC 提供有两种异步方式,只要将 Controller 方法返回值修改下述类即可:

  • DeferredResult

  • Callable

DeferredResult

DeferredResult 是 SpringMVC 3.2 之后引入新的类,只要让请求方法返回DeferredResult,就可以快速使用异步请求,示例代码如下:

ExecutorService executorService = Executors.newFixedThreadPool(10);  @RequestMapping("/hello_v1") public DeferredResult hello_v1() {     // 设置超时时间     DeferredResult deferredResult = new DeferredResult<>(7000L);     // 异步线程处理结束,将会执行该回调方法     deferredResult.onCompletion(() -> {         log.info("异步线程处理结束");     });     // 如果异步线程执行时间超过设置超时时间,将会执行该回调方法     deferredResult.onTimeout(() -> {         log.info("异步线程超时");         // 设置返回结果         deferredResult.setErrorResult("timeout error");     });     deferredResult.onError(throwable -> {         log.error("异常", throwable);         // 设置返回结果         deferredResult.setErrorResult("other error");     });     executorService.submit(() -> {         try {             TimeUnit.SECONDS.sleep(5);             deferredResult.setResult("hello_v1");             // 设置返回结果         } catch (Exception e) {             e.printStackTrace();             // 若异步方法内部异常             deferredResult.setErrorResult("error");         }     });     log.info("servlet 线程处理结束");     return deferredResult;  }

创建 DeferredResult 实例时可以传入特定超时时间。另外我们可以设置默认超时时间:

# 异步请求超时时间 spring.mvc.async.request-timeout=2000

如果异步程序执行完成,可以调用 DeferredResult#setResult返回响应结果。此时若有设置 DeferredResult#onCompletion 回调方法,将会触发该回调方法。

同时我们还可以设置超时回调方法 DeferredResult#onTimeout,一旦异步线程执行超时,将会触发该回调方法。

最后 DeferredResult 还提供其他异常的回调方法 onError,起初阿粉以为只要异步线程内发生异常,就会触发该回调方法。尝试在异步线程内抛出异常,但是无法成功触发。

后续阿粉查看这个方法的 doc,当 web 容器线程处理异步请求时发生异常,才能成功触发。

Callable

Spring 另外还提供一种异步请求使用方式,直接使用 JDK Callable。示例代码如下:

@RequestMapping("/hello_v2") public Callable hello_v2() {     return new Callable() {         @Override         public String call() throws Exception {             TimeUnit.SECONDS.sleep(5);             log.info("异步方法结束");             return "hello_v2";         }     }; }

默认情况下,直接执行将会输出 WARN 日志

这是因为默认情况使用 SimpleAsyncTaskExecutor 执行异步请求,每次调用执行都将会新建线程。由于这种方式不复用线程,生产不推荐使用这种方式,所以我们需要使用线程池代替。

我们可以使用如下方式自定义线程池:

@Bean(TaskExecutionAutoConfiguration.APPLICATION_TASK_EXECUTOR_BEAN_NAME) public AsyncTaskExecutor executor() {     ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();     threadPoolTaskExecutor.setThreadNamePrefix("test-");     threadPoolTaskExecutor.setCorePoolSize(10);     threadPoolTaskExecutor.setMaxPoolSize(20);     return threadPoolTaskExecutor; }

注意 Bean 名称一定要是 applicationTaskExecutor,若不一致, Spring 将不会使用自定义线程池。

或者可以直接使用 SpringBoot 配置文件方式配置代替:

# 核心线程数 spring.task.execution.pool.core-size=10 # 最大线程数 spring.task.execution.pool.max-size=20 # 线程名前缀 spring.task.execution.thread-name-prefix=test # 还有另外一些配置,读者们可以自行配置

这种方式异步请求的超时时间只能通过配置文件方式配置。

spring.mvc.async.request-timeout=10000

如果需要为单独请求的配置特定的超时时间,我们需要使用 WebAsyncTask 包装 Callable 。

@RequestMapping("/hello_v3") public WebAsyncTask hello_v3() {     System.out.println("asdas");     Callable callable=new Callable() {         @Override         public String call() throws Exception {             TimeUnit.SECONDS.sleep(5);             log.info("异步方法结束");             return "hello_v3";         }     };     // 单位 ms     WebAsyncTask webAsyncTask=new WebAsyncTask<>(10000,callable);     return webAsyncTask; }

"Java中Servelt3异步请求方式是什么"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!

线程 处理 业务 时间 方式 方法 结果 配置 客户 客户端 输出 更多 面的 同步 代码 任务 动作 情况 示例 不同 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 花魁咖啡 互联网新科技 广东猪兼强互联网科技有限公司 A股互联网金融科技公司 工业互联网科技新基建 互联网科技的 广州互联网科技公司 唐信互联网科技 大连 互联网科技网站 互联网科技股午盘股票涨跌 玖二柒互联网科技公司待遇 北京三清互联网科技 北京华百购互联网科技有限公司 互联网系的金融科技公司 互联网为啥属于高科技 彤创互联网科技有限公司 花神(南京)互联网科技有限公司 张家口科技产业互联网平台 数字科技和互联网金融哪个好 株洲百竞科技的互联网营销顾问 广州紫鲸互联网科技 多迪互联网科技有限公司 青海省互联网新科技 语蝶互联网科技有限公司 中国航天科技大学国际工业互联网 互联网行业科技股 国大互联网教育科技有限公司薪资 杭州披云加互联网科技有限公司 美国五大互联网科技公司市值多少 黑龙江互联网科技公司
0