第十九次課
什麼是過濾器
Servlet API中提供了一個Filter介面,開發web應用時,如果編寫的Java類實現了這個介面,則把這個java類稱之為過濾器Filter。通過Filter技術,開發人員可以實現使用者在訪問某個目標資源之前,對訪問的請求和響應進行攔截。簡單說,就是可以實現web容器對某資源的訪問前截獲進行相關的處理,還可以在某資源向web容器返回響應前進行截獲進行處理。
實現第一個Filter程式
建立MyServlet
@WebServlet("/MyServlet") public class MyServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { PrintWriter out=response.getWriter(); out.print("Hello MyServlet "); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request,response); } }
建立MyFilter
用配置檔案(web.xml)實現filter
1.先建立一個Filter類,該類要實現Filter介面 在idea中,點右鍵,新建Filter,輸入檔名MyFilter1
MyFilter1:
public class MyFilter1 implements Filter { public void destroy() { //過濾器物件在銷燬時自動呼叫,釋放資源 } public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException { //用於攔截使用者的請求,如果和當前過濾器的攔截路徑匹配,該方法會被呼叫 PrintWriter out=resp.getWriter(); out.write("HelloMyFilter"); chain.doFilter(req, resp); } public void init(FilterConfig config) throws ServletException { //過濾器物件在初始化時呼叫,可以配置一些初始化引數 } }
web.xml
<filter> <filter-name>MyFilter1</filter-name> <filter-class>filter.MyFilter1</filter-class> </filter> <filter-mapping> <filter-name>MyFilter1</filter-name> <url-pattern>/MyServlet</url-pattern> </filter-mapping>
<filter>
根元素用於註冊一個Filter
<filter-name>
子元素用於設定Filter名稱
<filter-class>
子元素用於設定Filter類的完整名稱
<filter-mapping>
根元素用於設定一個過濾器所攔截的資源
<filter-name>
子元素必須 與中的子元素相同。
<url-pattern>
子元素用於匹配使用者請求的URL.例如”/MyServlet”,這個URL還可以使用萬用字元””來表示,例如:“.do”適用於所有 以”.do” 結尾的Servlet路徑。
執行http://localhost:8080/MyServlet
結果:HelloMyFilterHello MyServlet
用註解實現filter
@WebFilter("/MyServlet")
public class MyFilter2 implements Filter {
public void destroy() {
//過濾器物件在銷燬時自動呼叫,釋放資源
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
//用於攔截使用者的請求,如果和當前過濾器的攔截路徑匹配,該方法會被呼叫
PrintWriter out=resp.getWriter();
out.write("HelloMyFilter");
chain.doFilter(req, resp);
}
public void init(FilterConfig config) throws ServletException {
//過濾器物件在初始化時呼叫,可以配置一些初始化引數
}
}
Filter對映
使用萬用字元“*”攔截使用者的所有請求
<url-pattern>
子元素用於匹配使用者請求的URL.例如”/MyServlet”,這個URL還可以使用萬用字元””來表示,例如:“.do”適用於所有 以”.do” 結尾的Servlet路徑。在註解中修改
@WebFilter("*.do")
public class MyFilter2 implements Filter {
public void destroy() {
//過濾器物件在銷燬時自動呼叫,釋放資源
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
//用於攔截使用者的請求,如果和當前過濾器的攔截路徑匹配,該方法會被呼叫
PrintWriter out=resp.getWriter();
out.write("HelloMyFilter2");
// chain.doFilter(req, resp);
}
public void init(FilterConfig config) throws ServletException {
//過濾器物件在初始化時呼叫,可以配置一些初始化引數
}
}
Filter鏈
在一個Web應用程式中可以註冊多個Filter程式,每個Filter程式都可以針對某一個URL進行攔截。如果多個Filter程式都對同一個URL進行攔截,那麼這些Filter就會組成一個Filter鏈(也叫過濾器鏈)。Filter鏈用FilterChain物件來表示,FilterChain物件中有一個doFilter()方法,該方法的作用就是讓Filter鏈上的當前過濾器允許,請求進入下一個Filter。 MyFilter01.java
public void doFilter(ServletRequest request,ServletResponse response, FilterChain chain) throws IOException, ServletException {
//用於攔截使用者的請求,如果和當前過濾器的攔截路徑匹配,該方法會被呼叫
PrintWriterout=response.getWriter();
out.write("HelloMyFilter01<br/>");
chain.doFilter(request,response);
}
MyFilter02.java
public void doFilter(ServletRequest request,ServletResponse response, FilterChain chain) throws IOException, ServletException {
//用於攔截使用者的請求,如果和當前過濾器的攔截路徑匹配,該方法會被呼叫
PrintWriterout=response.getWriter();
out.write("MyFilter02 Before<br/>");
chain.doFilter(request,response);
out.write("MyFilter02 After<br/>");
}
Web.xml
<filter>
<display-name>MyFilter01</display-name>
<filter-name>MyFilter01</filter-name>
<filter-class>cn.lctvu.filter.MyFilter01</filter-class>
</filter>
<filter-mapping>
<filter-name>MyFilter01</filter-name>
<url-pattern>/MyServlet</url-pattern>
</filter-mapping>
<filter>
<display-name>MyFilter02</display-name>
<filter-name>MyFilter02</filter-name>
<filter-class>cn.lctvu.filter.MyFilter02</filter-class>
</filter>
<filter-mapping>
<filter-name>MyFilter02</filter-name>
<url-pattern>/MyServlet</url-pattern>
</filter-mapping>
注意:Filter鏈中各個Filter的攔截順序與它們在Web.xml檔案中元素的對映順序一致,由於MyFilter01的元素位於MyFilter02的元素前面,因此使用者的訪問請求首先會被MyFilter01攔截,然後再被MyFilter02攔截。
在3.0之後新增@WebFilter註解,當使用註解配置多個Filter時,使用者無法控制其執行順序,此時Filter過濾的順序是按照Filter的類名來控制的,按自然排序的規則。
FilterConfig介面
為了獲取Filter程式在web.xml檔案中的配置資訊,Servlet API提供了一個FilterConfig介面,該介面封裝了Filter程式在web.xml中的所有註冊資訊,並且提供了一系列獲取這些配置資訊的方法。 MyFilter03
public class MyFilter03 implements Filter {
private String characterEncoding;
FilterConfig fc;
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
// 輸出引數資訊
characterEncoding=fc.getInitParameter("encoding");
System.out.println("encoding初始化引數值:"+characterEncoding);
chain.doFilter(req, resp);
}
public void init(FilterConfig config) throws ServletException {
this.fc=config;
}
}