• 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 {
     
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    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 */ }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    ①、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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    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() {
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    在这里插入图片描述

    ②、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() {
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    第二个过滤器

    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() {
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    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 {
    }
    
    • 1
    • 2
    • 3

    @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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    3.2.2、xml方式

    <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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    3.3、执行顺序

    多个Filter的执行顺序

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

    • 如果我们是在web.xml中配置的过滤器,那么过滤器的执行顺序就是在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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    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() {
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    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);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    输入:你真是个zz
    在这里插入图片描述

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

    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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    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() {
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
  • 相关阅读:
    leetCode 2578. 最小和分割 + 排序 + 贪心 + 奇偶分组(构造最优解)
    期末前端web大作业——名侦探柯南网页制作 Hbuiderx制作网页 静态HTML网页单页制作 dreamweaver网页设计与制作代码 web前端期末大作业
    畅捷通T+任意文件上传(CNVD-2022-60632 )漏洞复现
    VINS-Fusion-GNSS松耦合原理
    【单片机】12-串口通信和RS485
    day8-机器学习模型评估
    聊一聊作为高并发系统基石之一的缓存,会用很简单,用好才是技术活
    大厂外包干了一个月,技术明显进步。。。。。
    Linux基础
    ip地址范围不是整体范围的子集
  • 原文地址:https://blog.csdn.net/weixin_41544662/article/details/128175164