您现在的位置是:网站首页>博客详情博客详情

JavaEE Async 异步支持

边小丰2019年01月30日 JavaEE 163人已围观


摘要: Async技术是Servlet3.0 之后添加的,用于处理异步请求。在此之前,大多为同步请求,客户端向服务器提交请求,假设请求很耗时,那么按照之前同步的处理办法,servlet在接收到这个请求之后,会调用去处理这个耗时操作,如果这个耗时操作长时间没有返回,那么就造成了服务器的阻塞,服务器资源得不到有效利用,这样的结果显然对于服务器的高并发是非常不利的。 服务器可以异步执行,在等待长时间的过程完成期间,控制容器执行其他任务,当耗时操作完成返回后,再调用资源处理这个返回请求。


前言

Async技术是Servlet3.0 之后添加的,用于处理异步请求。在此之前,大多为同步请求,客户端向服务器提交请求,假设请求很耗时,那么按照之前同步的处理办法,servlet在接收到这个请求之后,会调用去处理这个耗时操作,如果这个耗时操作长时间没有返回,那么就造成了服务器的阻塞,服务器资源得不到有效利用,这样的结果显然对于服务器的高并发是非常不利的。
服务器可以异步执行,在等待长时间的过程完成期间,控制容器执行其他任务,当耗时操作完成返回后,再调用资源处理这个返回请求。

使用Async的步骤

启用async

异步行为需要在Servlet中显式启用 ,其方法有两种:

  • 添加@WebServlet的**asyncSupported**属性实现
@WebServlet(urlPatterns = "/async", asyncSupported = true)
  • 在**web.xml**文件中实现
    <servlet>
        <servlet-name>AsyncServlet</servlet-name>
        <servlet-class>com.dimple.servlet.AsyncServlet</servlet-class>
        <async-supported>true</async-supported> <!--设置启用Async-->
    </servlet>

在Servlet中开启async

@WebServlet(name = "AsyncServlet", urlPatterns = "/async",asyncSupported = true)
public class AsyncServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        PrintWriter out = response.getWriter();
        //输出Servlet开始的时候的系统时间
        out.println("Servlet is starting:"+new Date());
        //创建AsyncContext,开始异步调用
        AsyncContext asyncContext=request.startAsync();
        //设置超时时长,单位为毫秒
        asyncContext.setTimeout(60*1000);
        //启动异步调用的线程
        asyncContext.start(new MyTask(asyncContext));
        //输出Servlet结束的时间
        out.println("Servlet is ending :"+new Date());
    }
}

MyTask内容:

public class MyTask implements Runnable {
    AsyncContext context;

    public MyTask(AsyncContext context) {
        this.context = context;
    }

    /**
     * 此处单开一个线程进行耗时操作,为了模拟耗时操作,这里先让线程Sleep5秒。
     */
    @Override
    public void run() {
        try {
            Thread.sleep(5*1000);
            context.getResponse().getWriter().print("async is ending : "+new Date());
        } catch (InterruptedException | IOException e) {
            e.printStackTrace();
        }
    }
}

执行结果如下:

这里写图片描述

注意:这是采用IDEA开发的,可能采用Eclipse的小伙伴的开发的和我这边的url不一样。

AsyncListener 异步监听器

为了更加清晰的看到异步操作的各种细节,可以借助异步监听器实现。
异步监听器需要实现AsyncListener接口,该接口需要实现如下方法:

            @Override
            public void onComplete(AsyncEvent asyncEvent) throws IOException {
                //当异步调用完成后被调用
            }

            @Override
            public void onTimeout(AsyncEvent asyncEvent) throws IOException {
                //超时被调用
            }

            @Override
            public void onError(AsyncEvent asyncEvent) throws IOException {
                //出现错误的时候被调用
            }

            @Override
            public void onStartAsync(AsyncEvent asyncEvent) throws IOException {
                //启动Async的时候被调用
            }

添加监听器的方法:

asyncContext.addListener(new MyAsyncListener);

总结

使用Servlet3.0的Async异步支持,步骤总结如下:

  • 首先先声明异步支持(web.xml或者注解@webServlet)
  • 在相应的Servlet中获取AsyncContext实例。一般采用request.startAsync();该方法发挥一个AsyncContext对象。
  • 设置超时context.setTimeout();
  • 启动线程context.start(Runable runable);
  • 在相应的实现Runable接口的方法里进行耗时操作。

__EOF__

作  者Dimple
出  处/view/19
版权声明:署名 - 非商业性使用 - 禁止演绎,协议普通文本 | 协议法律文本
声援博主:如果您觉得文章对您有帮助,可以点击下方的鼓掌一下。您的鼓励是博主的最大动力!如有疑问请留言!


文章评论

我的名片

网名:Dimple | 裤兜有怪兽

职业:Java开发工程师

现居:四川省-成都市

Email:bianxiaofeng@sohu.com

每日一句

最近更新

点击排行

猜你喜欢