您的位置:首页 > 其它

AsyncContext简介

2015-12-19 16:18 281 查看
为了支持异步处理,在Servlet 3.0中,在ServletRequest上提供了startAsync()方法:

AsyncContext startAsync() throws java.lang.IllegalStateException;

AsyncContext startAsync(ServletRequest servletRequest,

                        ServletResponse servletResponse)

                        throws java.lang.IllegalStateException

这两个方法都会返回AsyncContext接口的实现对象,前者会直接利用原有的请求与响应对象来创建AsyncContext,后者可以传入自行创建的请求、响应封装对象。在调用了startAsync()方法取得AsyncContext对象之后,此次请求的响应会被延后,并释放容器分配的线程。

可以通过AsyncContext的getRequest()、getResponse()方法取得请求、响应对象,此次对客户端的响应将暂缓至调用AsyncContext的complete()或dispatch()方法为止,前者表示响应完成,后者表示将调派指定的URL进行响应。

若要能调用ServletRequest的startAsync()以取得AsyncContext,必须告知容器此Servlet支持异步处理,如果使用@WebServlet来标注,则可以设置其asyncSupported为true。例如:

@WebServlet(urlPatterns = "/some.do", asyncSupported = true)

public class AsyncServlet extends HttpServlet {

...

如果使用web.xml设置Servlet,则可以在<servlet>中设置<async-supported>标签为true:

...

<servlet>

    <servlet-name>AsyncServlet</servlet-name>

    <servlet-class>cc.openhome.AsyncServlet</servlet-class>

    <async-supported>true</async-supported>

</servlet>

...

如果Servlet将会进行异步处理,若其前端有过滤器,则过滤器亦需标示其支持异步处理,如果使用@WebFilter,同样可以设置其asyncSupported为true。例如:

@WebFilter(urlPatterns = "/some.do", asyncSupported = true)

public class AsyncFilter implements Filter{

...

如果使用web.xml设置过滤器,则可以设置<async-supported>标签为true:

...

<filter>

    <filter-name>AsyncFilter</filter-name>

    <filter-class>cc.openhome.AsyncFilter</filter-class>

    <async-supported>true</async-supported>

</filter>

...

下面示范一个异步处理的简单例子:

AsyncContextDemo  AsyncServlet.java

package cc.openhome;

import java.io.*;

import java.util.concurrent.*;

import javax.servlet.*;

import javax.servlet.annotation.*;

import javax.servlet.http.*;

@WebServlet(name="AsyncServlet", urlPatterns={"/async.do"},

             asyncSupported = true)

public class AsyncServlet extends HttpServlet {

    private ExecutorService executorService =

                      Executors.newFixedThreadPool(10);

    @Override

    protected void doGet(HttpServletRequest request,

                                 HttpServletResponse response)

    throws ServletException, IOException {

        response.setContentType("text/html; charset=UTF8");

        AsyncContext ctx = request.startAsync();

        executorService.submit(new AsyncRequest(ctx));

    }

    @Override

    public void destroy() {

         executorService.shutdown();

    }   

}

首先告诉容器,这个Servlet支持异步处理?,对于每个请求,Servlet会取得其AsyncContext?,并释放容器所分配的线程,响应被延后。对于这些被延后响应的请求,创建一个实现Runnable接口的AsyncRequest对象,并将其调度一个线程池(Thread pool)?,线程池的线程数量是固定的,让这些必须长时间处理的请求,在这些有限数量的线程中完成,而不用每次请求都占用容器分配的线程。

AsyncRequest是个实现Runnable的类,其模拟了长时间处理:

AsyncContextDemo  AsyncRequest.java

package cc.openhome;

import java.io.PrintWriter;

import javax.servlet.AsyncContext;

public class AsyncRequest implements Runnable {

    private AsyncContext ctx;

    public AsyncRequest(AsyncContext ctx) {

        this.ctx = ctx;

    }

    @Override

    public void run() {

        try {

            Thread.sleep(10000); 

            PrintWriter out = ctx.getResponse().getWriter();

            out.println("久等了...XD");

            ctx.complete();    

        } catch (Exception e) {

            throw new RuntimeException(e);

        }

    }

}

请求与响应对象都封装在AsyncContext中,所以AsyncRequest建构时必须接受AsyncContext实例。范例中以暂停线程的方式来模拟长时间处理?,并输出简单的字符串作为响应文字?,最后调用AsyncContext的complete()对客户端完成响应?。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: