# Filter
## 概念
Filter 的基本功能是對 Servlet 容器調用 Servlet 的過程進行攔截,從而在 Servlet 進行響應處理的前后實現一些特殊的功能。
在 Servlet API 中定義了三個接口類來開供開發人員編寫 Filter 程序:Filter, FilterChain, FilterConfig
Filter 程序是一個實現了 Filter 接口的 Java 類,與 Servlet 程序相似,它由 Servlet 容器進行調用和執行
Filter 程序需要在 web.xml 文件中進行注冊和設置它所能攔截的資源:Filter 程序可以攔截 Jsp, Servlet, 靜態圖片文件和靜態 html 文件
***
### 創建一個HelloWorldFilter
創建一個test.jsp
創建一個繼承Filter的類
~~~
package com.neusoft.web.fiter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class HelloWorldFilter implements Filter{
@Override
public void destroy() {
// TODO Auto-generated method stub
System.out.println("destroy");
}
@Override
public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)
throws IOException, ServletException {
// TODO Auto-generated method stub
System.out.println("doFilter");
}
@Override
public void init(FilterConfig arg0) throws ServletException {
// TODO Auto-generated method stub
System.out.println("init");
}
}
~~~
web.xml配置Filter
~~~
<filter>
<filter-name>helloworldFilter</filter-name>
<filter-class>com.neusoft.web.fiter.HelloWorldFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>helloworldFilter</filter-name>
<url-pattern>/20180125/test.jsp</url-pattern>
</filter-mapping>
~~~
運行jsp,發現init()被調用后(創建Filter對象后立即被調用,且只被調用一次),doFilter()被調用,所以init()與Servlet的init()基本功能一樣,都是初始化用的,而doFilter()與Servlet當中的service()功能基本一樣,而FilterConfig與ServletConfig基本一樣,封裝著配置信息;destory()釋放當前Filter所占用的資源的方法,在Filter被銷毀之前調用,且只能調用一次
而上述例子當中,發現頁面中的內容并沒有出現,是因為Filter將請求攔截下來了,想要對攔截進行放行,需要調用FilterChain的doFilter方法
~~~
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// TODO Auto-generated method stub
System.out.println("doFilter");
chain.doFilter(request, response);
}
~~~
### Filter鏈
~~~
<filter>
<filter-name>helloworldFilter</filter-name>
<filter-class>com.neusoft.web.fiter.HelloWorldFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>helloworldFilter</filter-name>
<url-pattern>/20180125/test.jsp</url-pattern>
</filter-mapping>
<filter>
<filter-name>secondFilter</filter-name>
<filter-class>com.neusoft.web.fiter.SecondFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>secondFilter</filter-name>
<url-pattern>/20180125/test.jsp</url-pattern>
</filter-mapping>
~~~
多個Filter在一起形成一個Filter鏈,而攔截的順序與filter-mapping的前后有關
思考:多個Filter代碼的順序
~~~
package com.neusoft.web.fiter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class HelloWorldFilter implements Filter{
@Override
public void destroy() {
// TODO Auto-generated method stub
System.out.println("destroy");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// TODO Auto-generated method stub
System.out.println("1.doFilter");
chain.doFilter(request, response);
System.out.println("2.doFilter");
}
@Override
public void init(FilterConfig arg0) throws ServletException {
// TODO Auto-generated method stub
System.out.println("init");
}
}
~~~
~~~
package com.neusoft.web.fiter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class SecondFilter implements Filter{
@Override
public void destroy() {
// TODO Auto-generated method stub
System.out.println("destroy2");
}
@Override
public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)
throws IOException, ServletException {
// TODO Auto-generated method stub
System.out.println("3.doFilter2");
arg2.doFilter(arg0, arg1);
System.out.println("4.doFilter2");
}
@Override
public void init(FilterConfig arg0) throws ServletException {
// TODO Auto-generated method stub
System.out.println("init2");
}
}
~~~
~~~
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>Test Page</h1>
<% System.out.println("5.test"); %>
</body>
</html>
~~~
***
課堂練習--1

***
#### dispatcher
< dispatcher >指定過濾器所攔截的資源被 Servlet 容器調用的方式,可以是REQUEST,INCLUDE,FORWARD和ERROR之一,默認REQUEST. 可以設置多個<dispatcher> 子元素用來指定 Filter 對資源的多種調用方式進行攔截。在filter-mapping中配置。
**REQUEST**:當用戶直接訪問頁面時,Web容器將會調用過濾器。如果目標資源是通過RequestDispatcher的include()或forward()方法訪問時,那么該過濾器就不會被調用。
INCLUDE:如果目標資源是通過RequestDispatcher的include()方法訪問時,那么該過濾器將被調用。除此之外,該過濾器不會被調用。
**FORWARD**:如果目標資源是通過RequestDispatcher的forward()方法訪問時,那么該過濾器將被調用,除此之外,該過濾器不會被調用。
ERROR:如果目標資源是通過聲明式異常處理機制調用時,那么該過濾器將被調用。除此之外,過濾器不會被調用。
***
### 典型應用1--字符編碼的過濾器
在每個頁面上都寫request.setCharacterEncoding()很麻煩,寫個過濾器
one.jsp
~~~
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="two.jsp" method="post">
username:<input type="text" name="username">
<input type="submit" value="Submit">
</form>
</body>
</html>
~~~
two.jsp
~~~
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
Hello:${ param.username }
</body>
</html>
~~~
web.xml
~~~
<context-param>
<param-name>encode</param-name>
<param-value>UTF-8</param-value>
</context-param>
~~~
EncodingFilter
~~~
package com.neusoft.web.fiter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
/**
* Servlet Filter implementation class EncodingFilter
*/
@WebFilter("/*")
public class EncodingFilter implements Filter {
public void destroy() {
// TODO Auto-generated method stub
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
String encode = fConfig.getServletContext().getInitParameter("encode");
request.setCharacterEncoding(encode);
chain.doFilter(request, response);
}
private FilterConfig fConfig;
public void init(FilterConfig fConfig) throws ServletException {
this.fConfig = fConfig;
}
}
~~~
***
### 典型應用2--檢測用戶是否登錄的過濾器
list.jsp
~~~
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>List Page</h1>
<a href="a.jsp">AAA</a>
<br><br>
<a href="b.jsp">BBB</a>
<br><br>
<a href="c.jsp">CCC</a>
<br><br>
<a href="d.jsp">DDD</a>
<br><br>
<a href="e.jsp">EEE</a>
<br><br>
</body>
</html>
~~~
a.jsp,b.jsp,c.jsp,d.jsp,e.jsp
~~~
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>BBB Page</h1>
<a href="list.jsp">Return...</a>
</body>
</html>
~~~
doLogin.jsp
~~~
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<%
// 1.獲取用戶的登錄信息
String username = request.getParameter("username");
// 2.若登錄信息完整,則把登錄信息放到HttpSession里
if(username != null && !username.trim().equals("")){
session.setAttribute(application.getInitParameter("userSessionKey"), username);
// 3.重定向到list.jsp
response.sendRedirect("list.jsp");
}else{
response.sendRedirect("login.jsp");
}
%>
</body>
</html>
~~~
login.jsp
~~~
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="doLogin.jsp" method="post">
userName:<input type="text" name="username">
<input type="submit" value="Submit">
</form>
</body>
</html>
~~~
web.xml
~~~
<!-- 不要攔截的資源 -->
<context-param>
<param-name>noCheckPage</param-name>
<param-value>/login/a.jsp,/login/doLogin.jsp,/login/list.jsp,/login/login.jsp</param-value>
</context-param>
<!-- 攔截后重定向到的頁面 -->
<context-param>
<param-name>redirectPage</param-name>
<param-value>/login/login.jsp</param-value>
</context-param>
<!-- 用戶信息放入到session中的鍵名 -->
<context-param>
<param-name>userSessionKey</param-name>
<param-value>USERSESSIONKEY</param-value>
</context-param>
~~~
CheckLoginFilter
~~~
package com.neusoft.web.fiter;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet Filter implementation class CheckLoginFilter
*/
@WebFilter("/login/*")
public class CheckLoginFilter extends HttpFilter {
private String sessionKey;
private String redirectUrl;
private String noCheckPage;
@Override
public void init() {
ServletContext servletContext = getFilterConfig().getServletContext();
sessionKey = servletContext.getInitParameter("userSessionKey");
redirectUrl = servletContext.getInitParameter("redirectPage");
// /login/a.jsp,/login/doLogin.jsp,/login/list.jsp,/login/login.jsp
noCheckPage = servletContext.getInitParameter("noCheckPage");
}
@Override
public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws IOException, ServletException {
// 1.獲取請求的serlvetPath
String servletPath = request.getServletPath();
// 2.檢查獲取到的是否為不需要檢查中的一個,若是,則放行,return
List<String> urls = Arrays.asList(noCheckPage.split(","));
if(urls.contains(servletPath)) {
filterChain.doFilter(request, response);
return;
}
// 3.檢查是否有登錄者,即檢查sessionKey是否存在,若不存在,則重定向redirectUrl
Object user = request.getSession().getAttribute(sessionKey);
if(user == null) {
response.sendRedirect(request.getContextPath()+redirectUrl);
return;
}
// 4.若存在,放行,允許訪問
filterChain.doFilter(request, response);
}
}
~~~
HttpFilter
~~~
package com.neusoft.web.fiter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class HttpFilter implements Filter{
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain filterChain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse)res;
doFilter(request,response,filterChain);
}
public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws IOException, ServletException {
filterChain.doFilter(request, response);
}
private FilterConfig filterConfig;
public FilterConfig getFilterConfig() {
return filterConfig;
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
init();
}
public void init(){
}
}
~~~
***
### Filter小結
(1)簡介
Filter是JavaWEB的一個重要組件,可以對發送到Servlet的請求進行攔截,并對響應也進行攔截
Filter是實現了Filter接口的Java類
Filter需要在web.xml文件中進行配置和映射(注解)
(2)在web.xml中如何配置
~~~
<filter>
<filter-name>helloworldFilter</filter-name>
<filter-class>com.neusoft.web.fiter.HelloWorldFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>helloworldFilter</filter-name>
<url-pattern>/20180125/test.jsp</url-pattern>
</filter-mapping>
~~~
配置與Servlet的配置很相似,url-pattern映射的路徑是可以攔截的資源,也就是通過哪些url能夠訪問到該Filter
***
- 第一章 配置和安裝Tomcat
- 第二章 Servlet(一)
- 第三章 Servlet(二)
- 練習 一 . Servlet配置級獲取初始化參數
- 第四章 JSP(一)
- 第五章 JSP(二)
- 第六章 MVC設計模式
- 第七章 Cookie
- 第八章 Session
- 練習 二 . 簡易版購物車
- 第九章 EL表達式
- 第十章 JSTL
- 第十一章 過濾器
- 第十二章 監聽器
- 第十三章 文件的上傳與下載
- 復習總結
- 如何手動啟動Tomcat
- 如何修改Tomcat端口號
- 如何在web.xml中配置Servlet
- Servlet生命周期
- load-on-startup參數
- Servlet映射路徑
- POST和GET的區別
- JSP中9個隱式對象及功能
- 請求轉發及請求重定向的區別
- JSP指令有哪些
- 簡述對MVC設計模式的理解
- 簡述Cookie機制
- 簡述Session機制
- HttpSession的生命周期
- Cookie和Session有什么區別
- 簡述創建過濾器步驟
- 過濾器經典案例--統一編碼字符集
- getParameter與getAttribute的區別
- JSP頁面中可以包含哪些元素
- web應用中,是如何跟蹤用戶的
- InteliJ創建web項目