リクエストの非同期処理は Spring 3.2 以降のバージョンで追加されました。この記事では主に Spring Boot で非同期リクエストを実装する方法を紹介します (Servlet 3.0)。興味のある方は参照してください。
リクエストの処理速度を向上させ、サービスパフォーマンスの消費を削減することを目的として、リクエストの非同期処理が Spring 3.2 以降のバージョンに追加されました。
同時リクエストの場合、Web サーバーの接続プールの長期占有によるパフォーマンスの問題を避けるために、呼び出し後に非 Web サービス スレッドが生成されます。これを処理するために Web サーバーのスループットが追加されます。
このため、Servlet 3.0 ではリクエストの非同期処理が追加され、Spring もこれに基づいてカプセル化されました。
この記事でもコード例を使用して、Spring Boot で非同期リクエストを適用する方法を説明します。
まず、いくつかの重要なポイントについて説明します:
1. @WebFilter および @WebServlet アノテーションの asyncSupported = true Attributes
非同期処理されるサーブレットに filter がある場合、 filter@ WebFilter のアノテーションは asyncSupported=true に設定する必要があります
それ以外の場合、現在のチェーンのフィルターまたはサーブレットは非同期操作をサポートしていません
。 Spring Boot は、デフォルトのプロセッサーでいくつかの intercept/* フィルターを追加します。/* はすべてのリクエストをインターセプトするため、asyncSupported=true 属性も設定する必要があるのは当然です。これらのフィルターは Spring Boot によって初期化されるため、統合構成用の @EnableAsync アノテーションが提供されます。このアノテーションは「非 @WebFilter および @WebServlet アノテーション」に対してのみ有効であるため、定義するフィルターは引き続き asyncSupported= true を構成する必要があります。 。
3. AsyncContext
Object4. asyncContext.setTimeout(20 * 1000L);
非同期リクエストを無期限に待機させることはできず、setTimeout を通じて最大タイムアウトを設定します。
2 つの方法で非同期タスクをテストします:
まず SpringBootSampleApplication に @EnableAsync アノテーションを追加します。
すべてのカスタム フィルターをもう一度確認します。次の 2 つの状況がある場合は、asyncSupported=true を設定する必要があります1) カスタム フィルターが /* をインターセプトします
2) 特定のフィルターが /shanhy/* をインターセプトする必要があります。実行する 非同期リクエストのサーブレットは /shanhy/testcomet です
方法 1: ネイティブ サーブレット メソッド
package org.springboot.sample.servlet; import java.io.IOException; import java.util.Queue; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; 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; /** * HTTP长连接实现 * * @author 单红宇(365384722) * @myblog http://blog.csdn.net/catoop/ * @create 2016年3月29日 */ @WebServlet(urlPatterns = "/xs/cometservlet", asyncSupported = true) //异步处理的servlet若存在过滤器,则过滤器的注解@WebFilter应设置asyncSupported=true, //否则会报错A filter or servlet of the current chain does not support asynchronous operations. public class CometServlet extends HttpServlet { private static final long serialVersionUID = -8685285401859800066L; private final Queue<AsyncContext> asyncContexts = new LinkedBlockingQueue<>(); private final Thread generator = new Thread("Async Event generator") { @Override public void run() { while (!generator.isInterrupted()) {// 线程有效 try { while (!asyncContexts.isEmpty()) {// 不为空 TimeUnit.SECONDS.sleep(10);// 秒,模拟耗时操作 AsyncContext asyncContext = asyncContexts.poll(); HttpServletResponse res = (HttpServletResponse) asyncContext.getResponse(); res.getWriter().write("{\"result\":\"OK - "+System.currentTimeMillis()+"\"}"); res.setStatus(HttpServletResponse.SC_OK); res.setContentType("application/json"); asyncContext.complete();// 完成 } } catch (InterruptedException e) { Thread.currentThread().interrupt(); e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } }; @Override public void init() throws ServletException { super.init(); generator.start(); } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println(">>>>>>>>>>CometServlet Request<<<<<<<<<<<"); doPost(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { AsyncContext asyncContext = req.startAsync(); asyncContext.setTimeout(20 * 1000L); asyncContexts.offer(asyncContext); } @Override public void destroy() { super.destroy(); generator.interrupt(); } }
@Controller public class PageController { @RequestMapping("/async/test") @ResponseBody public Callable<String> callable() { // 这么做的好处避免web server的连接池被长期占用而引起性能问题, // 调用后生成一个非web的服务线程来处理,增加web服务器的吞吐量。 return new Callable<String>() { @Override public String call() throws Exception { Thread.sleep(3 * 1000L); return "小单 - " + System.currentTimeMillis(); } }; } }
<%@ page pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>长连接测试</title> <script type="text/javascript" src="${pageContext.request.contextPath }/webjarslocator/jquery/jquery.js"></script> <script type="text/javascript"> $(function(){ function longPolling(){ $.getJSON('${pageContext.request.contextPath }/xs/cometservlet', function(data){ console.log(data.result); $('#n1').html(data.result); longPolling(); }); } longPolling(); function longPolling2(){ $.get('${pageContext.request.contextPath }/async/test', function(data){ console.log(data); $('#n2').html(data); longPolling2(); }); } longPolling2(); }); </script> </head> <body> <h1>长连接测试</h1> <h2 id="n1"></h2> <h2 id="n2"></h2> </body> </html>
1.
Java 無料ビデオチュートリアル
2.
画像の等比率サムネイルの実装に関する Java ビデオチュートリアル
3. FastJson チュートリアルマニュアル
以上がSpring Bootの2つの非同期リクエストメソッドの詳細説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。