Servlet3.0新特性-非同步處理Servlet、Filter
一、淺談Servlet
在Servlet 3.0 之前,一個普通 Servlet 的主要工作流程大致如下:
其中黃色階段通常是最耗時的,因為業務處理一般涉及資料庫操作,還會受到網路等的影響,而在此過程中,Servlet 執行緒一直處於阻塞狀態,直到業務處理完畢。在處理業務的過程中,Servlet 資源一直被佔用而得不到釋放,對於併發較大的應用,這有可能造成效能的瓶頸。對此,在以前通常是採用私有解決方案來提前結束 Servlet 執行緒,並及時釋放資源。
為解決這個問題,Servlet 3.0 就開始支援非同步處理了,這與 Ajax 非同步不一樣,之前的 Servlet 處理流程可以調整為如下的過程:
首先,Servlet 接收到請求之後,可能首先需要對請求攜帶的資料進行一些預處理;接著,Servlet 執行緒將請求轉交給一個非同步執行緒來執行業務處理,執行緒本身返回至容器,此時 Servlet 還沒有生成響應資料,非同步執行緒處理完業務以後,可以直接生成響應資料(非同步執行緒擁有 ServletRequest 和 ServletResponse 物件的引用),或者將請求繼續轉發給其它 Servlet。如此一來, Servlet 執行緒不再是一直處於阻塞狀態以等待業務邏輯的處理,而是啟動非同步執行緒之後可以立即返回。
二、啟用非同步處理
非同步處理特性可以應用於 Servlet 和過濾器兩種元件。在預設情況下,Servlet 和過濾器並沒有開啟非同步處理特性,因為非同步處理的工作模式和普通工作模式在實現上有著本質的區別,因此如果希望使用該特性,則必須按照如下的方式啟用:
1. 在 web.xml 檔案中啟動
Servlet3.0 預設是沒有 web.xml 檔案的,但 Servlet3.0 也是支援 web.xml 檔案的,較 Servlet之前的版本,Servlet 3.0 在 <servlet>
和 <filter>
標籤中增加了 <async-supported>
子標籤,該標籤預設是 false 。如果想啟用非同步支援,只需要置為 true 即可。例如:
<!-- servlet -->
<servlet>
<servlet-name>asynServlet</servlet-name>
<servlet-class>com.servlet.AsynServlet</servlet-class>
<async-supported>true</async-supported>
</servlet>
<!-- Filter -->
<filter>
<filter-name>asynFilter</filter-name>
<filter-class>com.filter.AsynFilter</filter-class>
<async-supported>true</async-supported>
</filter>
2. 通過註解開啟非同步支援
Servlet 3.0 提供的 @WebServlet 和 @WebFilter 進行 Servlet 或 Filter 配置的情況,這兩個註解都提供了 asyncSupported 屬性,預設該屬性的取值為 false。如果想啟用非同步支援,只需要置為 true 即可。例如:
@WebServlet(value="/asyn-servlet",asyncSupported=true)
public class ServletAsyn extends HttpServlet {...}
@WebFilter(value="/*",asyncSupported=true)
public class FilterAsyn implements Filter {...}
三、非同步處理的程式碼實現方式
Servlet 和 Filter 使用非同步支援的實現方式是一模一樣的操作。這裡只以 Servlet 的實現方式為例。
1. 模擬註冊發資訊到郵件的簡單的非同步處理 Servlet 示例程式碼:
package com.servlet;
import java.io.IOException;
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(value="/asyn-servlet",asyncSupported=true)
public class ServletAsyn extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("Servlet is start");
//1.獲得非同步上下文物件
AsyncContext ac = request.startAsync();
//2.啟動一個耗時的子執行緒
ThreadTask tt = new ThreadTask(ac);
//3.可設定非同步超時物件,需在啟動非同步上下文物件前設定
/*
* 設定超時後,在超時時間內子執行緒沒有結束,主執行緒則會停止等待,繼續往下執行
*/
ac.setTimeout(3000);
//4.開啟非同步上下文物件
ac.start(tt);
//主執行緒結束向客戶端傳送訊息
System.out.println("Servlet is end");
response.setContentType("text/html;charset=utf-8");
response.getWriter().append("資訊已傳送到郵箱");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
非同步執行緒的執行類:
package com.servlet;
import java.util.Date;
import javax.servlet.AsyncContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
public class ThreadTask implements Runnable{
private AsyncContext ac; //定義一個非同步上下文
public ThreadTask(AsyncContext ac) {
super();
this.ac = ac;
}
@Override
public void run() {
/*
* 服務端非同步典型應用是註冊時向郵箱傳送驗證碼
*/
try {
//進行非同步的一些處理
HttpServletRequest requst = (HttpServletRequest) ac.getRequest();
HttpSession session = requst.getSession();
System.out.println("asyn-task start" + new Date());
for(int i=5;i>0; i--) {
System.out.println(i);
Thread.sleep(1000);
}
//將結果放到session等方式
session.setAttribute("message", "This is the result of asyn");
System.out.println("asyn-task end" + new Date());
//通知主執行緒已經處理完成
/*
* 除了使用 ac.complete() 方法通知主執行緒已經處理外
* 還可以使用 ac.dispatch() 方法重定向到一個頁面
*/
ac.dispatch("/show.jsp");
} catch (Exception e) {
e.printStackTrace();
}
}
}
這裡的 show.jsp 模擬為指定郵箱。show.jsp頁面body標籤內程式碼為:<p>郵箱內容:${message }</p>
2. 模擬註冊發資訊到郵件的簡單的非同步處理 Servlet 測試過程
先訪問 show.jsp 頁面,結果如下:
然後我們訪問servlet:http://localhost:8080/Test2/asyn-servlet,在頁面顯示的是
然後我們看一下控制檯列印的結果:
最後我們再回過去看一下 show.jsp 頁面
三、對非同步處理過程的監聽
除此之外,Servlet 3.0 還為非同步處理提供了一個監聽器,使用 AsyncListener 介面表示。它可以監控如下四種事件:
(1)非同步執行緒開始時,呼叫 AsyncListener 的 onStartAsync(AsyncEvent event) 方法;
(2)非同步執行緒出錯時,呼叫 AsyncListener 的 onError(AsyncEvent event) 方法;
(3)非同步執行緒執行超時,則呼叫 AsyncListener 的 onTimeout(AsyncEvent event) 方法;
(4)非同步執行完畢時,呼叫 AsyncListener 的 onComplete(AsyncEvent event) 方法。
如果要註冊一個 AsyncListener,只需將準備好的 AsyncListener 物件傳遞給 AsyncContext 物件的 addListener() 方法即可,如下所示:
AsyncContext ac = request.startAsync();
ac.addListener(new AsyncListener() {
@Override
public void onComplete(AsyncEvent arg0) throws IOException {
// TODO Auto-generated method stub
}
@Override
public void onError(AsyncEvent arg0) throws IOException {
// TODO Auto-generated method stub
}
@Override
public void onStartAsync(AsyncEvent arg0) throws IOException {
// TODO Auto-generated method stub
}
@Override
public void onTimeout(AsyncEvent arg0) throws IOException {
// TODO Auto-generated method stub
}
});
相關文章
- Servlet 3.0 新特性Servlet
- 厲害了,Servlet3的非同步處理機制Servlet非同步
- java新特性處理時間工具類Java
- GRpc異常處理FilterRPCFilter
- Oracle 12c新特性--ASMFD(ASM Filter Driver)特性OracleASMFilter
- 淺嘗Spring註解開發_Servlet3.0與SpringMVCServletSpringMVC
- Filter 與 Servlet 的區別FilterServlet
- SpringBoot如何註冊Servlet、Filter、ListenerSpring BootServletFilter
- Netty之非阻塞處理Netty
- JavaScript | 非同步處理JavaScript非同步
- 非同步流程處理非同步
- 非同步處理方法非同步
- JavaWeb三大元件(Servlet、Filter、Listener)JavaWeb元件ServletFilter
- 【IDEA】HTML通過servlet3.0註解名提交表單到servlet類找不到頁面的問題IdeaHTMLServlet
- VUE例項:使用 CSS Filter 處理圖片VueCSSFilter
- springmvc學習指南 之---第27篇 spring如何實現servlet3.0無web.xml 配置servlet物件的SpringMVCServletWebXML物件
- Laravel 事件&非同步處理Laravel事件非同步
- js中非同步處理JS非同步
- 一文快速回顧 Servlet、Filter、ListenerServletFilter
- PHP 核心特性 - 錯誤處理PHP
- servlet非同步任務Servlet非同步
- python中快速處理關鍵字map,reduce,filterPythonFilter
- QT執行緒同步與非同步處理QT執行緒非同步
- DeferredResult——非同步請求處理非同步
- js的三種非同步處理JS非同步
- Mysql自動處理同步報錯MySql
- js學習之非同步處理JS非同步
- 從零手寫實現 tomcat-05-servlet 處理支援TomcatServlet
- 從零手寫實現 tomcat-09-servlet 處理類TomcatServlet
- 同步非同步,阻塞非阻塞非同步
- 非同步、同步、阻塞、非阻塞非同步
- 實戰Spring Boot 2.0系列(五) - Listener, Servlet, Filter和InterceptorSpring BootServletFilter
- JavaScript 非同步函式的 Promisification 處理JavaScript非同步函式
- Oracle DG同步失敗故障處理(二)Oracle
- SpringBoot 教程之處理非同步請求Spring Boot非同步
- SpringMVC非同步處理的 5 種方式SpringMVC非同步
- ActiveMQ-MessageListener非同步回撥處理MQ非同步
- JavaScript非同步處理的那些事兒JavaScript非同步