顾名思义就是对事物进行过滤的,在Web中的过滤器,当然就是对请求进行过滤,我们使用过滤器,就可以对请求进行拦截,然后做相应的处理,实现许多特殊功能。如登录控制,权限管理,过滤敏感词汇等。
只要请求或者响应符合配置的路径,不管路径对应的资源是否存在,都会进行过滤。
过滤器会对游览器的请求(和服务器返回的响应)进行过滤,过滤器可以动态的分为3个部分:
filterChain.doFilter(servletRequest,servletResponse)):将游览器请求放行,如果还有过滤器,那么就继续交给下一个过滤器这3个部分分别会发挥不同作用。

servlet-api.jar
Filter有3个阶段,分别是初始化,过滤,销毁。
它是随你的web应用启动而启动的,只初始化一次,以后就可以拦截相关请求,只有当你的web应用停止或重新部署的时候才销毁。
过滤器生命周期:初始化init() → 过滤doFilter() → 析构(销毁)destroy()
我们创建Filter,只需要继承Filter接口就行。
import javax.servlet.*;
import java.io.IOException;
public class MyFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
}
}
package javax.servlet;
public interface Filter {
default void init(javax.servlet.FilterConfig filterConfig) throws javax.servlet.ServletException { /* compiled code */ }
void doFilter(javax.servlet.ServletRequest servletRequest, javax.servlet.ServletResponse servletResponse, javax.servlet.FilterChain filterChain) throws java.io.IOException, javax.servlet.ServletException;
default void destroy() { /* compiled code */ }
}
FilterConfig和FilterConfig这2个对象是由服务器(Tomcat)在创建和调用Filter对象时所传入的,这2个对象十分有用。
public interface FilterConfig {
// 获取filter的名称
java.lang.String getFilterName();
// 获取ServletContext
javax.servlet.ServletContext getServletContext();
// 获取配置的初始参数的值
java.lang.String getInitParameter(java.lang.String s);
// 获取配置的所有参数名称
java.util.Enumeration<java.lang.String> getInitParameterNames();
}
/*
FilterChain就只有一个方法,其实这个方法就是用来对拦截进行放行的;
如果有多个拦截器,那么就会继续调用下一个Filter进行拦截。
doFilter方法需要传入个参数,一个是ServletRequest,一个是ServletResponse参数,这个直接传入进行。
Tomcat在调用过滤器时,默认就会传入Request和Response,
这个参数封装了请求和响应,我们直接使用就行。
ServletResquest和ServletResponse可以直接
强转成HttpServletRequest和HttpServletResponse,然后使用相应的方法
*/
public interface FilterChain {
void doFilter(javax.servlet.ServletRequest servletRequest, javax.servlet.ServletResponse servletResponse) throws java.io.IOException, javax.servlet.ServletException;
}
①、FilterConfig
运用:在init方法中使用FilterConfig来读取配置的数据库的信息,然后输出。
<web-app>
<filter>
<filter-name>myFilterConfigfilter-name>
<filter-class>com.clucky.filter.MyFilterConfigfilter-class>
<init-param>
<param-name>driverparam-name>
<param-value>com.mysql.jdbc.Driverparam-value>
init-param>
<init-param>
<param-name>urlparam-name>
<param-value>jdbc:mysql://localhost:3306/equip_employ_manage?serverTimezone=GMTparam-value>
init-param>
<init-param>
<param-name>usernameparam-name>
<param-value>rootparam-value>
init-param>
<init-param>
<param-name>passwordparam-name>
<param-value>rootparam-value>
init-param>
filter>
<filter-mapping>
<filter-name>myFilterConfigfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
web-ap>
import javax.servlet.*;
import java.io.IOException;
import java.util.Enumeration;
public class MyFilterConfig implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("-----------获取全部key:value------------");
//得到所有配置参数的名字
Enumeration<String> names = filterConfig.getInitParameterNames();
while (names.hasMoreElements()) {
//得到每一个名字
String name = names.nextElement();
System.out.println(name+" = "+filterConfig.getInitParameter(name));
}
System.out.println("-----------end.....------------");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
}
@Override
public void destroy() {
}
}

②、FilterConfig
配置2个Filter,通过FilterChain来进行多个过滤。
第一个过滤器
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
//注解方式配置Filter
@WebFilter("/*")
public class Filter01 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("调用过滤器01对请求进行过滤~~~~");
//放行,如果还有过滤器,那么就执行下一个过滤器
filterChain.doFilter(servletRequest,servletResponse);
System.out.println("调用过滤器01对响应进行过滤~~~~");
}
@Override
public void destroy() {
}
}
第二个过滤器
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
@WebFilter("/*")
public class Filter02 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("调用过滤器02对请求进行过滤~~~~");
//放行,如果还有过滤器,那么就执行下一个过滤器
filterChain.doFilter(servletRequest,servletResponse);
System.out.println("调用过滤器02对响应进行过滤~~~~");
}
@Override
public void destroy() {
}
}
Filter01先进行过滤,然后交给Filter02,然后访问资源,然后Filter02对响应进行过滤,然后Filter01对响应进行过滤。图示如下:


@WebFilter(value = {"/*"},filterName = "myFilter")
public class test implements Filter {
}
@WebFilter源码
urlPatterns和value是一样的。urlPatterns和value只能配置一个,不能两个都配置,两个都配置就会报错。
public @interface WebFilter {
java.lang.String description() default "";
// filter显示名称
java.lang.String displayName() default "";
// 初始化参数
javax.servlet.annotation.WebInitParam[] initParams() default {};
// 该filter的名字
java.lang.String filterName() default "";
java.lang.String smallIcon() default "";
java.lang.String largeIcon() default "";
// 指定对哪些servlet进行过滤
java.lang.String[] servletNames() default {};
// 指定拦截路径
java.lang.String[] value() default {};
// 指定拦截路径
java.lang.String[] urlPatterns() default {};
javax.servlet.DispatcherType[] dispatcherTypes() default {javax.servlet.DispatcherType.REQUEST};
// 是否支持异步模式
boolean asyncSupported() default false;
}
<web-app>
<filter>
<filter-name>myFilterfilter-name>
<filter-class>com.clucky.filter.MyFilterfilter-class>
filter>
<filter-mapping>
<filter-name>myFilterfilter-name>
<url—pattern>/*url-pattern>
filter-mapping>
web-app>
多个Filter的执行顺序
如果配置了2个过滤器,怎么知道那个过滤器先执行呢?
在web配置的顺序,配置在上面那么就会先执行。如果评论中含有我们定义的敏感词汇,那么我们就进行过滤,使用**来进行代替。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>评论title>
head>
<body>
<h1>输入评论内容h1>
<form action="${pageContext.request.contextPath}/comment" method="post">
<textarea name="message" cols="30" rows="10">textarea>
<input type="submit" value="提交">
form>
<p >${requestScope.get("name")}<span style="color: red">${requestScope.get("comment")}span>p>
body>
html>
Filter java
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
// 这里使用注解配置,也可以用xml配置
@WebFilter(servletNames = {"comment"},initParams = {@WebInitParam(name = "sensitiveWord", value = "zz")})
public class CommentFilter implements Filter {
private List<String> sensitiveWords = new ArrayList<>();
@Override
public void init(FilterConfig filterConfig) throws ServletException {
//得到敏感词汇
String word = filterConfig.getInitParameter("sensitiveWord");
//加入集合
sensitiveWords.add(word);
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//设置编码
servletRequest.setCharacterEncoding("utf-8");
servletResponse.setContentType("text/html;charset=utf-8");
//得到评论
String message = servletRequest.getParameter("message");
for (String sensitiveWord : sensitiveWords) {
//对所有敏感词汇进行过滤
if (message.contains(sensitiveWord)){
//替换敏感词汇
message = message.replace(sensitiveWord, "**");
}
}
//存入request域
servletRequest.setAttribute("comment",message);
//放行
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
}
}
Servlet java
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;
import java.util.HashSet;
@WebServlet(name = "comment",value = "/comment")
public class CommentServlet extends HttpServlet {
//记录评论敏感词汇的ip
private HashSet<String> hashSet = new HashSet<>();
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String message = request.getParameter("message");
String comment = (String) request.getAttribute("comment");
if (message.equals(comment)){
System.out.println("没有敏感词汇.....");
//设置名字
request.setAttribute("name","good boy:");
}else {
//有敏感词汇,记录IP
String localAddr = request.getLocalAddr();
System.out.println(localAddr);
hashSet.add(localAddr);
//设置名字
request.setAttribute("name","bad boy:");
}
//转发到comment.jsp页面
request.getRequestDispatcher("/comment.jsp").forward(request,response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
输入:你真是个zz

web.xml配置
<web-app>
<filter>
<filter-name>encodingfilter-name>
<filter-class>com.yyl.utils.EncodingFilterfilter-class>
<init-param>
<param-name>encodingparam-name>
<param-value>UTF-8param-value>
init-param>
<init-param>
<param-name>forceEncodingparam-name>
<param-value>trueparam-value>
init-param>
filter>
<filter-mapping>
<filter-name>encodingfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
web-app>
java
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class EncodingFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// 强转
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
request.setCharacterEncoding("UTF-8") ;
// 网页编码编译的格式
response.setContentType ("text/html; charset=UTF-8") ;
filterChain.doFilter(request, response) ;
}
@Override
public void destroy() {
}
}