1. Filter簡介
Filter也稱之為過濾器,WEB開發(fā)人員通過Filter技術(shù),對web服務(wù)器管理的所有web資源:例如Jsp ,Servlet ,靜態(tài)圖片文件或靜態(tài)html文件等進(jìn)行攔截,從而實現(xiàn)一些特殊的功能。
Servlet API中提供了一個Filter接口 ,開發(fā)web應(yīng)用時,如果編寫的類實現(xiàn)了這個接口,則把這個java類稱之為過濾器Filter。通過Filter技術(shù) ,開發(fā)人員可以實現(xiàn)用戶在訪問某個目標(biāo)資源之前,對訪問的請求和響應(yīng)進(jìn)行攔截,如下所示:


Filter開發(fā)入門
Filter開發(fā)步驟
Filter開發(fā)分為二個步驟:
- 編寫java類實現(xiàn)Filter接口,并實現(xiàn)其doFilter方法。
- 在web.xml(不使用注解方式)文件中使用<filter>和<filter-mapping>元素對編寫的filter類進(jìn)行注冊,并設(shè)置它所能攔截的資源。(了解即可,百度)
2. Filter是如何實現(xiàn)攔截的?
Filter接口中有一個doFilter方法, 當(dāng)我們編寫好Filter,并配置對哪個web資源進(jìn)行攔截后,WEB服務(wù)器每次在調(diào)用web資源的service方法之前,都會先調(diào)用一下filter的doFilter方法,因此,在該方法內(nèi)編寫代碼可達(dá)到如下目的:
調(diào)用目標(biāo)資源之前,讓一段代碼執(zhí)行。
是否調(diào)用目標(biāo)資源(即是否讓用戶訪問web資源)
web服務(wù)器在調(diào)用doFilter方法時,會傳遞一個filterChain對象進(jìn)來 ,filterChain對象是filter接口中最重要的一個對象,它也提供了一個doFilter方法,開發(fā)人員可以根據(jù)需求決定是否調(diào)用此方法,調(diào)用該方法,則web服務(wù)器就會調(diào)用web資源的service方法,即web資源就會被訪問,否則web資源不會被訪問。
調(diào)用目標(biāo)資源之后,讓一段代碼執(zhí)行。
3. 過濾器簡單代碼
主頁面 index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<a href="a.do?username=zhangsan">訪問Aservlet</a>
<a href="b.do?username=lisi">訪問Bservlet</a>
<a href="c.action?username=lisi">訪問Cservlet</a>
</body>
</html>
a.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
放行了.... a.jsp
</body>
</html>
b.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
過濾器打回了... b.jsp
</body>
</html>
過濾器
package com.lty.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
@WebFilter(filterName = "TestFilter" , urlPatterns = "*.do")
public class TestFilter implements Filter {
public void destroy() {
System.out.println("TestFilter destroy");
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
String username = req.getParameter("username");
System.out.println("doFilter before");
if(username.equals("zhangsan")){
chain.doFilter(req, resp); //放行了
}else{
req.getRequestDispatcher("b.jsp").forward(req,resp);
}
System.out.println("doFilter after");
}
public void init(FilterConfig config) throws ServletException {
System.out.println("TestFilter init");
}
}
servlet
package com.lty.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(name = "AServlet" , urlPatterns = "/a.do")
public class AServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("AServlet");
request.getRequestDispatcher("a.jsp").forward(request,response);
}
}
package com.lty.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(name = "BServlet" , urlPatterns = "/b.do")
public class BServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("BServlet");
}
}
package com.lty.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(name = "CServlet" , urlPatterns = "/c.action")
public class CServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("CServlet");
request.getRequestDispatcher("a.jsp").forward(request,response);
}
}
4. 過濾器的生命周期
Filter對象何時被創(chuàng)建?
服務(wù)器一啟動的時候,就會針對這個web應(yīng)用將所有的Filter對象(攔截器)創(chuàng)建出來,并且以后訪問的時候,都是使用同一個攔截器進(jìn)行攔截。也即一個攔截器會被所有的請求所共享,每一次請求來了之后,都會導(dǎo)致doFilter()方法被調(diào)用一次,F(xiàn)ilter對象只有一個,而doFilter()方法會被多次調(diào)用。
問: Filter對象在內(nèi)存里面有幾個?
答:一個。服務(wù)器并不會針對請求創(chuàng)建新的Filter對象(攔截器)。
Filter對象何時被摧毀?
移除掉web服務(wù)器里面這個web應(yīng)用(或停掉服務(wù)器),就會摧毀這個web應(yīng)用對應(yīng)的攔截器。
使用過濾器技術(shù)解決中文亂碼問題(統(tǒng)一全站的編碼)
package com.lty.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
@WebFilter(filterName = "CoderFilter" , urlPatterns = "*.do")
public class CoderFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
chain.doFilter(req, resp);
}
public void init(FilterConfig config) throws ServletException {
}
}

5. 過濾器應(yīng)用
主頁面 index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<a href="login.do">登錄</a>
<a href="admin.admin">進(jìn)入管理后臺界面</a>
</body>
</html>
登錄頁面 login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="login.do" method="post">
<input type="text" name="username">
<input type="submit" value="登錄">
</form>
</body>
</html>
admin.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
我是整個網(wǎng)站的后臺管理員頁面首頁
</body>
</html>
student.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
我是整個網(wǎng)站的后臺學(xué)生信息管理頁面
</body>
</html>
監(jiān)聽器
package com.lty.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
@WebFilter(filterName = "AuthFilter" , urlPatterns = "*.admin")
public class AuthFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest)req;
Object obj = request.getSession().getAttribute("user");
if(obj != null){
chain.doFilter(req, resp);
}else{
request.getRequestDispatcher("login.jsp").forward(request,resp);
}
}
public void init(FilterConfig config) throws ServletException {
}
}
servlet
package com.lty.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(name = "LoginServlet" , urlPatterns = "/login.do")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
request.getSession().setAttribute("user",username);
request.getRequestDispatcher("/WEB-INF/admin.jsp").forward(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getRequestDispatcher("login.jsp").forward(request,response);
}
}
package com.lty.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(name = "AdminServlet" , urlPatterns = "/admin.admin")
public class AdminServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getRequestDispatcher("/WEB-INF/admin.jsp").forward(request,response);// WEB-INF前面的 / 代表該項目中的web文件
}
}
package com.lty.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(name = "StudentServlet" , urlPatterns = "/student.admin")
public class StudentServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getRequestDispatcher("/WEB-INF/student.jsp").forward(request,response);// WEB-INF前面的 / 代表該項目中的web文件
}
}

6. 過濾器其它
當(dāng)一個項目使用多個過濾器的時候,默認(rèn)項目中第一個(靠前的)過濾器進(jìn)行首次攔截

凡是放到WEB-INF目錄下的文件,Tomcat服務(wù)器規(guī)定用戶無法在瀏覽器上進(jìn)行訪問(用戶通過輸入網(wǎng)址的方式進(jìn)行訪問)
