Filter過(guò)濾器 是什么
java web 中的過(guò)濾器可以攔截所有訪問(wèn)web資源的請(qǐng)求或響應(yīng)操作。
Filter過(guò)濾器 有什么用
- 攔截
- 數(shù)據(jù)處理
- 統(tǒng)一控制
Filter過(guò)濾器 如何用
使用步驟
- 創(chuàng)建一個(gè)類實(shí)現(xiàn)Filter接口
- 重寫接口中方法 doFilter 方法是真正過(guò)濾的。
- 在web.xml文件中配置
注意
在Filter的doFilter方法如果沒(méi)有執(zhí)行chain.doFilter(request,response)
那么資源是不會(huì)被訪問(wèn)到的。
示例
public class Myfilter2 implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("Myfilter2 執(zhí)行了");
//放行
chain.doFilter(request, response);
System.out.println("Myfilter2 攔截結(jié)束了");
}
public void init(FilterConfig fConfig) throws ServletException {
}
}
<filter>
<filter-name>MyFilter3</filter-name>
<filter-class>cn.leyue.filter.MyFilter3</filter-class>
</filter>
<filter-mapping>
<filter-name>MyFilter3</filter-name>
<url-pattern>/servlet/indexServlet</url-pattern>
</filter-mapping>
FilterChain
FilterChain是servlet 容器為開(kāi)發(fā)人員提供的對(duì)象,他提供了對(duì)某一個(gè)資源的已過(guò)濾請(qǐng)求調(diào)用鏈的視圖喂窟。
過(guò)濾器使用FilterChain調(diào)用鏈中的下一個(gè)過(guò)濾器。
如果調(diào)用的過(guò)濾器是鏈中的最后一個(gè)過(guò)濾器 則調(diào)用鏈末尾的資源。
怎樣可以形成一個(gè)Filter鏈类垦?
只要多個(gè)Filter 對(duì)同一個(gè)資源進(jìn)行攔截可以形成Filter鏈
怎樣確定Filter的執(zhí)行順序
由<filter-mapping>來(lái)確定
Filter 生命周期
- 當(dāng)服務(wù)器啟動(dòng),會(huì)創(chuàng)建Filter對(duì)象城须,并調(diào)用init方法蚤认,只調(diào)用一次
- 當(dāng)訪問(wèn)資源時(shí),路徑與Filter的攔截路徑匹配糕伐,會(huì)執(zhí)行Filter中的doFilter方法砰琢,這個(gè)方法
是真正攔截操作的方法。 - 當(dāng)服務(wù)器關(guān)閉時(shí),會(huì)調(diào)用Filter的destroy 方法來(lái)進(jìn)行銷毀操作陪汽。
FilterConfig
在Filter的init 方法上有一個(gè)參數(shù)训唱,類型就是FilterConfig,
FilterConfig它是Filter的配置對(duì)象挚冤,它可以完成以下功能:
* 獲取Filter名稱
* 獲取Filter初始化參數(shù)
* 獲取ServletContext 對(duì)象
getFilterName() getInitParameter(String name)
getInitParameterNames() getServletContext();
* 怎樣在Filter中獲取一個(gè)FilterConfig對(duì)象况增?
private FilterConfig fConfig;
public void init(FilterConfig fConfig) throws ServletException {
this.fConfig = fConfig;
}
Filter 配置
基本配置
<filter>
<filter-name>filter</filter-name>
<filter-class>filter類的包名.類名</filter-class>
</filter>
<filter-mapping>
<filter-name>filter 名稱</filter-name>
<filter-pattern>路徑</filter-pattern>
</filter-mapping>
<url-pattern>
完全匹配 以“/demo”開(kāi)始,不包含通配符
目錄匹配 以“/”開(kāi)始训挡,以*結(jié)束
擴(kuò)展名匹配 *.xxx 不能寫成 /*.xxx
<servlet-name>
<filter>
<filter-name>MyFilter3</filter-name>
<filter-class>cn.leyue.filter.MyFilter3</filter-class>
</filter>
<filter-mapping>
<filter-name>MyFilter3</filter-name>
<url-pattern>/servlet/indexServlet</url-pattern>
</filter-mapping>
<dispatcher>
<filter-mapping>
<filter-name>MyFilter3</filter-name>
<url-pattern>/servlet/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
可以取的值有 REQUEST FORWARD ERROR INCLUDE
它的作用是:當(dāng)以什么方式去訪問(wèn)web資源時(shí)澳骤,進(jìn)行攔截操作.
1.REQUEST 當(dāng)是從瀏覽器直接訪問(wèn)資源,或是重定向到某個(gè)資源時(shí)進(jìn)行攔截方式配置的 它也是默認(rèn)值
2.FORWARD 它描述的是請(qǐng)求轉(zhuǎn)發(fā)的攔截方式配置
3.ERROR 如果目標(biāo)資源是通過(guò)聲明式異常處理機(jī)制調(diào)用時(shí)澜薄,那么該過(guò)濾器將被調(diào)用宴凉。除此之外,過(guò)濾器不會(huì)被調(diào)用表悬。
4.INCLUDE 如果目標(biāo)資源是通過(guò)RequestDispatcher的include()方法訪問(wèn)時(shí)弥锄,那么該過(guò)濾器將被調(diào)用。除此之外蟆沫,該過(guò)濾器不會(huì)被調(diào)用
md5 加密
public static String md5(String plainText) {
byte[] secretBytes = null;
try {
secretBytes = MessageDigest.getInstance("md5").digest(
plainText.getBytes());
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("沒(méi)有md5這個(gè)算法籽暇!");
}
String md5code = new BigInteger(1, secretBytes).toString(16);
for (int i = 0; i < 32 - md5code.length(); i++) {
md5code = "0" + md5code;
}
return md5code;
}
全局的編碼過(guò)濾器
public class EncodingFilter implements Filter {
/**
* Default constructor.
*/
public EncodingFilter() {
// TODO Auto-generated constructor stub
}
/**
* @see Filter#destroy()
*/
public void destroy() {
// TODO Auto-generated method stub
}
/**
* @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
*/
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
req.setCharacterEncoding("utf-8");
MyRequest myRequst = new MyRequest(req);
chain.doFilter(myRequst, response);
}
/**
* @see Filter#init(FilterConfig)
*/
public void init(FilterConfig fConfig) throws ServletException {
// TODO Auto-generated method stub
}
/**
* 實(shí)現(xiàn)與被包裝對(duì)象相同的接口
* 定義一個(gè)與包裝類相同對(duì)象的引用
* 定義一個(gè)構(gòu)造方法,把被包裝對(duì)象傳過(guò)來(lái)
* 對(duì)于不需要改寫方法饭庞,直接調(diào)用
* 對(duì)于無(wú)需要改寫方法戒悠,寫自己的方法體
*/
class MyRequest extends HttpServletRequestWrapper {
HttpServletRequest request;
public MyRequest(HttpServletRequest request) {
super(request);
this.request = request;
}
@Override
public String getParameter(String name) {
if(getParameterMap().get(name)==null) {
return null;
}
return getParameterMap().get(name)[0];
}
@Override
public String[] getParameterValues(String name) {
return getParameterMap().get(name);
}
private boolean flag = true;
@Override
public Map<String, String[]> getParameterMap() {
//獲取請(qǐng)求方式
String method = request.getMethod();
if(method.equalsIgnoreCase("post")) {
//處理亂碼
try {
request.setCharacterEncoding("utf-8");
return request.getParameterMap();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
} else if(method.equalsIgnoreCase("get")) {
Map<String, String[]> map = this.request.getParameterMap();
if (!flag) {
for (Map.Entry<String, String[]> m : map.entrySet()) {
String[] values = m.getValue();
for (int i = 0; i < values.length; i++) {
try {
//get方式處理亂碼
values[i] = new String(values[i].getBytes("ISO-8859-1"), "utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
flag =true;
}
return map;
}
return super.getParameterMap();
}
}
}
2016.11.6