Asynchronous Servlet3.0 and Servlet3.0

Source: Internet
Author: User

Asynchronous Servlet3.0 and Servlet3.0

The previous operations of the servlet are synchronized at the same time by following this process:

1. The request is routed to a servlet based on a path,

2. servlet obtains a series of parameters

3. Execute a series of logic (the proportion of time consumed is also greater)

4. Return results

The above problem occurs when all the operations are synchronized. Therefore, this request must be blocked so that it will be returned only after the tasks are completed,

This will be a waste of resources, because the thread is blocked, just waiting for the completion of the task. But after servlet3.0, we can basically

Yes.

1. The request is routed to a servlet based on a path,

2. Put the logic into the asynchronous queue

3. Return results

4. the asynchronous queue processes the task and returns the result to the page.

Servet3.0 mainly involves two features for asynchronous processing: AsyncContext and asyncSupported.

① If we want our servlet to support Asynchronization, The asyncSupported attribute must be set. For the annotation type, we directly set the attribute.

@WebServlet(asyncSupported=true,urlPatterns={"/async"})

For the configuration price of the old version, you only need to add

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

Another is to set up dynamic servlets.

dynamic.setAsyncSupported(true);
You can.
② There are still a lot of things to remember for AsyncContext, but it mainly keeps requests and corresponding references, the operation after the returned result is to operate the two references in an asynchronous environment.

To obtain this, you need to use the method added after request 3.0, startAsync (..), this method is to return an AsyncContext object, which contains the request and response references. There are many asynchronous processing methods. We can directly define a work queue, asynchronous processing, or directly using AsyncContext. start (Runnable) method to start a new thread for processing logic

Main Methods of AsyncContext:
GetRequest () is the request. We can use the same method in an asynchronous environment as in a service.

GetReponse () is similar to the above

HasOriginalRequestAndResponse () indicates whether the AsyncContext we use is obtained using the original request, or through encapsulated requests and corresponding creation.
In short, the original type indicates that startAsync () is called (). But it encapsulates startAsync (ServletRequest, ServletResponse) or other types,

The dispatch () method. This method has several reloads, indicating forwarding. It is a bit similar to req. getRequestDispatcher (), but it is rich.
If startAsync (ServletRequest, ServletResponse) is used to initialize AsyncContext, and the incoming request is an instance of HttpServletRequest, The URI returned by HttpServletRequest. getRequestURI () is used for allocation. Otherwise, it is the request URI finally dispatched by the container.
The following code is online:
// Request to/url/A AsyncContext ac = request. startAsync ();... ac. dispatch (); // asynchronously distributed to/url/A // request to/url/A // forward to/url/B request. getRequestDispatcher ("/url/B "). forward (request, response); // starts the Asynchronous Operation AsyncContext ac = request from the target of FORWARD. startAsync (); ac. dispatch (); // asynchronously distributed to/url/A // request to/url/A // forward to/url/B request. getRequestDispatcher ("/url/B "). forward (request, response); // starts the Asynchronous Operation AsyncContext ac = request from the target of FORWARD. startAsync (request, response); ac. dispatch (); // asynchronously distributed to/url/B

Dispatch (String path) is forwarded to the specified url.

 

Complete (): After we use request. startAsync (...) to obtain AsyncContext, after completing asynchronous operations, we need to call this method to end asynchronous operations. If the request is assigned to a Servlet that does not support asynchronous operations, or the target servlet called by AsyncContext. dispatch does not call complete, the complete method is called by the container. However, for a more legal operation, for example, if you do not call the startAsync release method but substitute complete (), the IllegalStateException exception will be thrown. At the same time, before you call complete (), you can call dispath () the method does not work. Of course, this is because the asynchronous method is not over yet. Of course it does not work.

SetTimeOut (...) sets the timeout time to indicate the maximum time of asynchronous processing. If it is a negative number, it indicates that it will never time out.

Start (Runnable run) Runnable indicates an asynchronous task. When we do this, we will add AsyncContext to all the operations for this reason.

AddListener (AsyncListener listener)

The first three are easy to understand. Finally, the asynchronous listener will be notified in the order they are added to the request.

Below is the general usage of AsyncContext

 

Package com. hotusm. servlet. async; import java. io. IOException; import java. io. printWriter; import java. util. concurrent. timeUnit; import javax. servlet. asyncContext; import javax. servlet. asyncEvent; import javax. servlet. asyncListener; import javax. servlet. servletException; import javax. servlet. servletRequest; import javax. servlet. annotation. webServlet; import javax. servlet. http. httpServlet; import javax. servlet. http. httpServletRequest; import javax. servlet. http. response; @ WebServlet (urlPatterns = {"/url"}, response = true) public class AsynDemoServlet extends HttpServlet {@ Override protected void doGet (HttpServletRequest req, comment resp) throws ServletException, IOException {// resp. setHeader ("Connection", "Keep-Alive"); resp. setContentType ("text/html; charset = UTF-8"); System. out. println (req. isAsyncSupported () + "" + req. isAsyncStarted ();/* req. getAsyncContext (); indicates the recently created AsyncContext */final AsyncContext ac = req. startAsync (); // set the timeout value ac. setTimeout (5 * 1000L); // This method is ac. start (new Runnable () {public void run () {try {TimeUnit. SECONDS. sleep (3L);} catch (InterruptedException e) {e. printStackTrace ();} try {PrintWriter writer = ac. getResponse (). getWriter (); writer. write ("1"); writer. flush (); // This is to test whether the same AsyncContext can call the request and response PrintWriter writer1 = ac multiple times before the complete is called. getResponse (). getWriter (); writer1.write ("2"); writer1.flush (); ServletRequest request = ac. getRequest (); request. setAttribute ("isAsyn", true);/** 2. after complete is called, it indicates that the Asynchronization has ended. If you call * getRequest or getResponse, IllegalStateException ***/ac will be thrown. complete ();} catch (Exception e) {e. printStackTrace () ;}}); // sets the listener to ac. addListener (new AsyncListenerImpl (); // the same request cannot be called multiple times at the same time. // req. startAsync (); PrintWriter out = resp. getWriter (); out. write ("hello async"); out. write ("<br/>"); // call flush. Otherwise, it will not be output because the content is not flushed out. flush ();} static class AsyncListenerImpl implements AsyncListener {public void onComplete (AsyncEvent event) throws IOException {System. out. println ("onComplete");} public void onTimeout (AsyncEvent event) throws IOException {System. out. println ("onTimeout"); event. getAsyncContext (). complete ();} public void onError (AsyncEvent event) throws IOException {System. out. println ("onError");} public void onStartAsync (AsyncEvent event) throws IOException {System. out. println ("onStartAsync ");}}}

When we use the url above, we will immediately return hello async, and then OUTPUT 12 seconds later.

 

The above method only uses the start (Runnable run); method. We can also put AsyncContext in a work queue, and then another thread pool for processing.

Sample Code:

Package com. hotusm. servlet. async; import java. io. IOException; import java. io. printWriter; import java. util. map; import java. util. concurrent. linkedBlockingQueue; import javax. servlet. asyncContext; import javax. servlet. servletException; import javax. servlet. annotation. webServlet; import javax. servlet. http. httpServlet; import javax. servlet. http. httpServletRequest; import javax. servlet. http. httpServletResponse; @ WebServlet (urlPatterns = {"/async1"}, region = true) public class extends HttpServlet {private LinkedBlockingQueue <AsyncContext> works = new LinkedBlockingQueue <AsyncContext> (100 ); @ Override public void init () throws ServletException {
// Because this is a test, five threads are enabled for processing. But in actual cases, a scalable solution new Thread (new HelperWork () must be designed ()). start (); new Thread (new HelperWork ()). start (); new Thread (new HelperWork ()). start (); new Thread (new HelperWork ()). start () ;}@ Override protected void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp. setHeader ("Connection", "Keep-Alive"); resp. addHeader ("Cache-Control", "private"); resp. addHeader ("Pragma", "no-cache"); resp. setContentType ("text/html; charset = UTF-8"); try {works. put (req. startAsync ();} catch (Exception e) {} PrintWriter writer = resp. getWriter (); writer. write ("waiting for asynchronous completion"); writer. flush ();} private class HelperWork implements Runnable {public void run () {try {AsyncContext ac = works. take ();

// Simulate service consumption
TimeUnit. SECONDS. sleep (2L)

HttpServletRequest request = (HttpServletRequest) ac. getRequest ();

                Map<String, String[]> maps = request.getParameterMap();                System.out.println(maps);                                HttpServletResponse response = (HttpServletResponse)ac.getResponse();                PrintWriter writer = response.getWriter();                writer.write(maps.toString());                writer.flush();                ac.complete();            } catch (Exception e) {                e.printStackTrace();            }                    }    }}

 

The above is just a way of thinking. We can also put it into the thread pool for processing and so on.

Then let's talk about how to use ajax for asynchronous communication. We only need to retain the reference of AsyncContext when accessing the servlet for the first time, and then interact with the page through the output.

 

 

 



 





Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.