JavaWeb—过滤器—Eclipse版动力节点学习笔记

JavaWeb—过滤器

哔哩哔哩蛙课网【动力节点】JavaWeb-Eclipse版学习视频网址
文章只为分享学习经验和自己复习用,学习还是该去查看正规视频网站和官方文档才更有效。

解释 归属 备注
init() 过滤器的初始化工作 Filter
doFilter() 请求与响应开启过滤器 Filter
destroy() 销毁过滤器 Filter
FilterConfig 过滤器配置 Filter
<url-pattern/> <filter-mapping/>中url不能使用 / Filter 可以指定servlet-name
<dispatcher/> 过滤器所过滤的请求类型 Filter
FORWARD 只拦截 RequestDispatcher 的 forward()方法所转发的请求 Filter
INCLUDE 只拦截 RequestDispatcher 的 include()方法所转发的请求 Filter
ERROR 只会拦截转向错误页面的请求 Filter
REQUEST 默认值,只要不是forward()方法或 include()方法转发的,都拦截 Filter
FilterChain 过滤器链 Filter 过滤器集合
HttpServletRequestWrapper 装饰者类 Filter
Decorator Pattern 装饰器模式 Filter

过滤器 Filter

1、Filter 基础

Filter 是 Servlet 规范的三大组件之一。顾名思义,就是过滤。可以在请求到达目标资源之前先对请求进行拦截过滤,即对请求进行一些处理;也可以在响应到达客户端之前先对响应进行拦截过滤,即对响应进行一些处理。

在这里插入图片描述

1.1、Filter 的生命周期

Filter 的生命周期与 Servlet 的生命周期类似,其主要生命周期阶段有四个:Filter 对象的创建、Filter 对象的初始化、Filter 执行 doFilter()方法,及最终 Filter 对象被销毁。

Filter 的整个生命周期过程的执行,均由 Web 服务器负责管理。即 Filter 从创建到销毁的整个过程中方法的调用,都是由 Web 服务器负责调用执行,程序员无法控制其执行流程。

在这里插入图片描述

1.1.1、代码测试

定义 Filter

在 Servlet 规范中,有一个 javax.servlet.Filter 接口,实现了该接口的类称为过滤器。

该接口中有三个方法需要实现:

  • init():初始化方法,即 Filter 被创建后,在后面用到的资源的初始化工作,可以在这里完成。
  • doFilter():Filter 的核心方法,对于请求与响应的过滤,就是在这个方法中完成的。
  • destroy():销毁方法。Filter 被销毁前所调用执行的方法。对于资源的释放工作,可以在这里完成
import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

// Filter是在应用启动时被创建和初始化的
// Filter是单例多线程的
// Filter是在应用被停止时销毁的
// doFilter()方法是无法哪个线程访问,只要由该Filter进行过滤,那么就会执行该Filter的doFilter()方法
// 并且是每过滤一次就会执行一次doFilter()
// 由于Filter是单例多线程的,为了保证其线程安全性,一般是不为Filter添加可修改的成员变量的
public class SomeFilter implements Filter {
   

	public SomeFilter() {
   
		System.out.println("创建SomeFilter");
	}
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
   
		System.out.println("初始化SomeFilter");
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
   
		System.out.println("执行SomeFilter --- before---");
		// 将请求放行到下一个资源
		chain.doFilter(request, response);
      
		System.out.println("执行SomeFilter --- after---");
	}

	@Override
	public void destroy() {
   
		System.out.println("销毁SomeFilter");
	}
}

注册 Filter

过滤器 Filter 与 Servlet、Listener 一样,也需要在 web.xml 中进行注册。其注册的标签结构与 Servlet 的非常相似,也需要指定该 Filter 可以过滤的请求类型。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	id="WebApp_ID" version="2.5">
	
	<!-- 注册Filter -->
	<filter>
		<filter-name>Some-Filter</filter-name>
		<filter-class>com.bjpowernode.filters.SomeFilter</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>Some-Filter</filter-name>
        <!-- /* 所有请求都拦截 -->
		<url-pattern>/*</url-pattern>
	</filter-mapping>
	
</web-app>
1.1.2、Filter 的特征
  • Filter 是单例多线程的。
  • Filter 是在应用被加载时创建并初始化,这是与 Servlet 不同的地方。Servlet 是在该 Servlet被第一次访问时创建。Filter 与 Servlet 的共同点是,其无参构造器与 init()方法只会执行一次。
  • 用户每提交一次该 Filter 可以过滤的请求,服务器就会执行一次 doFilter()方法,即doFilter()方法是可以被多次执行的。
  • 当应用被停止时执行 destroy()方法,Filter 被销毁,即 destroy()方法只会执行一次。
  • 由于 Filter 是单例多线程的,所以为了保证其线程安全性,一般情况下是不为 Filter 类定义可修改的成员变量的。因为每个线程均可修改这个成员变量,会出现线程安全问题。

1.2、FilterConfig

1.2.1、FilterConfig 的获取

与 ServletConfig 类似,FilterConfig 指的是当前 Filter 在 web.xml 中的配置信息。同样是一个 Filter 对象一个 FilterConfig 对象,多个 Filter 对象会有多个 FilterConfig 对象。在 Web 容器调用 init()方法时,Web 容器首先会将 web.xml 中当前 Filter 类的配置信息封装为一个 FilterConfig 对象。Web 容器会将这个对象传递给 init()方法中的 FilterConfig 参数。也就是说,我们要获取 FilterConfig 对象,就需要像 Servlet 获取 ServletConfig 一样,在 Filter类中声明一个 FilterConfig 成员变量,并在 init()方法中赋值。

1.2.2、FilterConfig 中的方法

FilterConfig 接口中的方法与 ServletConfig 接口中的方法,方法名与意义完全相同。

在这里插入图片描述

Filter 在 web.xml 中进行配置时,可以指定多个初始化参数。

1.2.3、代码测试

定义 OneFilter

package com.bjpowernode.filters;

import java.io.IOException;
import java.util.Enumeration;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

// FilterConfig指的是Filter在web.xml中的注册信息

public class SomeFilter implements Filter {
   
	
	private FilterConfig filterConfig;
	
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
   
		this.filterConfig = filterConfig;
	}
	
	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
   
		// 获取Filter的Name
		String filterName = filterConfig.getFilterName();
		System.out.println("filterName = " + filterName);
		
		// 获取所有的初始化参数名称
		Enumeration<String> names = filterConfig.getInitParameterNames();
		// 遍历枚举
		while(names.hasMoreElements()) {
   
			String name = names.nextElement();
			String value = filterConfig.getInitParameter(name);
			System.out.println(name + " = " + value);
		}
		
		// 获取全局域
		ServletContext sc = filterConfig.getServletContext();
		System.out.println("ServletContext = " + sc);
		
		// 将请求放行到下一个资源
		chain.doFilter(request, response);
		
	}

}

注册 OneFilter

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	id="WebApp_ID" version="2.5">
	
	<filter>
		<filter-name>Some-Filter</filter-name>
		<filter-class>com.bjpowernode.filters.SomeFilter</filter-class>
		<init-param>
			<param-name>company</param-name>
			<param-value>bjpowernode</param-value>
		</init-param>
		<init-param>
			<param-name>teacher</param-name>
			<param-value>Reyco</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>Some-Filter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
	
</web-app>

1.3、Filter 的< url-pattern/ >

对于 Filter 的<url-pattern/>的匹配路径设置问题,与 Servlet 的类似。不过,有两点需要注意:

1.3.1、全路径匹配不支持/

对于 Servlet 中的<url-pattern/>的全路径匹配设置方式,可以设置为/*,也可以设置为/。但,对于 Filter 的<url-pattern/>的全路径匹配设置,只支持/*,而不支持/。也就是说,若一个 Filter 的<url-pattern/>指定为为/,则将不过滤任何请求。

为什么要设计为不支持/呢?因为全路径的/只会拦截静态资*请求,对动态资源请求是不拦截的。若支持/,则可能会出现对某些请求的不拦截。

1.3.2、Filter 可以不指定< url-pattern/ >

<filter-mapping/>中可以不指定<url-pattern/>,但需要使用<servlet-name/>标签。该标签用来指定该 Filter 专门过滤指定 Servlet 的请求。即相当于当前 Filter 的<url-pattern/>的值与指定 Servlet 的<url-pattern/>的值相同。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	id="WebApp_ID" version="2.5">
	
	<filter>
		<filter-name>Some-Filter</filter-name>
		<filter-class>com.bjpowernode.filters.SomeFilter</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>Some-Filter</filter-name>
		<!-- 若Filter为全路径匹配方式,那么url-pattern只能写为/*,而不能写为/。 -->
		<!-- <url-pattern>/*</url-pattern> -->
		<!-- filter-mapping中可以不使用url-pattern,但需要指定servlet-name,即当前过滤器拦截的是对指定Servlet的请求 -->
		<servlet-name>SomeServlet</servlet-name>
	</filter-mapping>

	<servlet>
		<display-name>SomeServlet</display-name>
		<servlet-name>SomeServlet</servlet-name>
		<servlet-class>com.bjpowernode.servlets.SomeServlet</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>SomeServlet</servlet-name>
		<!-- 
			/*:表示当前Servlet可以匹配所有的请求,即可以拦截所有的请求,无论发出的是静态资源,还是动态资源的访问请求,统统会被拦截
			/:不会拦截动态资源请求,即不会拦截对于jsp页面的请求,但会拦截静态资源请求
		 -->
		
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值