浅谈servlet3异步原理与实践

浅谈servlet3异步原理与实践

什么是Servlet3异步

Servlet3.0规范中增加了异步处理的功能,使Servlet容器的性能可以进一步提升。Servlet3.0之前,servlet都是由线程来处理的,每次请求都需要创建一个线程,处理完请求后才会销毁这个线程。如果请求量很大,反复创建销毁线程的过程会给服务器造成很大负担。

而异步Servlet能够处理复杂和耗时的操作,而不用将请求交给固定的线程进行处理。异步Servlet通过启用一个线程来处理某个请求,然后在到达I/O操作之前将控制权交回到Servlet容器。这样一来,线程便得到释放,不会阻塞应用程序的其他部分,最终提高了整个应用程序的性能。

Servlet3异步实现代码

在Servlet3中,异步处理需要先调用 AsyncContextstartAsync() 方法来开启异步模式。

接下来我们来看一个使用异步的Servlet示例:

@WebServlet("/asyncServlet")
public class AsyncServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        final AsyncContext asyncContext = req.startAsync();
        asyncContext.setTimeout(30_000L);
        asyncContext.start(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(5_000L);
                    PrintWriter writer = asyncContext.getResponse().getWriter();
                    writer.println("Hello, World!");
                    writer.flush();
                    asyncContext.complete();
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
        });
    }
}

在上面的代码中,当客户端访问 /asyncServlet 地址时,服务器会将请求交由 HttpServlet处理。正如之前解释的那样,在代码中我们需要调用 startAsync() 来开启异步模式。

接下来,我们在异步 Servlet 中创建一个新的线程(我们使用Java的 Lambda 表达式实现 Runnable 的 run() 方法),并在这个线程中处理请求。在这个例子中,我们让线程休眠5秒钟,然后再向客户端返回“Hello, World!”的消息。

最后调用 complete() 方法来告知Servlet容器这个请求已经处理完毕。GetMethod实例处理不会刷新并提交响应。

进阶使用

除了在 doGet() 里创建异步上下文之外,还可以在 doPost() 或者 doPut() 里使用异步上下文。如果你希望有多个异步操作,你可以创建多个 Runnable 的实例,并使用多个线程并行工作,从而快速响应客户端。

示例二

@WebServlet("/asyncServlet")
public class AsyncServlet extends HttpServlet {      
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        AsyncContext asyncContext = req.startAsync();
        asyncContext.setTimeout(9000); //设置异步上下文的超时时间
        asyncContext.addListener(new AsyncListener() { 
            @Override
            public void onComplete(AsyncEvent asyncEvent) throws IOException, ServletException {
                LOG.info("执行 onComplete 方法. ");
            }

            @Override
            public void onError(AsyncEvent asyncEvent) throws IOException, ServletException {
                LOG.info("执行 onError 方法 time={}", System.currentTimeMillis());
            }

            @Override
            public void onTimeout(AsyncEvent asyncEvent) throws IOException, ServletException {
                LOG.info("执行 onTimeout 方法 time={}", System.currentTimeMillis());
            }

            @Override
            public void onStartAsync(AsyncEvent asyncEvent) throws IOException, ServletException {
                LOG.info("执行 onStartAsync 方法 time={}", System.currentTimeMillis());
            }
        });
        asyncContext.start(new Runnable() {
            @Override
            public void run() {
                //模拟一个阻塞操作
                try {
                    Thread.sleep(8000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //触发OnComplete事件
                asyncContext.complete(); 
            }
        });   
    }
}

在这个示例中,我们使用了 addListener() 方法来添加多个异步事件的监听器。如果我们在 AsyncServlet 内部执行一个耗时长的操作,例如等待另一个远程服务返回数据,我们需要将超时时间设置的长一些,否则异步 Operaion 会超时导致失败。所以在代码中,我们将超时时间设置为了 9 秒。

最终,在异步完成后, AsyncListener#onComplete() 方法会被调用。如果异步 Operation 超时, AsyncListener#onTimeout() 方法会被调用。

总结

到此,我们就详细讲解了 Servlet 3 异步处理的基本原理和实现,在实际开发中,使用异步能够有效的提升服务器的响应速度,节省服务器资源,加速系统的处理速度。为了防止超时,我们需要灵活的设置超时时间,并为异步事件添加监听器,以便及时发现并处理回调事件。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:浅谈servlet3异步原理与实践 - Python技术站

(0)
上一篇 2023年5月20日
下一篇 2023年5月20日

相关文章

  • SpringBoot如何接收前端传来的json数据

    Spring Boot 提供了多种方式用于接收前端传来的 JSON 数据,包括但不限于以下两种常见方式: 使用 @RequestBody 注解 使用 @RequestBody 注解可以将前端传来的 JSON 数据直接转换为 Java 对象。具体操作如下: (1)在控制器中添加 @PostMapping 注解,并指定请求路径。比如: @PostMapping(…

    Java 2023年5月26日
    00
  • Java图像处理之获取用户感兴趣的区域

    下面是Java图像处理之获取用户感兴趣的区域的完整攻略。 1. 确定用户感兴趣的区域 首先需要进行的是确定用户感兴趣的区域,这可以通过鼠标点击的方式来实现。具体的流程如下: 首先需要引用Java图形处理的库,例如JavaFX等。 创建一个可视化界面,并在界面上用ImageView组件展示原始图片。 监听ImageView的鼠标点击事件,获取鼠标点击的坐标,然…

    Java 2023年5月19日
    00
  • Java循环队列原理与用法详解

    Java循环队列原理与用法详解 什么是循环队列 循环队列是一种经典的队列实现方式,它的特点是:队列的头尾相连,形成了一个环形结构。当队列满时,新的数据会从队列头部开始覆盖旧的数据。因此,循环队列在使用过程中,需要记录队列的头部和尾部指针,以便能够正确地判断队列是空还是满,以及在队列中添加、删除元素时,正确地定位到队列的头部和尾部。 基本实现方法 在Java中…

    Java 2023年5月26日
    00
  • Java利用套接字实现应用程序对数据库的访问

    Java利用套接字实现应用程序对数据库的访问,需要经过以下步骤: 配置数据库信息:在Java应用程序中,我们可以通过配置文件比如Property文件来存储数据库信息,比如数据库名称、用户名、密码、地址、端口等等。 建立连接:使用Java JDBC API中的该库驱动连接数据库。 字段验证:避免SQL注入攻击,对输入的字段进行验证和过滤。 构建SQL语句:使用…

    Java 2023年6月1日
    00
  • Java开发过程中关于异常处理的详解

    Java开发过程中关于异常处理的详解 在Java开发中,异常处理是非常重要的一个环节。良好的异常处理可以提高代码质量,让程序更加健壮和稳定。本文将会从以下几个方面详细讲解Java开发过程中关于异常处理的相关知识。 1. 什么是Java异常 Java异常指的是在程序运行过程中出现的错误情况,这些错误情况可能会导致程序崩溃或产生不正确的结果。Java异常可以分为…

    Java 2023年5月27日
    00
  • 腾讯、百度、华为、搜狗和滴滴Android面试题汇总

    腾讯、百度、华为、搜狗和滴滴Android面试题汇总攻略 前言 面试是进入互联网公司的重要一步,而在面试中往往会遇到很多细节和难点。这些细节和难点很大程度上与我们日常的工作不相关,但是却是面试中极度重要的考核点。为此,本文梳理腾讯、百度、华为、搜狗和滴滴等高端公司的面试题目,希望能对你在面试中起到帮助的作用。 分类 面经的题型并不固定,但是它们可以被大致归类…

    Java 2023年5月26日
    00
  • Java中的常用输入输出语句的操作代码

    接下来我将为你详细讲解Java中常用的输入输出语句操作代码。 标准输入输出 Java中有两个标准的输入输出流:System.in和System.out。 输出语句 输出语句用于将数据输出到控制台或其他设备。 Java中使用System.out.println()方法来将数据输出,并自动在结尾处添加一个换行符。 例如,以下代码输出“Hello World!”:…

    Java 2023年5月26日
    00
  • 简单了解java ibatis #及$的区别和用法

    下面是关于“简单了解java ibatis #及$的区别和用法”的完整攻略: 什么是Java iBatis? Java iBatis(也称MyBatis)是一种Java持久层框架,它可以将Java对数据库的访问和操作抽象出来,使得Java程序员可以更加方便地访问和操作数据库。而“#”和“$”是Java iBatis中常用的参数占位符,用于动态地替换SQL语句…

    Java 2023年5月20日
    00
合作推广
合作推广
分享本页
返回顶部