JavaWeb Filter filter

Reference: Detailed explanation of JavaWeb filter (Filter)

1 Introduction

As the name implies, it is to filter things. The filter in the Web is of course to filter the request. We use the filter to intercept the request, and then do the corresponding processing to realize many special functions. Such as 登录控制, 权限管理, 过滤敏感词汇etc.

As long as the request or response matches the configured path, regardless of whether the resource corresponding to the path exists or not, it will be filtered.

1.1. Principle:

The filter will 游览器的请求(和服务器返回的响应)filter, and the filter can be dynamically divided into 3 parts:

  • 1. Code before release: filter the browser request for the first time, and then continue to execute
  • 2. Release ( filterChain.doFilter(servletRequest,servletResponse)): release the browser request, if there are still filters, then continue to the next filter
  • 3. Code after release: filter the returned web resources again

These three parts will play different roles.
insert image description here

1.2. Package:

servlet-api.jar

2. Life cycle

Filter has 3 stages, namely initialization, filtering, and destruction.

  1. Initialization phase: When the server starts, our server (Tomcat) will read the configuration file, scan the annotations, and then create our Filter.
  2. Filtering stage: As long as the path of the requested resource is the same as the intercepted path, the filter will filter the request, and this stage will continue to circulate during the running of the server.
  3. Destruction phase: When the server (Tomcat) is closed, the Filter created by the server will also be destroyed

It is started when your web application is started, it is only initialized once, and related requests can be intercepted in the future, and it will only be destroyed when your web application is stopped or redeployed.

Filter life cycle: initialization init() → filter doFilter() → destruction (destruction) destroy()

3. Use

我们创建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, interface, parameters

3.1.1. Interface

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. Parameters

The two objects FilterConfig and FilterConfig are passed in by the server (Tomcat) when creating and calling the Filter object, and these two objects are very useful.

  • The FilterConfig object can read the initial parameters we configured;
  • FilterChain can realize the connection between multiple Filters.
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;
}

①.
Use of FilterConfig: Use FilterConfig in the init method to read the information of the configured database, and then output it.

<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() {
    
    
    }
}

insert image description here

②, FilterConfig
configures 2 Filters, and performs multiple filtering through FilterChain.
first filter

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() {
    
    
    }
}

second filter

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 filters first, then passes it to Filter02, then accesses resources, then Filter02 filters the response, and then Filter01 filters the response. The diagram is as follows:
insert image description here
insert image description here

3.2. Configuration

  • The path configured in the url-pattern of Filter is to access existing network resources, such as static pages, jsp, servlet, etc.
  • The relationship between filter and url-pattern is a many-to-many relationship. That is, Filter can be responsible for intercepting multiple requests or responses; one request or response can also be intercepted by multiple Filters. (Multiple filters will form a filter chain according to the order configured in web.xml).

3.2.1, Annotation method

@WebFilter(value = {
    
    "/*"},filterName = "myFilter")
public class test implements Filter {
    
    
}

@WebFilter source code

urlPatterns and value are the same. Only one of urlPatterns and value can be configured, not both, and an error will be reported if both are configured.

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 mode

<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. Execution sequence

Execution order of multiple Filters

If two filters are configured, how do you know which filter to execute first?

  • If we configure the filter in web.xml, then the execution order of the filter is the <filter-mapping>order of the web configuration, and the configuration above will be executed first.
  • If we use @WebFilter for configuration, the execution order is the order of character comparison. For example, if there are 2 filters, one is AFilter and the other is BFilter, then AFilter will be executed first.
  • If annotations and xml are mixed, those configured in web.xml will be executed first.

3.4. Specific application (filter sensitive words)

If the comment contains the sensitive words we defined, then we will filter it and use ** to replace it.

jsp page

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

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

Enter: you are such a zz
insert image description here

3.5. Specific application (solve garbled characters)

web.xml configuration

<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() {
    
    

    }
}

Guess you like

Origin blog.csdn.net/weixin_41544662/article/details/128175164