servlet非同步任務

LZC發表於2021-07-19

使用SpringBoot框架
啟動類需要加@ServletComponentScan註解

@WebServlet(urlPatterns = "/my/servlet", asyncSupported = true)
public class MyServlet extends HttpServlet implements InitializingBean {
    // 所有的請求都存放到這個佇列裡面
    private static LinkedBlockingQueue<AsyncContext> taskQueue = new LinkedBlockingQueue<>();

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 啟動非同步請求
        AsyncContext asyncContext = req.startAsync();
        try {
            // 將請求放入到佇列裡面
            taskQueue.put(asyncContext);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        // 開啟一個執行緒從佇列裡面獲取任務
        new Thread(()->{
            // 這裡是一個死迴圈,不斷的從佇列裡面獲取任務
            while (true) {
                try {
                    // 從佇列裡面獲取任務,如果佇列為空,執行緒將會被阻塞,當佇列不為空時,執行緒會被喚醒
                    AsyncContext asyncContext = taskQueue.take();
                    HttpServletResponse resp = (HttpServletResponse) asyncContext.getResponse();
                    asyncContext.start(()->{
                        System.out.println(Thread.currentThread() + "開始處理..." + LocalDateTime.now().toString());
                        try {
                            Thread.sleep(3000); // 睡眠三秒模型業務流程
                            resp.getWriter().println("Hello World:" + Thread.currentThread());
                        } catch (IOException | InterruptedException e) {
                            e.printStackTrace();
                        }
                        // 觸發完成,相應使用者
                        asyncContext.complete();
                        System.out.println(Thread.currentThread() + "處理結束..." + LocalDateTime.now().toString());
                    });
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}
本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章