一撒强、Filter介紹
過濾器概念
- 客戶端與服務(wù)器資源文件之間的一道過濾網(wǎng)笙什;
- 管理Web服務(wù)器的所有資源琐凭,例如對JSP、Servlet胚吁、靜態(tài)圖片文件或靜態(tài)HTML文件等進(jìn)行攔截愁憔;
- 可以過濾幾乎所有的請求,完成一些特殊的功能蕉毯;
- Filter依賴于Servlet容器,屬于Servlet規(guī)范的一部分进肯;
- Filter的執(zhí)行由Servlet容器回調(diào)完成棉磨;
- Filter的生命周期由Servlet容器管理。
過濾器使用場景
完成通用的操作:登陸驗證环形、URL級別的權(quán)限訪問控制抬吟、壓縮響應(yīng)信息统抬、統(tǒng)一編碼處理、過濾敏感字符等等钙畔。
過濾器實現(xiàn)步驟
- 定義一個類金麸,實現(xiàn)javax.servlet.Filter接口;
- 復(fù)寫方法揍魂,尤其是doFilter方法愉烙,必須實現(xiàn)解取;
- 配置過濾器信息返顺。
- web.xml
- @WebFilter注解
- @Configuration配置類
過濾器生命周期
Filter的生命周期由Servlet容器管理:
- init:在服務(wù)器啟動后遂鹊,會創(chuàng)建Filter對象,然后調(diào)用init方法慧邮。只執(zhí)行一次。用于加載資源耻矮。
- doFilter:每一次請求被攔截資源時忆谓,會執(zhí)行。執(zhí)行多次哨免。
- destroy:在服務(wù)器關(guān)閉后昙沦,F(xiàn)ilter對象被銷毀盾饮。如果服務(wù)器是正常關(guān)閉,則會執(zhí)行destroy方法芍碧。只執(zhí)行一次号俐。用于釋放資源吏饿。
過濾器攔截路徑配置
- 具體的資源路徑: /hello.jsp 只訪問hello.jsp資源時,過濾器才會被執(zhí)行
- 攔截目錄: /hello/* 訪問/hello下的所有資源時贞远,過濾器才會被執(zhí)行
- 后綴名攔截: *.jsp 訪問所有后綴名為jsp資源時笨忌,過濾器才會被執(zhí)行
- 攔截所有資源: /* 訪問所有資源時,過濾器才會被執(zhí)行
過濾器攔截請求調(diào)度方式配置
- 請求調(diào)度方式
- REQUEST:默認(rèn)值袱结。瀏覽器直接請求資源
- FORWARD:轉(zhuǎn)發(fā)訪問資源
- NCLUDE:包含訪問資源
- ERROR:錯誤跳轉(zhuǎn)資源
- ASYNC:異步訪問資源
- web.xml配置:<filter-mapping>中的<dispatcher>標(biāo)簽
- @WebFilter注解配置:dispatcherTypes屬性
- @Configuration配置類:FilterRegistrationBean對象的dispatcherTypes屬性
過濾器鏈(多個過濾器)調(diào)用的先后順序
- web.xml: <filter-mapping>定義在上邊的垢夹,先執(zhí)行
- @WebFilter注解:按照類名的字符串比較規(guī)則比較维费,值小的先執(zhí)行(注意不是配置的filter的名字)
- 如: AFilter 和 BFilter,AFilter就先執(zhí)行了而晒。
- 如: AFilter17 和 AFilter6欣硼,AFilter17就先執(zhí)行了。
- @Order注解:值小的先執(zhí)行
- Configuration配置類:FilterRegistrationBean對象的order屬性:值小的先執(zhí)行
- @WebFilter指定的過濾器優(yōu)先級都高于FilterRegistrationBean配置的過濾器
過濾器鏈(多個過濾器)執(zhí)行的先后順序
- FilterChain的執(zhí)行順序遵循先進(jìn)后出原則
- 以doFilter方法中調(diào)用filterChain.doFilter(servletRequest,servletResponse)的位置為準(zhǔn)豹障,這里放行到下一個過濾器焦匈;
- filterChain.doFilter位置之前的代碼先執(zhí)行缓熟,然后再放行;
- filterChain.doFilter位置之后的代碼是響應(yīng)回來后再執(zhí)行垦写;
- Request請求被所有的Filter處理之后,返回的順序是從最后一個開始返回,直到返回給客戶端
二彰触、Filter使用
Java Web使用Filter
基于實現(xiàn)Filter + web.xml配置
創(chuàng)建一個類况毅,實現(xiàn)javax.servlet.Filter接口,尤其是doFilter方法么鹤;
package com.liutit.filter;
import javax.servlet.*;
import java.io.IOException;
public class DemoFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
Filter.super.init(filterConfig);
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// 客戶端發(fā)送請求經(jīng)過過濾器蒸甜,
// 這里一般處理請求對象Request
System.out.println("filter in....");
// 放行
filterChain.doFilter(servletRequest,servletResponse);
// 服務(wù)器響應(yīng)請求后毡们,經(jīng)過此處,然后再到客戶端,
// 這里一般處理響應(yīng)對象Response
System.out.println("filter out....");
}
@Override
public void destroy() {
Filter.super.destroy();
}
}
在web.xml中配置過濾器信息红氯;
<?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_3_1.xsd"
version="3.1">
<filter>
<filter-name>demo</filter-name>
<filter-class>com.liutit.filter.DemoFilter</filter-class>
</filter>
<!-- filter-mapping標(biāo)簽定義的位置決定多個過濾器調(diào)用的順序痢甘,由上而下依次調(diào)用, 與filter標(biāo)簽的定義位置無關(guān)-->
<filter-mapping>
<filter-name>demo</filter-name>
<!-- 攔截路徑 -->
<url-pattern>/*</url-pattern>
<!-- 攔截方式 -->
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
</web-app>
基于實現(xiàn)Filter + @WebFilter注解
創(chuàng)建一個類者铜,實現(xiàn)javax.servlet.Filter接口放椰,尤其是doFilter方法砾医,并在類上添加@WebFilter注解;
package com.liutit.filter;
import javax.servlet.*;
import java.io.IOException;
@WebFilter("/*")
public class DemoFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
Filter.super.init(filterConfig);
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// 客戶端發(fā)送請求經(jīng)過過濾器压恒,
// 這里一般處理請求對象Request
System.out.println("filter in....");
// 放行
filterChain.doFilter(servletRequest,servletResponse);
// 服務(wù)器響應(yīng)請求后探赫,經(jīng)過此處撬呢,然后再到客戶端,
// 這里一般處理響應(yīng)對象Response
System.out.println("filter out....");
}
@Override
public void destroy() {
Filter.super.destroy();
}
}
Spring Boot使用Filter
pom.xml導(dǎo)入pring-boot-starter-web包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
基于實現(xiàn)Filter + 配置Configuration類
package com.liutit.filter;
import javax.servlet.*;
import java.io.IOException;
public class DemoFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
Filter.super.init(filterConfig);
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// 客戶端發(fā)送請求經(jīng)過過濾器,
// 這里一般處理請求對象Request
System.out.println("filter in....");
// 放行
filterChain.doFilter(servletRequest,servletResponse);
// 服務(wù)器響應(yīng)請求后潭千,經(jīng)過此處借尿,然后再到客戶端,
// 這里一般處理響應(yīng)對象Response
System.out.println("filter out....");
}
@Override
public void destroy() {
Filter.super.destroy();
}
}
Configuration類
package com.liutit.config;
import com.liutit.filter.DemoFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.servlet.DispatcherType;
@Configuration
public class FilterConfiguration {
@Bean
public FilterRegistrationBean registrationFilter() {
FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
// 設(shè)置過濾器
filterRegistration.setFilter(new DemoFilter());
// 指定url策略
filterRegistration.addUrlPatterns("/*");
// 指定過濾請求調(diào)度方式,默認(rèn)REQUEST
filterRegistration.setDispatcherTypes(DispatcherType.REQUEST);
// 設(shè)置過濾器名稱
filterRegistration.setName("demoFilter");
// 過濾器順序:數(shù)字越小茂契,越先執(zhí)行
filterRegistration.setOrder(1);
return filterRegistration;
}
}
基于實現(xiàn)Filter + @WebFilter注解 + @ServletComponentScan注解
package com.liutit.filter;
import javax.servlet.*;
import java.io.IOException;
@Order(1)
@WebFilter("/*")
public class DemoFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
Filter.super.init(filterConfig);
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// 客戶端發(fā)送請求經(jīng)過過濾器掉冶,
// 這里一般處理請求對象Request
System.out.println("filter in....");
// 放行
filterChain.doFilter(servletRequest,servletResponse);
// 服務(wù)器響應(yīng)請求后,經(jīng)過此處战秋,然后再到客戶端讨韭,
// 這里一般處理響應(yīng)對象Response
System.out.println("filter out....");
}
@Override
public void destroy() {
Filter.super.destroy();
}
}
啟動類上添加@ServletCoponentScan注解
在啟動類上使用@ServletComponentScan注解后,
Servlet狰闪、Filter蹬铺、Listener可以直接通過@WebServlet甜攀、@WebFilter、@WebListener注解自動注冊恒序。
package com.liutit;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
@SpringBootApplication
@ServletComponentScan
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}