先写一个Post接口用来请求,给过滤器测试用

@RestController
@RequestMapping(value = "api/tool")
public class ToolModuleController {

    /**
     * @param
     * @return
     * @创建日期:2020年3月5日
     * @功能说明:生成UUID
     */
    @ApiOperation(value = "生成UUID(数字+字母)", notes = "生成UUID(数字+字母)")
    @PostMapping(value = "generateUuid")
    public String generateUuid() {
        try {
            String id = UUIDGeneratorUtil.buildMallOrderSn();
            return id;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return "失败";
        }
    }
  }

方式一:通过注解扫描的方式完成Filter组件的注册

过滤器的使用很简单,建一个类,实现Filter(引入的是javax.servlet),那么这个类就是过滤器了,加上@WebFilter配置过滤规则,@Order用于多个过滤器时定义执行顺序,值越小越先执行,最后要在启动类加上@ServletComponentScan,不加过滤器不生效。
1、过滤器init方法是初始化的,程序(tomcat)启动的时候执行,doFilter方法里面就可以写过滤的逻辑了,destroy方法是程序(tomcat)关闭的时候执行的。
1.1、web服务器在调用doFilter方法时,会传递一个filterChain对象进来,filterChain对象是filter接口中最重要的一个对 象,它也提供了一个doFilter方法,开发人员可以根据需求决定是否调用此方法,调用该方法,则web服务器就会调用web资源的service方 法,即web资源就会被访问,否则web资源不会被访问。有多个过滤器,会接着掉下一个过滤器
2、@WebFilter讲解:
2.1、urlPatterns注解过滤写法:
①完全匹配:以“/”开头,以字母(非“”)结束
如:/test/list ②目录匹配:以“/”开头且以“/”结尾
如: /test/* ③扩展名匹配:以“*.”开头,以扩展名结束
如:*.do*.jsp 2.2、filterName 里面的值是当前类名

新建第一个过滤器:FilterDemo1

package wwfww.warehouse.aaaTest.filter;



import org.springframework.core.annotation.Order;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
/**
 * @Order(int) 注解,配合 @WebFilter 注解使用,用于多个过滤器时定义执行顺序,值越小越先执行
 */
@Order(1)
@WebFilter(filterName = "FilterDemo1",urlPatterns = {"/api/tool/*","*.jsp"})
public class FilterDemo1 implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("这边可以是初始化,可以干一些初始化的工作,比如初始化读取文件");

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        System.out.println("进入过滤器");
        if(request.getParameter("num").equals("1")){
            //假设这边是用来验证登录密码的
            request.setCharacterEncoding("密码错误");
        }else{
            /**
             * doFilter()的作用是将请求转发给过滤器链上下一个对象。这里的“下”指的是哪里 ?
             *指的是下一个filter,如果没有filter那就是你请求的资源。
             */
            chain.doFilter(request,response);
        }
        System.out.println("退出过滤器");
    }

    @Override
    public void destroy() {

    }
}

新建第二个过滤器:FilterDemo2

package wwfww.warehouse.aaaTest.filter;

import org.springframework.core.annotation.Order;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
/**
 * @Order(int) 注解,配合 @WebFilter 注解使用,用于多个过滤器时定义执行顺序,值越小越先执行
 */
@Order(2)
@WebFilter(filterName = "FilterDemo2",urlPatterns = {"/api/tool/*"})
public class FilterDemo2 implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        System.out.println("轮到我执行了");
         /**
             * doFilter()的作用是将请求转发给过滤器链上下一个对象。这里的“下”指的是哪里 ?
             *指的是下一个filter,如果没有filter那就是你请求的资源。不加这句你的请求就到不了你的接口
             */
        chain.doFilter(request,response);
    }

    @Override
    public void destroy() {

    }
}

启动类:

@SpringBootApplication
@ServletComponentScan
@MapperScan(basePackages = {"wwfww.warehouse.mapper"})//不加这句mapper依赖注入不进来
public class WarehouseApplication {

    public static void main(String[] args) {
        SpringApplication.run(WarehouseApplication.class, args);
    }

}

控制台输出:

2021-03-06 12:13:58.533  INFO 11976 --- [           main] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 1601 ms
这边可以是初始化,可以干一些初始化的工作,比如初始化读取文件
Loading class `com.mysql.jdbc.Driver'. This is deprecated. The new driver class is `com.mysql.cj.jdbc.Driver'. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.
2021-03-06 12:13:58.681  INFO 11976 --- [           main] com.zaxxer.hikari.HikariDataSource       : warehouse - Starting...
2021-03-06 12:13:58.681  WARN 11976 --- [           main] com.zaxxer.hikari.util.DriverDataSource  : Registered driver with driverClassName=com.mysql.jdbc.Driver was not found, trying direct instantiation.
2021-03-06 12:13:58.884  INFO 11976 --- [           main] com.zaxxer.hikari.HikariDataSource       : warehouse - Start completed.
2021-03-06 12:13:58.937  INFO 11976 --- [           main] o.hibernate.jpa.internal.util.LogHelper  : HHH000204: Processing PersistenceUnitInfo [name: default]
2021-03-06 12:13:59.001  INFO 11976 --- [           main] org.hibernate.Version                    : HHH000412: Hibernate ORM core version 5.4.12.Final
2021-03-06 12:13:59.140  INFO 11976 --- [           main] o.hibernate.annotations.common.Version   : HCANN000001: Hibernate Commons Annotations {5.1.0.Final}
2021-03-06 12:13:59.257  INFO 11976 --- [           main] org.hibernate.dialect.Dialect            : HHH000400: Using dialect: org.hibernate.dialect.MySQL8Dialect
2021-03-06 12:13:59.460  INFO 11976 --- [           main] o.h.e.t.j.p.i.JtaPlatformInitiator       : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
2021-03-06 12:13:59.475  INFO 11976 --- [           main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2021-03-06 12:14:00.132  WARN 11976 --- [           main] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
2021-03-06 12:14:00.249  INFO 11976 --- [           main] pertySourcedRequestMappingHandlerMapping : Mapped URL path [/v2/api-docs] onto method [springfox.documentation.swagger2.web.Swagger2Controller#getDocumentation(String, HttpServletRequest)]
2021-03-06 12:14:00.356  INFO 11976 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2021-03-06 12:14:00.409  INFO 11976 --- [           main] o.s.b.a.w.s.WelcomePageHandlerMapping    : Adding welcome page template: index
2021-03-06 12:14:00.559  INFO 11976 --- [           main] d.s.w.p.DocumentationPluginsBootstrapper : Context refreshed
2021-03-06 12:14:00.580  INFO 11976 --- [           main] d.s.w.p.DocumentationPluginsBootstrapper : Found 1 custom documentation plugin(s)
2021-03-06 12:14:00.612  INFO 11976 --- [           main] s.d.s.w.s.ApiListingReferenceScanner     : Scanning for api listing references
2021-03-06 12:14:00.729  INFO 11976 --- [           main] .d.s.w.r.o.CachingOperationNameGenerator : Generating unique operation named: sendEmailUsingPOST_1
2021-03-06 12:14:00.804  INFO 11976 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8888 (http) with context path ''
2021-03-06 12:14:00.804  INFO 11976 --- [           main] wwfww.warehouse.WarehouseApplication     : Started WarehouseApplication in 4.425 seconds (JVM running for 6.183)
2021-03-06 12:14:05.063  INFO 11976 --- [nio-8888-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2021-03-06 12:14:05.063  INFO 11976 --- [nio-8888-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2021-03-06 12:14:05.072  INFO 11976 --- [nio-8888-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 9 ms
进入过滤器
轮到我执行了
退出过滤器

方式二、在启动类注册Filter

方式二是新建一个类实现Filter,然后在启动类那边将这个类注册,可以通过@Order()来实现过滤器顺序

新建FilterDemo3,并且实现Filter

package wwfww.warehouse.aaaTest.filter;

import javax.servlet.*;
import java.io.IOException;

public class FilterDemo3 implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        System.out.println("进入过滤器");
            /**
             * doFilter()的作用是将请求转发给过滤器链上下一个对象。这里的“下”指的是哪里 ?
             *指的是下一个filter,如果没有filter那就是你请求的资源。
             */
            chain.doFilter(request,response);
        System.out.println("退出过滤器");

    }

    @Override
    public void destroy() {

    }
}

新建FilterDemo4类,并且实现Filter

package wwfww.warehouse.aaaTest.filter;

import javax.servlet.*;
import java.io.IOException;

public class FilterDemo4 implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        System.out.println("方式二轮到我了");
        chain.doFilter(request,response);
    }

    @Override
    public void destroy() {

    }
}

启动类注册Filter组件

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.context.annotation.Bean;
import tk.mybatis.spring.annotation.MapperScan;
import wwfww.warehouse.aaaTest.filter.FilterDemo3;

@SpringBootApplication
@MapperScan(basePackages = {"wwfww.warehouse.mapper"})//不加这句mapper依赖注入不进来
public class WarehouseApplication {

    public static void main(String[] args) {
        SpringApplication.run(WarehouseApplication.class, args);
    }

     /**
     * 注册Filter
     * @return
     */
    @Bean
    @Order(1)
    public FilterRegistrationBean getFilterRegistrationBean(){
        FilterRegistrationBean ben = new FilterRegistrationBean(new FilterDemo3());
        ben.addUrlPatterns(new String[]{"/api/tool/*","*.jsp"});
        return ben;

    }
    /**
     * 注册Filter
     * @return
     */
    @Bean
    @Order(2)
    public FilterRegistrationBean getFilterRegistrationBean2(){
        FilterRegistrationBean ben = new FilterRegistrationBean(new FilterDemo4());
        ben.addUrlPatterns(new String[]{"/api/tool/*","*.jsp"});
        return ben;

    }

}

控制台输出:

进入过滤器
方式二轮到我了
退出过滤器

过滤器应用场景

1)过滤敏感词汇(防止sql注入)

2)设置字符编码

@Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        //转换
        HttpServletRequest request1 = (HttpServletRequest)request;
        HttpServletResponse response1 = (HttpServletResponse)response;
        //设置编码
        request1.setCharacterEncoding("UTF-8");
        response1.setCharacterEncoding("UTF-8");
        /*
         * 使用doFilter方法调用链中的下一个过滤器或目标资源(servlet或JSP页面)。
         * chain.doFilter处理过滤器的其余部分(如果有的话),最终处理请求的servlet或JSP页面。
         */
        chain.doFilter(request,response);
    }

3)URL级别的权限访问控制

4)压缩响应信息

Java过滤器与拦截器的区别