JavaWeb Filter 过滤器

参考:JavaWeb过滤器(Filter)详解

1、简介

顾名思义就是对事物进行过滤的,在Web中的过滤器,当然就是对请求进行过滤,我们使用过滤器,就可以对请求进行拦截,然后做相应的处理,实现许多特殊功能。如登录控制权限管理过滤敏感词汇等。

只要请求或者响应符合配置的路径,不管路径对应的资源是否存在,都会进行过滤。

1.1、原理:

过滤器会对游览器的请求(和服务器返回的响应)进行过滤,过滤器可以动态的分为3个部分:

  • 1.放行之前的代码:对游览器请求进行第一次过滤,然后继续执行
  • 2.放行(filterChain.doFilter(servletRequest,servletResponse)):将游览器请求放行,如果还有过滤器,那么就继续交给下一个过滤器
  • 3.放行后的代码:对返回的Web资源再次进行过滤处理

这3个部分分别会发挥不同作用。
在这里插入图片描述

1.2、包:

servlet-api.jar

2、生命周期

Filter有3个阶段,分别是初始化,过滤,销毁。

  1. 初始化阶段:当服务器启动时,我们的服务器(Tomcat)就会读取配置文件,扫描注解,然后来创建我们的Filter。
  2. 过滤阶段:只要请求资源的路径和拦截的路径相同,那么过滤器就会对请求进行过滤,这个阶段在服务器运行过程中会一直循环。
  3. 销毁阶段:当服务器(Tomcat)关闭时,服务器创建的Filter也会随之销毁

它是随你的web应用启动而启动的,只初始化一次,以后就可以拦截相关请求,只有当你的web应用停止或重新部署的时候才销毁。

过滤器生命周期:初始化init() → 过滤doFilter() → 析构(销毁)destroy()

3、使用

我们创建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 {
    
    
 
    }
}

3.1、接口、参数

3.1.1、接口

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 */ }
}

3.1.2、参数

FilterConfig和FilterConfig这2个对象是由服务器(Tomcat)在创建和调用Filter对象时所传入的,这2个对象十分有用。

  • FilterConfig对象可以读取我们配置的初始参数;
  • FilterChain可以实现多个Filter之间的连接。
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>myFilterConfig</filter-name>
	    <!-- 过滤器对应的java类 -->
	    <filter-class>com.clucky.filter.MyFilterConfig</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/equip_employ_manage?serverTimezone=GMT</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>root</param-value>
	    </init-param>
	</filter>
	<filter-mapping><!-- 映射 -->
	    <filter-name>myFilterConfig</filter-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对响应进行过滤。图示如下:
在这里插入图片描述
在这里插入图片描述

3.2、配置

  • Filter 的 url-pattern 中配置的路径是访问已经存在的网络资源,如静态页面、jsp、servlet等。
  • filter 和 url-pattern 之间的关系是 多对多的关系。即,Filter可负责拦截多个请求或响应;一个请求或响应也可被多个Filter拦截。(多个 filter 会根据 web.xml 中配置的顺序组成 filter 链)。

3.2.1、注解方式

@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;
}

3.2.2、xml方式

<web-app>
    <filter>
        <filter-name>myFilter</filter-name>
        <filter-class>com.clucky.filter.MyFilter</filter-class>
    </filter>
    <!-- 一个过滤器需要过滤多种文件,则可以配置多个<filter-mapping>,
    一个mapping定义一个url-pattern来定义过滤规则 -->
    <filter-mapping>
        <filter-name>myFilter</filter-name>
        <!-- 所有外部访问都需要先经过该过滤器。 -->
		<url—pattern>/*</url-pattern>
		<!-- 作用于某一文件夹下所有文件 -->
		<!-- <url—pattern>/dir/*</url-pattern> -->
		<!-- 作用于某一种类型的文件 -->
		<!-- <url—pattern>*.扩展名</url-pattern> -->
		<!-- 作用于某一文件夹下某一类型文件 -->
		<!-- <url—pattern>/dir/*.扩展名</url-pattern> -->
    </filter-mapping>
</web-app>

3.3、执行顺序

多个Filter的执行顺序

如果配置了2个过滤器,怎么知道那个过滤器先执行呢?

  • 如果我们是在web.xml中配置的过滤器,那么过滤器的执行顺序就是<filter-mapping>在web配置的顺序,配置在上面那么就会先执行。
  • 如果我们是使用@WebFilter进行配置的,那么执行顺序就是字符比较顺序来执行,例如有2个过滤器,一个是AFilter,一个是BFilter,那么AFilter就会先执行。
  • 如果注解和xml混用,那么在web.xml中配置的会先执行。

3.4、具体应用(过滤敏感词)

如果评论中含有我们定义的敏感词汇,那么我们就进行过滤,使用**来进行代替。

jsp页面

<%@ 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>

requestScope介绍

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
在这里插入图片描述

3.5、具体应用(解决乱码)

web.xml配置

<web-app>
 <filter>
    <filter-name>encoding</filter-name>
    <filter-class>com.yyl.utils.EncodingFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>  
      <param-value>UTF-8</param-value>
    </init-param>
    <init-param>
      <param-name>forceEncoding</param-name>
      <param-value>true</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>encoding</filter-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() {
    
    

    }
}

猜你喜欢

转载自blog.csdn.net/weixin_41544662/article/details/128175164
今日推荐