提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
首先来看一下官方文档的解释:
A filter is an object that performs filtering tasks on either the request to a resource (a servlet or static content), or on the response from a resource, or both.
过滤器是对对资源(servlet或静态内容)的请求或对来自资源的响应执行过滤任务的对象,或者对两者都执行过滤任务。
Filters perform filtering in the doFilter method. Every Filter has access to a FilterConfig object from which it can obtain its initialization parameters, and a reference to the ServletContext which it can use, for example, to load resources needed for filtering tasks.
过滤器在doFilter方法中执行过滤。每个Filter都可以访问FilterConfig对象,它可以从中获得初始化参数,还可以访问ServletContext的引用,例如,它可以使用ServletContext来加载筛选任务所需的资源。
Filters are configured in the deployment descriptor of a web application.
过滤器在web应用程序的部署描述符中配置。
Examples that have been identified for this design are:
Authentication Filters
Logging and Auditing Filters
Image conversion Filters
Data compression Filters
Encryption Filters
Tokenizing Filters
Filters that trigger resource access events
XSL/T filters
Mime-type chain Filter
已经确定的这种设计的例子有:
身份验证过滤器
日志和审计过滤器
图像转换过滤器
数据压缩过滤器
加密的过滤器
分过滤器
触发资源访问事件的过滤器
XSL / T过滤器
mime类型过滤器链
总结分析:
一个实现了特殊接口(Filter)的Java类. 实现对请求资源(jsp,servlet,html,)的过滤的功能. 过滤器是一个 运行在服务器的程序, 优先于请求资源(Servlet或者jsp,html)之前执行. 并且它是JavaWeb三大组件之一。另外两个是Servlet和Listener。 它是在2000年发布的Servlet2.3规范中加入的一个接口。是Servlet规范中非常实用的技术。 它可以对web应用中的所有资源进行拦截,并且在拦截之后进行一些特殊的操作。 常见应用场景:URL级别的权限控制;过滤敏感词汇;中文乱码问题等等。
开发步骤 :
代码演示
自定义Servlet类Demo01Filter
// 自定义Servlet类Demo01Filter,实现Filter接口。
public class FilterDemo01 implements Filter {
// 重写接口中的抽象方法doFilter()
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// 在doFilter中编写拦截任务
System.out.println("FilterDemo01");
// 过滤器放行
filterChain.doFilter(servletRequest,servletResponse);
}
}
编写XML配置文件
<filter>
<filter-name>FilterDemo01filter-name>
<filter-class>com.test.filter.FilterDemo01filter-class>
filter>
<filter-mapping>
<filter-name>FilterDemo01filter-name>
<url-pattern>/*url-pattern>
filter-mapping>
定义一个ServletDemo01类进行测试
@WebServlet("/demo01")
public class ServletDemo01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("ServletDemo01....");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
注意事项 : Filter只需要放行一次,如果放行多次,会导致Servlet执行多次
执行流程
图解
代码实现
xml配置
<filter>
<filter-name>FileterDemo02filter-name>
<filter-class>com.test.filter.FilterDemo02filter-class>
filter>
<filter-mapping>
<filter-name>FileterDemo02filter-name>
<url-pattern>/*url-pattern>
filter-mapping>
java代码
public class FilterDemo02 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("过滤器初始化执行了....");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
}
@Override
public void destroy() {
System.out.println("过滤器销毁.....");
}
}
注意事项: 当过滤器放行,执行完目标资源后,仍会回到过滤器中。
初始化配置
初始化配置
<init-param>
<param-name>初始化参数名称param-name>
<param-value>初始化参数值param-value>
init-param>
初始化配置相关方法
String getFilterName() 获取过滤器的名称
String getInitParameter(String name) 获取过滤器初始化配置参数值
Enumeration<String> getInitParameterNames() 获取过滤器所有初始化参数名称
ServletContext getServletContext() 获取ServletContext域对象
代码演示
public class FilterDemo03 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
String encoding = filterConfig.getInitParameter("encoding");
System.out.println("encoding = " + encoding);
String filterName = filterConfig.getFilterName();
System.out.println("filterName = " + filterName);
Enumeration initParameterNames = filterConfig.getInitParameterNames();
ServletContext servletContext = filterConfig.getServletContext();
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("filter执行了....");
filterChain.doFilter(servletRequest, servletResponse);
}
}
过滤器路径配置
只针对某一个Servlet的请求进行拦截
<filter-mapping>
<filter-name>过滤器名称filter-name>
<url-pattern>Servlet名称url-pattern>
filter-mapping>
完全匹配:必须/开头
<filter-mapping>
<filter-name>过滤器名称filter-name>
<servlet-name>/任意路径servlet-name>
filter-mapping>
目录匹配:以/开头,*结尾
<filter-mapping>
<filter-name>过滤器名称filter-name>
<url-pattern>/路径/*url-pattern>
filter-mapping>
后缀匹配:以*开头,文件后缀结尾
<filter-mapping>
<filter-name>过滤器名称filter-name>
<url-pattern>路径/*.文件后缀名url-pattern>
filter-mapping>
代码示例
<filter>
<filter-name>FilterDemo03filter-name>
<filter-class>com.test.filter.FilterDemo03filter-class>
filter>
<filter-mapping>
<filter-name>FilterDemo03filter-name>
<servlet-name>ServletDemo01servlet-name>
filter-mapping>
<filter>
<filter-name>FilterDemo03filter-name>
<filter-class>com.test.filter.FilterDemo03filter-class>
filter>
<filter-mapping>
<filter-name>FilterDemo03filter-name>
<url-pattern>/demo01url-pattern>
filter-mapping>
<filter>
<filter-name>FilterDemo03filter-name>
<filter-class>com.test.filter.FilterDemo03filter-class>
filter>
<filter-mapping>
<filter-name>FilterDemo03filter-name>
<url-pattern>/properted/*url-pattern>
filter-mapping>
<filter>
<filter-name>FilterDemo03filter-name>
<filter-class>com.test.filter.FilterDemo03filter-class>
filter>
<filter-mapping>
<filter-name>FilterDemo03filter-name>
<url-pattern>/*.htmlurl-pattern>
filter-mapping>
概述 : 一个请求可能被多个过滤器所过滤,只有当所有过滤器都放行,请求才能到达目标资源,如果有某一 个过滤器没有放行,那么请求则无法到达后续过滤器以及目标资源,多个过滤器组成的链路就是过滤器链。
如图示例 :
过滤器的执行顺序 : 先配置的先过滤,后放行。后配置的后过滤,先放行。
代码演示 :
xml配置
<filter>
<filter-name>FilterDemo04filter-name>
<filter-class>com.test.filter.FilterDemo04filter-class>
filter>
<filter-mapping>
<filter-name>FilterDemo04filter-name>
<url-pattern>/*url-pattern>
filter-mapping>
<filter>
<filter-name>FilterDemo05filter-name>
<filter-class>com.test.filter.FilterDemo05filter-class>
filter>
<filter-mapping>
<filter-name>FilterDemo05filter-name>
<url-pattern>/*url-pattern>
filter-mapping>
<filter>
<filter-name>FilterDemo06filter-name>
<filter-class>com.test.filter.FilterDemo06filter-class>
filter>
<filter-mapping>
<filter-name>FilterDemo06filter-name>
<url-pattern>/*url-pattern>
filter-mapping>
Java代码
public class FilterDemo04 implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("FilterDemo04过滤器....");
filterChain.doFilter(servletRequest, servletResponse);
System.out.println("FiterDemo04放行....");
}
}
public class FilterDemo05 implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("FilterDemo05过滤器....");
filterChain.doFilter(servletRequest, servletResponse);
System.out.println("FiterDemo05放行....");
}
}
public class FilterDemo06 implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("FilterDemo06过滤器....");
filterChain.doFilter(servletRequest, servletResponse);
System.out.println("FiterDemo06放行....");
}
}
运行结果:
FilterDemo04过滤器....
FilterDemo05过滤器....
FilterDemo06过滤器....
ServletDemo01....
FiterDemo06放行....
FiterDemo05放行....
FiterDemo04放行....
概述 : Filter过滤器默认拦截的是请求,但是在实际开发中,我们还有请求转发和请求包含,以及由服务器触 发调用的全局错误页面。默认情况下过滤器是不参与过滤的,要想使用,就需要我们配置。
过滤器5种拦截行为
拦截行为 | 说明 |
---|---|
REQUEST | 过滤请求:默认 |
ERROR | 过滤全局错误页面:当由服务器调用全局错误页面时,过滤器工作 |
FORWAD | 过滤请求转发:当请求转发时,过滤器工作。 |
INCLUDE | 过滤请求包含:当请求包含时,过滤器工作。 |
ASYNC | 过滤异步类型,它要求我们在fiter标签中配置开启异步支持 |
代码实现
<filter>
<filter-name>Demo01Filterfilter-name>
<filter-class>com.qzw.filter.Demo01Filterfilter-class>
<async-supported>trueasync-supported>
filter>
<filter-mapping>
<filter-name>Demo01Filterfilter-name>
<url-pattern>/*url-pattern>
<dispatcher>REQUESTdispatcher>
<dispatcher>FORWARDdispatcher>
<dispatcher>ERRORdispatcher>
<dispatcher>INCLUDEdispatcher>
<dispatcher>ASYNCdispatcher>
filter-mapping>
注意事项
include会将下一个资源中的内容包含到当前资源中,而forward不会。
概述 : 通过注解方式进行过滤器配置@WebFilter
源码分析 :
@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 {}; // 配置Servlet名称,通过Servlet名称拦截 标签
String[] value() default {}; // 拦截请求 与 urlpatterns类似
String[] urlPatterns() default {}; // 配置过滤方式
DispatcherType[] dispatcherTypes() default {DispatcherType.REQUEST}; // 配置浏览器拦截行为
boolean asyncSupported() default false;
}
代码示例 :
@WebFilter(
filterName = "FilterDemo07",
urlPatterns = "/demo01",
servletNames = "Demo01Servlet",
initParams = {
@WebInitParam(name = "username", value = "root"),
@WebInitParam(name = "password", value = "root123")
}
)
public class FilterDemo07 implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("FilterDemo07过滤器....");
filterChain.doFilter(servletRequest, servletResponse);
}
}
监听器概述 :
在介绍监听器之前,先跟同学们普及一个知识,观察者设计模式。因为所有的监听器都是观察者设计模 式的体现。
那什么是观察者设计模式呢? 它是事件驱动的一种体现形式。就好比在做什么事情的时候被人盯着。当对应做到某件事时,触发事 件。
观察者模式通常由以下三部分组成:
事件源:触发事件的对象。
事件:触发的动作,里面封装了事件源。
监听器:当事件源触发事件时,要做的事情。
一般是一个接口,由使用者来实现。 下图描述了观察者设计模式组成:
监听器的分类:
监听器配置方式:
<listener>
<listener-class>自定义监听器的全类名listener-class>
listener>
概述 : 监听ServletRequest创建销毁
ServletRequestListener接口
/**
* 用于监听ServletRequest对象创建和销毁的监听器
* @since Servlet 2.4
*/
public interface ServletRequestListener extends EventListener {
/**
* 对象创建时执行此方法。
*/
public default void requestInitialized (ServletRequestEvent sre) {
}
/**
* 对象销毁执行此方法
*/
public default void requestDestroyed (ServletRequestEvent sre) {
}
}
概述 : 监听HttpSession创建销毁
HttpSessionListener接口
/**
* 用于监听HttpSession对象创建和销毁的监听器
*/
public interface HttpSessionListener extends EventListener {
/**
* 对象创建时执行此方法。
*/
public default void sessionCreated(HttpSessionEvent se) {
}
/**
* 对象销毁执行此方法
*/
public default void sessionDestroyed(HttpSessionEvent se) {
}
}
概述 : 监听ServletContext创建销毁
ServletContextListener接口
/**
* 用于监听ServletContext对象创建和销毁的监听器
* @since v 2.3
*/
public interface ServletContextListener extends EventListener {
/**
* 对象创建时执行此方法。该方法的参数是ServletContextEvent事件对象,事件是【创建对象】这个动作
* 事件对象中封装着触发事件的来源,即事件源,就是ServletContext
*/
public default void contextInitialized(ServletContextEvent sce) {
}
/**
* 对象销毁执行此方法
*/
public default void contextDestroyed(ServletContextEvent sce) {
}
}
开发步骤
代码实现
xml配置文件
<listener>
<listener-class>com.test.listener.ServletContextListenerDemo01listener-class>
listener>
Java代码
public class ServletContextListenerDemo01 implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("ServletContext创建了");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("ServletContext销毁了");
}
}
概述 : 监听请求域对象中的数据的变化(添加, 修改, 移除)
ServletRequestAttributeListener接口
/**
* 用于监听ServletRequest域(请求域)中属性发生变化的监听器
* @since Servlet 2.4
*/
public interface ServletRequestAttributeListener extends EventListener {
/**
* 域中添加了属性触发此方法。
*/
public default void attributeAdded(ServletRequestAttributeEvent srae) {
}
/**
* 域中删除了属性触发此方法
*/
public default void attributeRemoved(ServletRequestAttributeEvent srae) {
}
/**
* 域中属性发生改变触发此方法
*/
public default void attributeReplaced(ServletRequestAttributeEvent srae) {
}
}
概述 : 监听会话域对象中的数据的变化(添加, 修改, 移除)
HttpSessionAttributeListener接口
/**
* 用于监听HttpSession域(会话域)中属性发生变化的监听器
* @since v 2.3
*/
public interface HttpSessionAttributeListener extends EventListener {
/**
* 域中添加了属性触发此方法。
*/
public default void attributeAdded(HttpSessionBindingEvent se) {
}
/**
* 域中删除了属性触发此方法
*/
public default void attributeRemoved(HttpSessionBindingEvent se) {
}
/**
* 域中属性发生改变触发此方法
*/
public default void attributeReplaced(HttpSessionBindingEvent se) {
}
}
概述 : 监听应用域对象中的数据的变化(添加, 修改, 移除)
ServletContextAttributeListener接口
/**
* 用于监听ServletContext域(应用域)中属性发生变化的监听器
* @since v 2.3
*/
public interface ServletContextAttributeListener extends EventListener {
/**
* 域中添加了属性触发此方法。参数是ServletContextAttributeEvent事件对象,事件是【添加属性】。
* 事件对象中封装着事件源,即ServletContext。
* 当ServletContext执行setAttribute方法时,此方法可以知道,并执行。
*/
public default void attributeAdded(ServletContextAttributeEvent scae) {
}
/**
* 域中删除了属性触发此方法
*/
public default void attributeRemoved(ServletContextAttributeEvent scae) {
}
/**
* 域中属性发生改变触发此方法
*/
public default void attributeReplaced(ServletContextAttributeEvent scae) {
}
}
开发步骤
代码实现
xml代码
<listener>
<listener-class>com.test.listener.ServletContextAttributeListenerDemo01listener-class>
listener>
Java代码
public class ServletContextAttributeListenerDemo01 implements ServletContextAttributeListener {
@Override
public void attributeAdded(ServletContextAttributeEvent scae) {
System.out.println("属性添加了....");
}
@Override
public void attributeRemoved(ServletContextAttributeEvent scae) {
System.out.println("属性移除.....");
}
@Override
public void attributeReplaced(ServletContextAttributeEvent scae) {
System.out.println("属性修改...");
}
}
用于监听三大域对象中对象状态改变(钝化/活化 , 绑定/解绑)
分类
概述 : 用于监听会话域对象中对象状态改变( 绑定/解绑)
HttpSessionBindingListener接口
/**
* 用于感知对象和和会话域绑定的监听器
* 当有数据加入会话域或从会话域中移除,此监听器的两个方法会执行。
* 加入会话域即和会话域绑定
* 从会话域移除即从会话域解绑
*/
public interface HttpSessionBindingListener extends EventListener {
/**
* 当数据加入会话域时,也就是绑定,此方法执行
*/
public default void valueBound(HttpSessionBindingEvent event) {
}
/**
* 当从会话域移除时,也就是解绑,此方法执行
*/
public default void valueUnbound(HttpSessionBindingEvent event) {
}
}
概述 : 用于监听会话域对象中对象状态改变( 钝化/活化)
HttpSessionActivationListener接口
/**
* 用于感知会话域中对象钝化和活化的监听器
*/
public interface HttpSessionActivationListener extends EventListener {
/**
* 当会话域中的数据钝化时,此方法执行
*/
public default void sessionWillPassivate(HttpSessionEvent se) {
}
/**
* 当会话域中的数据活化时(激活),此方法执行
*/
public default void sessionDidActivate(HttpSessionEvent se) {
}
}
在实际开发中,我们可以根据具体情况来从这8个监听器中选择使用。三类监听器由于无需配置,只 需要根据实际需求编写代码,所以此处我们就不再演示了。
概述 : 通过注解的方式配置监听器@WebListener
注解源码 :
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface WebListener {
String value() default "";
}
代码实现
@WebListener
public class ServletContextListenerDemo02 implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("ServletContext创建了");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("ServletContext销毁了");
}
}