過濾器介紹
但這還不是全部。您真的不認為 servlet 有那麼簡單,是嗎?
除了我們已經分析過的 servlet 之外,還有所謂的“實用 servlet”——過濾器。它們與 servlet 非常相似,但它們的主要工作是幫助 servlet 處理請求。
過濾器就像秘書,而 servlet 就像導演。在文件到達主任辦公桌之前,它會通過秘書的手。主管簽字後,它會再次交給秘書,例如,已經作為外發信件。
這樣的秘書可以拒絕對主管的某些請求(例如,垃圾郵件)。或者對他已知的問題給出標準答案(“導演不在位”)。等等。而且,可以有多個這樣的秘書:一個可以一次性為所有董事過濾垃圾郵件,另一個可以在不同董事之間傳遞請求,等等。
過濾器的工作方式相同。

類 Filter、FilterChain、FilterConfig
過濾器與 servlet 非常相似,但有一些細微差別。要編寫自己的過濾器,您需要繼承自javax.servlet.Filter
.
過濾器也有方法init()
和destroy()
。service()
過濾器沒有方法,而是有一個doFilter()
. 甚至有自己的類 FilterConfig。過濾器也被添加到 web.xml 文件中的 servlet 或通過 @WebFilter 註釋。
方法列表:
方法 | 描述 | |
---|---|---|
1個 | init(FilterConfig config) |
過濾器初始化 |
2個 | destroy() |
過濾卸料 |
3個 | doFilter(ServletRequest , ServletResponse, FilterChain) |
請求處理(過濾) |
servlet 和過濾器有什麼區別?
可以有多個過濾器,它們按順序處理請求(和響應)。它們被組合成一個所謂的鏈 - 甚至有一個特殊的類FilterChain
。
在方法中處理完請求後,doFilter()
需要調用doFilter()
鏈中下一個過濾器的方法。例子:
public class MyFilter implements Filter {
public void init(FilterConfig arg0) throws ServletException {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws Exception {
PrintWriter out = resp.getWriter();
out.print("Adding something before the body of the response");
chain.doFilter(req, resp); // call the next filter in the chain
out.print("Adding something after the body of the response");
}
public void destroy() {
}
}
實際上,您不能那樣添加響應主體。形式上,過濾器和 servlet 是相互獨立的,可以獨立更改。它們可以由不同的開發人員在不同的時間編寫。過濾器功能只是一個服務功能,例如:
- 記錄所有傳入的請求(和響應)
- 數據壓縮
- 數據的加密(和解密)
- 請求數據驗證
- 添加/刪除所需的標題
- 重定向請求
- 訪問控制(檢查用戶是否登錄)
RequestDispatcher類
doFilter()
有時可能需要在方法中運行過濾器時調用另一個 servlet 。為此,容器有一個特殊的對象RequestDispatcher
。
您可以通過兩種方式獲得它:
- 在對象
HttpServletRequest
- 在對象
ServletContext
該對象可用於將現有請求重定向到另一個 servlet。例如,原來用戶沒有被授權,我們想給他看一個有授權的頁面。好吧,或者服務器出現錯誤,我們想向用戶顯示一個錯誤頁面:)
public class HelloServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws Exception {
String path = "/error.html";
ServletContext servletContext = this.getServletContext();
RequestDispatcher requestDispatcher = servletContext.getRequestDispatcher(path);
requestDispatcher.forward(request, response);
}
}
您也可以RequestDispatcher
從過濾器調用。
public class MyFilter implements Filter {
public void init(FilterConfig arg0) throws ServletException {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws Exception {
String path = "/error.html";
ServletContext servletContext = req.getServletContext();
RequestDispatcher requestDispatcher = servletContext.getRequestDispatcher(path);
requestDispatcher.forward(req, resp);
}
public void destroy() {
}
}
注意請求會在方法中處理,使用後forward()
不需要再調用。doFilter()
RequestDispatcher
重定向和轉發的比較
還有一點很重要。如果你想將用戶重定向到你的 servlet 中的另一個 URI,那麼你可以通過兩種方式做到這一點:
redirect
forward
我們已經對它們進行了分析,但是為了方便我再說一遍。
當您通過調用重定向response.sendRedirect("link")
時,服務器會向瀏覽器(客戶端)發迴響應302
和您指定的鏈接。瀏覽器在分析服務器響應後,會下載您傳遞的鏈接。即,瀏覽器中的鏈接更改為新鏈接。
如果您通過 call轉發requestDispatcher.forward()
,則會在容器內發出一個新請求,並且您的 servlet 會將其響應發送給瀏覽器(客戶端)作為您的 servlet 的響應。在這種情況下,瀏覽器收到來自新 servlet 的響應,但瀏覽器中的鏈接沒有改變。
GO TO FULL VERSION