SpringBoot 中Filter的作用以及使用

SpringBoot 中Filter的作用以及使用
1、Filter的作用

Filter使用户可以改变一个 request和修改一个response.
Filter 不是一个servlet,它不能产生一个response,它能够在一个request到达servlet之前预处理request,也可以在离开 servlet时处理response.
换种说法,filter其实是一个”servlet chaining”(servlet 链).
通俗点说法filter相当于加油站,request是条路,response是条路,
目的地是servlet,这个加油站设在什么地方对什么数据操作可以由你来控制。
1
2
3
4
5
Filter过滤器实现的是javax.servlet.Filter接口的类,而在javax.servlet.Filter中定义了以下三个方法:

init(FilterConfig fConfig)
init()方法用来初始化过滤器,可以在init()方法中获取Filter中的初始化参数。
@Override
public void init(FilterConfig filterConfig) throws ServletException {
//用来获取Filter中初始化的参数
}
1
2
3
4
doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
doFilter()方法完成过滤操作。当请求发过来的时候,过滤器将执行doFilter方法。
在HttpServletRequest 执行doFilter()之前,根据需要检查 HttpServletRequest ,同时也可以修改HttpServletRequest 请求头和数据。
在HttpServletResponse 执行doFilter()之后,根据需要检查 HttpServletResponse ,同时也可以修改HttpServletResponse响应头和数据。
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println(“进行过滤以及逻辑判断操作”);
filterChain.doFilter(servletRequest,servletResponse);
}

1
2
3
4
5
6
destroy()
Filter对象创建后会驻留在内存,当web应用移除或服务器停止时调用destroy()方法进行销毁。在Web容器卸载 Filter 对象之前被调用。destroy()方法在Filter的生命周期中仅执行一次。通过destroy()方法,可以释放过滤器占用的资源。
@Override
public void destroy() {
//销毁Filter对象,Filter生命周期结束
}
1
2
3
4
上来我们先创建一个小demo 然后我们再讲解其中的原理
我们在IDEA中创建一个SpringBoot的基础项目(这里不介绍这么创建了)

一、这里采用的@WebFilter注解过滤
目录结构

@Order(x)x越小优先级 越高
@WebFilter 用于将一个类声明为过滤器,该注解将会在部署时被容器处理,容器将根据具体的属性配置将相应的类部署为过滤器。**该注解具有下表给出的一些常用属性 ( 以下所有属性均为可选属性,但是 value、urlPatterns、servletNames 三者必需至少包含一个,且 value 和 urlPatterns 不能共存,如果同时指定,通常忽略 value 的取值 )

package cn.tll.config;

import org.springframework.core.annotation.Order;

import javax.servlet.*;
import javax.servlet.FilterConfig;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

/**

  • @author tll

  • @create 2020/8/1 12:41

  • @Order(x) 里面的数越小 越优先执行

  • @WebFilter() 代表着这是个Filter类 并把它注入到容器中
    */
    @Order(1)
    @WebFilter(initParams = {@WebInitParam(name = “nofilter”,value = “/one,/two”)})
    public class FirstFilter implements Filter {

    /**

    • 不过滤的资源
      */
      private String[] nofilter;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    //将不过滤的资源存入数组中
    String nofilterString = filterConfig.getInitParameter(“nofilter”);
    if (nofilterString!=null&&nofilterString.length()>0){
    nofilter = nofilterString.split(",");
    }

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    HttpServletRequest request = (HttpServletRequest) servletRequest;
    boolean flag = isNofilter(request);
    if (flag){
    filterChain.doFilter(servletRequest,servletResponse);
    }else {
    request.getRequestDispatcher("/forword").forward(servletRequest,servletResponse);
    }

    }

    @Override
    public void destroy() {

    }
    /**
    *isNofilter 判断路径是否不需要过滤
    */
    public boolean isNofilter(HttpServletRequest request){
    String requestURI = request.getRequestURI();
    System.out.println(requestURI);
    for (String s : nofilter) {
    if (requestURI.contains(s)){
    return true;
    }
    }
    return false;
    }
    }

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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
Controller中的代码
这里的@RestController注解作用就不用多说了

package cn.tll.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**

  • @author tll

  • @create 2020/8/1 12:48
    */
    @RestController
    public class IndexController {

    @RequestMapping({"/","/index"})
    public String index(){
    return “访问成功”;
    }

    @RequestMapping("/forword")
    public String forword(){
    return “请先登录”;
    }

    @RequestMapping("/one")
    public String one(){
    return “one”;
    }

    @RequestMapping("/two")
    public String two(){
    return “two”;
    }
    }

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
最后千万不要忘了在启动类上加上@ServletComponentScan
注:@ServletComponentScan注解的含义在SpringBootApplication(启动类)上使用@ServletComponentScan注解后,Servlet、Filter(过滤器)、Listener(监听器)可以直接通过@WebServlet、@WebFilter、@WebListener注解自动注册,无需其他代码!

package cn.tll;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;

/**

  • 因为使用的是注解Filter 所以需要在程序入口加入@ServletComponentScan

*/
@SpringBootApplication
@ServletComponentScan
public class SpringbootFilterApplication {

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

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
二,@Bean注解方式
我们还是先创建一个干净的SpringBoot项目吧

首先把Controller写好 先测试一下有无问题

package cn.tll.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**

  • @author tll

  • @create 2020/8/2 8:51
    */
    @RestController
    public class IndexController {

    @RequestMapping({"/","/index"})
    public String index(){
    return “欢迎进入首页”;
    }

    @RequestMapping(“noRoot”)
    public String noRoot(){
    return “对不起,请先登录”;
    }

    @RequestMapping("/one")
    public String one(){
    return “one”;
    }

    @RequestMapping("/two")
    public String two(){
    return “two”;
    }

}

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

好的没问题
再创建一个WebConfig

package cn.tll.config;

import cn.tll.filter.FirstFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**

  • @author tll

  • @create 2020/8/2 8:57
    */
    @Configuration
    public class WebConfig {

    @Bean
    public FilterRegistrationBean filterRegistrationBean(){
    FilterRegistrationBean registrationBean = new FilterRegistrationBean(new FirstFilter());
    //过滤所有路径
    registrationBean.addUrlPatterns("/*");
    //添加不过滤路径
    registrationBean.addInitParameter(“noFilter”,"/one,/two");
    registrationBean.setName(“firstFilter”);
    registrationBean.setOrder(1);
    return registrationBean;
    }

    @Bean
    public FilterRegistrationBean twoFilterRegistrationBean(){
    FilterRegistrationBean registrationBean = new FilterRegistrationBean(new TwoFilter());
    registrationBean.setOrder(2);
    registrationBean.addUrlPatterns("/*");
    registrationBean.setName(“TwoFilter”);
    return registrationBean;
    }
    }

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
接着就是创建Filter了
这里创建两个Filter主要是用于查看setOrder优先级是否有用
Order(x) 里面的x数值越小优先级越高

package cn.tll.filter;

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

/**

  • @author tll

  • @create 2020/8/2 9:00
    */
    public class FirstFilter implements Filter {

    private String[] noFilters;

    /**

    • 过滤器初始化
    • @param filterConfig
    • @throws ServletException
      */
      @Override
      public void init(FilterConfig filterConfig) throws ServletException {
      String noFilter = filterConfig.getInitParameter(“noFilter”);
      if (noFilter!=null&&noFilter.length()>0){
      noFilters = noFilter.split(",");
      }
      }

    /**

    • 过滤器方法
    • @param servletRequest
    • @param servletResponse
    • @param filterChain
    • @throws IOException
    • @throws ServletException
      */
      @Override
      public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
      System.out.println(“这里是FirstFilter”);
      HttpServletRequest request = (HttpServletRequest) servletRequest;
      boolean flag = isFilter(request);
      if (flag){
      System.out.println(“可以访问”);
      filterChain.doFilter(servletRequest,servletResponse);
      }else {
      System.out.println(“不可以访问”);
      //没有权限不可以访问,需要转发到友好界面
      request.getRequestDispatcher("/noRoot").forward(servletRequest,servletResponse);
      }
      }

    /**

    • 过滤器销毁
      */
      @Override
      public void destroy() {

    }

    /**

    • 判断URL是否包含不过滤的路径

    • @param request

    • @return
      */
      public boolean isFilter(HttpServletRequest request){
      String requestURI = request.getRequestURI();
      for (String noFilter : noFilters) {
      System.out.println(noFilter);
      if (requestURI.contains(noFilter)){
      return true;

       }
      

      }
      return false;
      }
      }

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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
package cn.tll.filter;

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

/**

  • @author tll

  • @create 2020/8/2 9:23
    */
    public class TwoFilter 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(“这里是TwoFiter”);
    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
大功告成,你觉得那种方法简单呢?
源码地址
@WebFilter注解开发

@Bean注解开发源码
————————————————
版权声明:本文为CSDN博主「天亮再出发」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_43483502/article/details/107733067

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值