Filter&Listener
Filter&Listener
今日內容
- Filter:過濾器
- Listener:監聽器
Filter:過濾器
-
概念 *web中的過濾器:當訪問伺服器資源時,過濾器可以將請求攔截下來,完成一些特殊的功能。
-
過濾器的作用 *一般用於完成通用的操作。如:登入驗證、統一編碼處理、敏感字元過濾…
-
快速入門 *步驟:
- 定義一個類,實現介面Filter
- 複寫方法
- 配置攔截路徑 i. web.xml ii. 註解
*程式碼 :
@WebFilter("/*")//訪問所有資源之前,都會執行該過濾器 public class FilterDemo1 implements Filter
-
過濾器細節:
- web.xml配置
<filter> <filter-name>demo1</filter-name> <filter-class>cn.itcast.web.filter.FilterDemo1</
-
過濾器執行流程
- 執行過濾器
- 執行放行後的資源
- 回來執行過濾器放行程式碼下邊的程式碼
-
過濾器生命週期方法
- init:在伺服器啟動後,會建立Filter物件,然後呼叫init方法。只執行一次。用於載入資源。
- doFilter:每一次請求被攔截資源時,會執行多次。
- destroy:在伺服器關閉後,Filter物件被銷燬。如果伺服器是被正常關閉的,會執行destroy方法,只執行一次,用於釋放資源。
-
過濾器配置詳解 *攔截路徑配置:
- 具體資源路徑:/index.jsp 只有訪問index,jsp資源時,過濾器才會被執行。
- 攔截目錄:/user/* 訪問/user下的所有資源時,過濾器都會被執行
- 字尾名攔截:*.jsp 訪問所有後綴名為jsp資源時,過濾器才會被執行
- 攔截所有資源:/* 訪問所有資源時,過濾器都會被執行
*攔截方式配置: i. 註解配置:設定dispatcherTypeshux 1. REQUEST:預設值。瀏覽器直接請求資源。 2. FORWARD:轉發訪問資源。 3. INCLUDE:包含訪問資源。 4. ERROR:錯誤跳轉資源。 5. ASYNC:非同步訪問資源。 ii. web.xml配置 *設定<dispatcher></dispatcher>標籤即可
-
過濾器鏈(配置多個過濾器) *執行順序:如果有兩個過濾器:過濾器1和過濾器2
- 過濾器1
- 過濾器2
- 資源執行
- 過濾器2
- 過濾器1
*過濾器先後順序問題: 1. 註解和配置:按照類名的字串比較規則比較,較小的先執行 2. web.xml配置<filter-mapping>誰定義在上邊,誰先執行
- 案列
- 案例1_登入驗證 * 需求: 1. 訪問day17_case案例的資源。驗證其是否登入 2. 如果登入了,則直接放行。 3. 如果沒有登入,則跳轉到登入頁面,提示"您尚未登入,請先登入"。
package web.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebFilter("/*")
public class LoginFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
HttpServletRequest request=(HttpServletRequest)req;
String uri = request.getRequestURI();
if (uri.contains("/login.jsp")||uri.contains("/loginUserServlet")||uri.contains("/checkCode")||uri.contains("/css/")||uri.contains("/fonts/")||uri.contains("/js/")){
chain.doFilter(req, resp);
}
else {
HttpSession session = request.getSession();
Object user = session.getAttribute("user");
if (user!=null){
chain.doFilter(request,resp);
}else {
request.setAttribute("login_msg","您尚未登入,請先登入!");
request.getRequestDispatcher("/login.jsp").forward(request,resp);
}
}
}
public void init(FilterConfig config) throws ServletException {
}
}
- 案例2_敏感詞彙過濾
-
需求: 1. 對day17_case案例錄入的資料進行敏感詞彙過濾 2. 敏感詞彙參考《敏感詞彙.txt》 3. 如果是敏感詞彙,替換為 ***
-
分析: 1. 對request物件進行增強。增強獲取引數相關方法 2. 放行。傳遞代理物件
package web.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
@WebFilter("/*")
public class SensitiveWordFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
ServletRequest proxy_req=(ServletRequest) Proxy.newProxyInstance(req.getClass().getClassLoader(), req.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 增強Parameter方法
//判斷是否有Parameter方法
if (method.getName().equals("getParameter")){
//增強返回值
//獲取返回值
String value = (String) method.invoke(req, args);
if (value!=null){
for (String s : list) {
if (value.contains(s)){
value = value.replaceAll(s, "***");
}
}}
return value;
}
if (method.getName().equals("getParameterMap")){
Map<String,String[]> value=(Map<String,String[]>)method.invoke(req,args);
if (value!=null){
for (String s : list) {
Set<String> keySet = value.keySet();
for (String key : keySet) {
String[] strs = value.get(key);
for (int i = 0; i < strs.length; i++) {
if (strs[i].contains(s)){
strs[i]=strs[i].replaceAll(s,"***");
}
}
}
}
return value;
}
}
if (method.getName().equals("getParameterValues")){
//增強返回值
//獲取返回值
String[] value = (String[]) method.invoke(req, args);
if (value!=null){
for (String s : list) {
for (String str : value) {
if (str.contains(s)){
str=str.replaceAll(s,"***");
}
}
}
return value;
}
}
return method.invoke(req,args);
}
});
chain.doFilter(proxy_req, resp);
}
private List<String> list=new ArrayList<String>();
public void init(FilterConfig config) throws ServletException {
try{
ServletContext servletContext = config.getServletContext();
String realPath = servletContext.getRealPath("/WEB-INF/classes/敏感詞彙.txt");
BufferedReader br=new BufferedReader(new FileReader(realPath));
String len;
while((len=br.readLine())!=null){
list.add(len);
}
br.close();
System.out.println(list);
} catch (Exception e){
e.printStackTrace();
}
}
}
Listener:監聽器
-
概念:web的三大元件之一。
-
事件的監聽機制:
- 事件:一件事情
- 事件源:事件發生的地方
- 監聽器:一個物件
- 註冊監聽:將事件、事件源、監聽器綁在一起。當事件源上發生某個事件後,執行監聽器程式碼
-
ServletContextListener:監聽ServletContext物件的建立和銷燬
-
方法: * void contextDestroyed(ServletContextEvent sce):ServletContext物件被銷燬之前會呼叫該方法 * void contextInitialized(ServletContextEvent sce):ServletContext物件建立後會呼叫該方法
-
步驟: * 定義一個類,實現ServletContextListener介面 * 複寫方法 * 配置 i. web.xml <listener><listener-class>全類名</listener-class> 指定初始化引數<context-param> ii. 註解: @WebListener
-