什么是Filter(过滤器)?
Filter也称之为过滤器,它是Servlet技术中最实用的技术,Web开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。
它主要用于对用户请求进行预处理,也可以对HttpServletResponse进行后处理。使用Filter的完整流程:Filter对用户请求进行预处理,接着将请求交给Servlet进行处理并生成响应,最后Filter再对服务器响应进行后处理。
过滤器原理
当我们使用过滤器时,过滤器会对游览器的请求进行过滤,过滤器可以动态的分为3个部分,1.放行之前的代码,2.放行,3.放行后的代码,这3个部分分别会发挥不同作用。
第一部分代码会对游览器请求进行第一次过滤,然后继续执行
第二部分代码就是将游览器请求放行,如果还有过滤器,那么就继续交给下一个过滤器
第三部分代码就是对返回的Web资源再次进行过滤处理
我们使用过滤器,也就是说,不止请求会经过过滤器,我们的响应也会经过过滤器。
创建过滤器(Filter)
1.先书写一个普通类,如果普通类实现了Filter接口,则此类为过滤器类
public class Filter1 implements Filte
-
让普通类实现接口中的抽象方法,然后决定是否放行
package com.bjpowernode.filter; import javax.servlet.*; import java.io.IOException; public class Filter1 implements Filter { @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { } }
Filter接口有3个方法,但是这里我们值实现一个,我们实现了一个doFilter方法,这个方法就是我们写过滤代码的地方,(另外两个我们会在生命周期里面讲解)
3.在web.xml文件配置过滤器的过滤路径或者通过注解方式配置(Filter的两种配置方式)
3.1注解方式
如果我们使用注解方式的话需要先了解属性,那么我们来先看一下源码
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package javax.servlet.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.servlet.DispatcherType;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface WebFilter {
String description() default "";
String displayName() default "";
WebInitParam[] initParams() default {};
String filterName() default "";
String smallIcon() default "";
String largeIcon() default "";
String[] servletNames() default {};
String[] value() default {};
String[] urlPatterns() default {};
DispatcherType[] dispatcherTypes() default {DispatcherType.REQUEST};
boolean asyncSupported() default false;
}
里面的配置还是很多的,这里我们只讲解我们需要使用的
filterName:该filter的名字
initParams:初始化参数
displayName:filter显示名称
servletNames:指定对哪些servlet进行过滤
asyncSupported:是否支持异步模式
urlPatterns:指定拦截路径
value:指定拦截路径 (urlPatterns和value是一样的。只能配置一个,两个都配置就会报错)
注解配置
@WebFilter("/*") <!--过滤的路径-->这里的(/*)表示过滤所有的,里面的多个参数用 **,** 进行分隔。
注意:如果我们仅仅需要配置一个拦截路径,那么我们可以直接简写@WebLister(“拦截路径”),如@WebFilter(“/*”)就是拦截所有请求。
3.2xml方式配置
<?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>filter1</filter-name>
<filter-class>com.bjpowernode.filter.Filter1</filter-class> <!--过滤器-->
</filter>
<filter-mapping>
<filter-name>filter1</filter-name>
<url-pattern>/*</url-pattern> <!--过滤的路径-->表示过滤所有的
</filter-mapping>
</web-app>
这个就是xml配置方式,里面属性都是一样的,这个和Servlet的配置方式基本一样,这里就不再赘述了。
使用过滤器(Filter)
我们先来感受一下如何使用过滤器,其它细节我们后面会一 一讲解。
package com.bjpowernode.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
@WebFilter("/*") // 注解方式
public class Filter1 implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("对request进行过滤");
filterChain.doFilter(servletRequest,servletResponse); // 放行
System.out.println("对request完成过滤");
}
}
然后 启动服务器,然后我们在游览器中输入<http://localhost:8080你会看到如下图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CFqohHGR-1667654438454)(C:\Users\ADMINI~1\AppData\Local\Temp\1667648186406.png)]
注意:上面之所以出现这个页面是因为我们服务器下面没有资源。
然后我们打开后台你会看到如下图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FjL0XkeO-1667654438457)(C:\Users\ADMINI~1\AppData\Local\Temp\1667648386995.png)]
从上面的执行结果来看,我们此时就可以得出结论,过滤器是不会管资源是否存在的,而只会对配置的拦截路径进行拦截
1.1 Fliter(过滤器)的生命周期
同servlet对象一样,Filter对象的创建也是交给web服务器完成的,在web服务器创建和使用及最后销毁filter时,会调用filter对应的方法
初始化方法:
public void init(FilterConfig filterConfig);
和我们编写的Servlet程序一样,Filter的创建和销毁由WEB服务器负责。 web 应用程序启动时,web 服务器将创建Filter 的实例对象,并调用其init方法,读取web.xml配置,完成对象的初始化功能,从而为后续的用户请求作好拦截的准备工作(filter对象只会创建一次,init方法也只会执行一次)。开发人员通过init方法的参数,可获得代表当前filter配置信息的FilterConfig对象。
拦截请求方法
public void doFilter
这个方法完成实际的过滤操作。当客户请求访问与过滤器关联的URL的时候,Servlet过滤器将先执行doFilter方法。FilterChain参数用于访问后续过滤器。
销毁方法**😗*
public void destroy();
Filter对象创建后会驻留在内存,当web应用移除或服务器停止时才销毁。在Web容器卸载 Filter 对象之前被调用。该方法在Filter的生命周期中仅执行一次。在这个方法中,可以释放过滤器使用的资源。
生命周期三个阶段的小小总结
Filter有3个阶段,分别是初始化,拦截和过滤,销毁。
1.初始化阶段:当服务器启动时,我们的服务器(Tomcat)就会读取配置文件,扫描注解,然后来创建我们的Filter。
2.拦截和过滤阶段:只要请求资源的路径和拦截的路径相同,那么过滤器就会对请求进行过滤,这个阶段在服务器运行过程中会一直循 环。
3.销毁阶段:当服务器(Tomcat)关闭时,服务器创建的Filter也会随之销毁。
代码演示
package com.bjpowernode.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
@WebFilter("/*") // 注解方式
public class Filter1 implements Filter {
/*
* 1. Filter的创建时机是 服务器启动的时候
* 2. init方法只调用一次,并紧跟构造器方法调用之后
* 3. doFilter 方法,每次请求都会进入 该方法 ,并且 是在调用service之前,能不能进入service 方法,就要看 doFilter 方法有没有放行
* 4. destroy 方法,在服务器正常关闭的请情况下,调用
*
* */
// 构造器
public Filter1 (){
System.out.println("我是构造器!");
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("init()"); // 这个是初始化方法,在服务器启动的时候就会执行
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//这个方法就是过滤和拦截的方法,当请求和拦截匹配时调用
System.out.println("doFilter");
}
@Override
public void destroy() {
// 这个方法是销毁方法,只有在项目正常关闭的情况下才会执行
System.out.println("destroy");
}
}
启动服务器后台输出
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-v5HzRUK1-1667654438458)(C:\Users\ADMINI~1\AppData\Local\Temp\1667650406113.png)]
游览器访问
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-S2AC4LPr-1667654438460)(C:\Users\ADMINI~1\AppData\Local\Temp\1667650534079.png)]
游览器访问过后后台输出
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oREeEfgt-1667654438461)(C:\Users\ADMINI~1\AppData\Local\Temp\1667650587412.png)]
在这里我们可以得出结论
在服务器启动的时候过滤器的构造器会执行,随后init()方法会执行,并且这他们两个只会在服务器启动的时候执行一次
然后我们再次通过游览器访问
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FjpK8P1v-1667654438462)(C:\Users\ADMINI~1\AppData\Local\Temp\1667650862167.png)]
后台输出
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cGj1IFQk-1667654438464)(C:\Users\ADMINI~1\AppData\Local\Temp\1667650911939.png)]
在这里我们又得到一个结论
doFilter方法只会在每次有人访问的时候执行
关闭服务器后台输出
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9jJZErgh-1667654438465)(C:\Users\ADMINI~1\AppData\Local\Temp\1667651073758.png)]
执行的结果都和我们预想的一样,这也就验证了我们上面所学生命周期结果是相吻合的了。
FilterConfig
FilterConfig 类见名知义, 它是 Filter 过滤器的配置文件类。
Tomcat 每次创建 Filter 的时候, 也会同时创建一个 FilterConfig 类, 这里包含了 Filter 配置文件的配置信息。
FilterConfig 类的作用是获取 filter 过滤器的配置内容
1、 获取 Filter 的名称 filter-name 的内容
2、 获取在 Filter 中配置的 init-param 初始化参数
3、 获取 ServletContext 对象
FilterConfig的四个方法
- getFilterName():获取filter的名称
- getServletContext():获取ServletContext
- getInitparamter(String var1):获取配置的初始参数的值
- getInitParamterNames():获取配置的所有参数名称
FilterConfig实例运用
代码实列
package com.bjpowernode.filter;
import javax.servlet.*;
import java.io.IOException;
import java.util.Enumeration;
public class FilterConfig1 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
Enumeration<String> names = filterConfig.getInitParameterNames(); //getInitParameterNames()得到所有配置参数的的名称
// 遍历出所有的参数信息并打印到控制台
while (names.hasMoreElements()) {
String name = names.nextElement();
System.out.println(name+" = "+filterConfig.getInitParameter(name));
}
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
}
@Override
public void destroy() {
}
}
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_4_0.xsd"
version="4.0">
<--这是前面测试用的不用管注释而已-->
<!--<filter>
<filter-name>filter1</filter-name>
<filter-class>com.bjpowernode.filter.Filter1</filter-class> <!–过滤器–>
</filter>
<filter-mapping>
<filter-name>filter1</filter-name>
<url-pattern>/*</url-pattern> <!–过滤的路径–>
</filter-mapping>-->
<filter>
<filter-name>myFilterConfig</filter-name>
<filter-class>com.bjpowernode.filter.FilterConfig1</filter-class>
<init-param>
<param-name>driver</param-name>
<param-value>com.mysql.jdbc.Driver</param-value>
</init-param>
<init-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost:3306/web</param-value>
</init-param>
<init-param>
<param-name>username</param-name>
<param-value>root</param-value>
</init-param>
<init-param>
<param-name>password</param-name>
<param-value>123456</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>myFilterConfig</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
启动服务器输出结果如下图所示
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0llKxuNM-1667654438466)(C:\Users\ADMINI~1\AppData\Local\Temp\1667653718879.png)]
FilterConfig读取配置文件演示完毕。
关于过滤器的讲解到这里就结束了,当然这上面讲的也很多不足之处,关于过滤器更多的知识点各位在另行查阅相关的文章
谢谢你的阅读!
56
myFilterConfig
/*
启动服务器输出结果如下图所示
[外链图片转存中...(img-0llKxuNM-1667654438466)]
FilterConfig读取配置文件演示完毕。
关于过滤器的讲解到这里就结束了,当然这上面讲的也很多不足之处,关于过滤器更多的知识点各位在另行查阅相关的文章
写的不好还请大佬们谅解
谢谢你的阅读!