Java Web之過濾器(Filter)

https://blog.csdn.net/yuzhiqiang_1993/article/details/81288912java

過濾器(Filter)
過濾器實際上就是對web資源進行攔截,作一些處理後再交給下一個過濾器或servlet處理
一般都是用來攔截request進行處理的,也能夠對返回的response進行攔截處理web

大概流程圖以下服務器

 

應用場景
自動登陸
統一設置編碼格式
訪問權限控制
敏感字符過濾等cookie

建立Filter##
在Servlet中咱們通常都會對request和response中的字符集編碼進行配置,若是Servlet過多字符集編碼發生變化時修改起碼會很麻煩,這些通用的字符集編碼配置等工做咱們能夠放到Filter中來實現。
下面咱們來建立一個處理字符集編碼的Filter。app

右鍵包名—>new ---->Filter異步

 

輸入過濾器名稱,跟建立Servlet同樣,這裏咱們直接使用**@WebFilter**註解,再也不去web,xml中進行配置了。jsp

 

建立完成後默認代碼,能夠看到,CharsetFilter實現了Filter接口,實現了3個方法。3個方法的做用已經在註釋中寫清楚了。網站

package filter;編碼

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;url

@WebFilter(filterName = "CharsetFilter")
public class CharsetFilter implements Filter {
public void destroy() {
/*銷燬時調用*/
}

public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
/*過濾方法 主要是對request和response進行一些處理,而後交給下一個過濾器或Servlet處理*/

chain.doFilter(req, resp);//交給下一個過濾器或servlet處理
}

public void init(FilterConfig config) throws ServletException {

/*初始化方法 接收一個FilterConfig類型的參數 該參數是對Filter的一些配置*/

}

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
配置Filter
可配置的屬性有這些

 

經常使用配置項
urlPatterns
配置要攔截的資源

以指定資源匹配。例如"/index.jsp"
以目錄匹配。例如"/servlet/*"
之後綴名匹配,例如"*.jsp"
通配符,攔截全部web資源。"/*"
**initParams **
配置初始化參數,跟Servlet配置同樣

例如

initParams = {
@WebInitParam(name = "key",value = "value")
}
1
2
3
dispatcherTypes **
配置攔截的類型,可配置多個。默認爲DispatcherType.REQUEST**
例如

dispatcherTypes = {DispatcherType.ASYNC,DispatcherType.ERROR}
1
其中DispatcherType是個枚舉類型,有下面幾個值

FORWARD,//轉發的
INCLUDE,//包含在頁面的
REQUEST,//請求的
ASYNC,//異步的
ERROR;//出錯的
1
2
3
4
5
下面咱們來對CharsetFilter 代碼進行一下修改

package filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
import java.io.IOException;

@WebFilter(filterName = "CharsetFilter",
urlPatterns = "/*",/*通配符(*)表示對全部的web資源進行攔截*/
initParams = {
@WebInitParam(name = "charset", value = "utf-8")/*這裏能夠放一些初始化的參數*/
})
public class CharsetFilter implements Filter {
private String filterName;
private String charset;

public void destroy() {
/*銷燬時調用*/

System.out.println(filterName + "銷燬");
}

public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
/*過濾方法 主要是對request和response進行一些處理,而後交給下一個過濾器或Servlet處理*/
System.out.println(filterName + "doFilter()");
req.setCharacterEncoding(charset);
resp.setCharacterEncoding(charset);
chain.doFilter(req, resp);
}

public void init(FilterConfig config) throws ServletException {

/*初始化方法 接收一個FilterConfig類型的參數 該參數是對Filter的一些配置*/

filterName = config.getFilterName();
charset = config.getInitParameter("charset");

System.out.println("過濾器名稱:" + filterName);
System.out.println("字符集編碼:" + charset);

}

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
這樣一個簡單的字符集編碼處理的過濾器就完成了
咱們看看執行打印的結果


須要注意的是
過濾器是在服務器啓動時就會建立的,只會建立一個實例,常駐內存,也就是說服務器一啓動就會執行Filter的init(FilterConfig config)方法.
當Filter被移除或服務器正常關閉時,會執行destroy方法

多個Filter的執行順序
在咱們的請求到達Servle之間是能夠通過多個Filter的,通常來講,建議Filter之間不要有關聯,各自處理各自的邏輯便可。這樣,咱們也無需關心執行順序問題。
若是必定要確保執行順序,就要對配置進行修改了,執行順序以下

在web.xml中,filter執行順序跟<filter-mapping>的順序有關,先聲明的先執行
使用註解配置的話,filter的執行順序跟名稱的字母順序有關,例如AFilter會比BFilter先執行
若是既有在web.xml中聲明的Filter,也有經過註解配置的Filter,那麼會優先執行web.xml中配置的Filter
咱們寫個小例子看一下

新建3個Filter,加上以前的CharsetFilter一共四個

 

其中CharsetFilter和ABFilter是經過註解聲明的

CharsetFilter註解配置


@WebFilter(filterName = "CharsetFilter",
urlPatterns = "/*",/*通配符(*)表示對全部的web資源進行攔截*/
initParams = {
@WebInitParam(name = "charset", value = "utf-8")/*這裏能夠放一些初始化的參數*/
})
1
2
3
4
5
6
ABFilter

@WebFilter(filterName = "ABFilter",urlPatterns = "/*")
1
AFilter和BFilter是在web.xml配置的。
執行順序跟<filter>的順序無關
<filter-mapping>的順序才決定執行順序

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<filter>
<filter-name>AFilter</filter-name>
<filter-class>filter.AFilter</filter-class>
</filter>
<filter>
<filter-name>BFilter</filter-name>
<filter-class>filter.BFilter</filter-class>
</filter>

<!--這裏BFilter在AFilter以前-->
<filter-mapping>
<filter-name>BFilter</filter-name>
<url-pattern>/filter.jsp</url-pattern>
</filter-mapping>

<filter-mapping>
<filter-name>AFilter</filter-name>
<url-pattern>/filter.jsp</url-pattern>
</filter-mapping>


</web-app>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
每一個Filter添加了打印語句,以下
以ABFilter爲例

package filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@WebFilter(filterName = "ABFilter",urlPatterns = "/*")
public class ABFilter implements Filter {
private String filterName;

public void destroy() {
}

public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
System.out.println(filterName + " doFilter()");
chain.doFilter(req, resp);
}

public void init(FilterConfig config) throws ServletException {
filterName= config.getFilterName();
System.out.println("過濾器名稱:" + filterName +" init");
}

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
下面咱們來訪問filter.jsp看看打印結果

 

能夠看到,執行結果符合預期。
BFilter和AFilter是在web.xml中聲明的,且BFilter的<filter-mapping>在前,故BFilter在AFilter以前執行。
ABFilter和CharsetFilter是經過註解聲明的,故他倆在BFilter和AFilter以後執行,可是ABFilter的名稱以A開頭,故在CharsetFilter以前執行

 

訪問權限控制小例子##
下面咱們寫一個訪問控制權限控制的小例子。
咱們在瀏覽一些網站常常有這個狀況,沒有登陸時是不容許咱們訪其主頁的,只有登陸事後才能訪問。
下面咱們就用Filter簡單實現一下。

需求分析

登陸時將登陸的帳號密碼保存到cookie中,下次訪問時攜帶帳號和密碼,過濾器中進行校驗
用戶沒有登陸直接訪問主頁時,要跳轉到登陸頁面
登陸過濾器不對登陸頁面進行過濾
咱們先來看一下項目結構

 

這裏主要看一下LoginFilter的代碼

咱們在LoginFilter中對非登陸頁面的其餘jsp都會進行過濾,判斷cookie中是否攜帶了account和pwd。
若是有這兩個數據表示以前登陸過,那麼對數據進行校驗,正確的話就進行下一個操做。
不然的話,跳轉到登陸界面

package filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebFilter(filterName = "LoginFilter", urlPatterns = "*.jsp", dispatcherTypes = {})
public class LoginFilter implements Filter {
public void destroy() {
}

public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {


System.out.println("LoginFilter doFilter");

HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;

String url = request.getRequestURI();

System.out.println("請求的url:" + url);
/*登陸頁面不須要過濾*/

int idx = url.lastIndexOf("/");
String endWith = url.substring(idx + 1);


if (!endWith.equals("login.jsp")) {
/*不是登陸頁面 進行攔截處理*/

System.out.println("不是登陸頁面,進行攔截處理");

if (!isLogin(request)) {
System.out.println("沒有登陸過或者帳號密碼錯誤,跳轉到登陸界面");
response.sendRedirect("login.jsp");
} else {
System.out.println("已經登陸,進行下一步");
chain.doFilter(req, resp);
}

} else {

System.out.println("是登陸頁面,不進行攔截處理");
chain.doFilter(req, resp);
}


}


private boolean isLogin(HttpServletRequest request) {

Cookie[] cookies = request.getCookies();

String account = "";
String pwd = "";

if (cookies != null && cookies.length > 0) {
for (Cookie cookie : cookies) {
if (cookie.getName().equals("account")) {
account = cookie.getValue();
} else if (cookie.getName().equals("pwd")) {
pwd = cookie.getValue();
}
}
}

if (account.equals("") || pwd.equals("")) {
return false;

} else if (account.equals("yzq") && pwd.equals("123")) {
return true;
}


return false;
}

public void init(FilterConfig config) throws ServletException {
System.out.println("LoginFilter init");
}

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
執行效果

 

能夠看到,咱們在沒有登陸的狀況下直接去訪問index.jsp頁面時會自動跳轉到登陸頁面,在登陸成功後,再次直接訪問index頁面則能夠訪問。--------------------- 版權聲明:本文爲CSDN博主「喻志強」的原創文章,遵循CC 4.0 by-sa版權協議,轉載請附上原文出處連接及本聲明。原文連接:https://blog.csdn.net/yuzhiqiang_1993/article/details/81288912

相關文章
相關標籤/搜索