服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Java教程 - 浅谈Springboot实现拦截器的两种方式

浅谈Springboot实现拦截器的两种方式

2021-11-25 13:25怪咖软妹@ Java教程

本文详细的介绍了Springboot拦截器的两种方式实现,一种就是用拦截器,一种就是过滤器,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

实现过滤请求有两种方式:

一种就是用拦截器,一种就是过滤器

拦截器相对来说比较专业,而过滤器虽然不专业但是也能完成基本的拦截请求要求。

一、拦截器方式

1、配置HandlerInterceptor

下面这个也是我们公司项目拦截器的写法,总体来说感觉还不错,我就记录了下来。
利用了一个静态Pattern变量存储不走拦截器的路径,然后在preHandle方法当中进行过滤,让他返回true。

?
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
@Component
public class LoginInterceptor implements HandlerInterceptor{
    
    private static final Pattern SHOULD_NOT_FILTER_URL_PATTERN;
    
    static {
        List<String> urlList = new ArrayList<>();
        // 将不走拦截器的请求存放到Pattern
        urlList.add("(socket/.*)");
        urlList.add("(user/findUserList)");
        StringBuilder sb = new StringBuilder();
        for (String url : urlList) {
            sb.append(url);
            sb.append("|");
        }
        sb.setLength(sb.length() - 1);
        SHOULD_NOT_FILTER_URL_PATTERN = Pattern.compile(sb.toString());
    }
    
    /**
     * 在请求处理之前进行调用(Controller方法调用之前)
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        
        HttpSession session = request.getSession();
        // 获取访问的url
        String servletPath = request.getServletPath();
        // 排除特定请求
        if (SHOULD_NOT_FILTER_URL_PATTERN.matcher(servletPath).find()) {
            return true;
        }
        if (session.getAttribute("user") != null) {
            // 可能有的项目在校验完session,还会校验token
            String token = request.getHeader("access_token");
            // 此处业务省略。。。
            return true;
        }
        return false;
    }
 
    /**
     * 请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
        // TODO Auto-generated method stub
        
    }
 
    /**
     * 在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作)
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        // TODO Auto-generated method stub
        
    }
}

2、注册拦截器

配置完上面的拦截器还需要注册拦截器。

WebMvcConfigurerAdapter类是 Spring内部的一种配置方式
采用JavaBean的形式来代替传统的xml配置文件形式进行针对框架个性化定制

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Configuration
public class MyWebAppConfigurer extends WebMvcConfigurerAdapter {
    
    @Autowired
    private LoginInterceptor loginInterceptor;
    
 
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 多个拦截器组成一个拦截器链
        // addPathPatterns 用于添加拦截规则
        // excludePathPatterns 用户排除拦截
        registry.addInterceptor(loginInterceptor).addPathPatterns("/**");
        super.addInterceptors(registry);
    }
}

3、使用拦截器的坑

继承WebMvcConfigurerAdapter 重写addInterceptors方法的时候,一定要使用注入方式,将loginInterceptor注入到变量当中,要么就使用@Bean注解的方式,将loginInterceptor(拦截器)注入到容器。

之所以这么搞是因为拦截器在 Bean 初始化之前进行,所以在拦截器中无法像这样注入 Bean。
就算加了@Component,他是存放于容器当中了,但是他存放容器当中的对象属性,是空属性。

浅谈Springboot实现拦截器的两种方式 浅谈Springboot实现拦截器的两种方式

在WebMvcConfigurerAdapter 使用@Autowired注入了一遍拦截器,属性就有值了。

说白了不管采用哪种方案,目的只有一个,让对象的属性有值,因为拦截器比其他对象初始化早,导致属性为空,想让他有值,就想办法让他重新走一遍spring注入容器,也可以采用这种方式:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Configuration
public class MyWebAppConfigurer extends WebMvcConfigurerAdapter {
    
    // 这么写的目的是为了在SessionInterceptor中能注入spring中的service
    @Bean
    LoginInterceptor loginInterceptor() {
        return new LoginInterceptor();
    }
 
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 多个拦截器组成一个拦截器链
        // addPathPatterns 用于添加拦截规则
        // excludePathPatterns 用户排除拦截
        registry.addInterceptor(loginInterceptor()).addPathPatterns("/**");
        super.addInterceptors(registry);
    }
}

二、过滤器方式

本人这一篇博客写了关于filter的一些知识:http://www.zzvips.com/article/207461.html

1、实现Filter接口

?
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
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Component;
 
@Component
@WebFilter(filterName = "requestParamFilter",urlPatterns = "/*")
public class RequestParamFilter implements Filter {
 
    private static final Pattern SHOULD_NOT_FILTER_URL_PATTERN;
    
    static {
        List<String> urlList = new ArrayList<>();
        // 将不走拦截器的请求存放到Pattern
        urlList.add("(socket/.*)");
        urlList.add("(user/findUserList)");
        StringBuilder sb = new StringBuilder();
        for (String url : urlList) {
            sb.append(url);
            sb.append("|");
        }
        sb.setLength(sb.length() - 1);
        SHOULD_NOT_FILTER_URL_PATTERN = Pattern.compile(sb.toString());
    }
 
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
 
    }
    
    // 发送请求会执行这个方法
    // 一个doFilter相当于拦截器的执行前和执行后
    // filterChain.doFilter后面的内容就是执行后的内容,假如不执行filterChain.doFilter方法相当于方法被拦截
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
                         FilterChain filterChain) throws IOException, ServletException {
        System.out.println("sunhan---请求参数过滤器!---test1");
        HttpServletRequest request = (HttpServletRequest)servletRequest;
        HttpSession session = request.getSession();
        // 获取访问的url
        String servletPath = request.getServletPath();
        // 排除特定请求
        if (SHOULD_NOT_FILTER_URL_PATTERN.matcher(servletPath).find()) {
            filterChain.doFilter(servletRequest,servletResponse);
        }
        System.out.println("开始拦截了................");
        //业务代码
    }
 
    @Override
    public void destroy() {
 
    }
}

2、使用过滤器需要注意的

拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑

执行顺序如下:

浅谈Springboot实现拦截器的两种方式

到此这篇关于浅谈Springboot实现拦截器的两种方式的文章就介绍到这了,更多相关Springboot 拦截器内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/weixin_43888891/article/details/119778754

延伸 · 阅读

精彩推荐
  • Java教程java设计模式之装饰器模式(Decorator)

    java设计模式之装饰器模式(Decorator)

    这篇文章主要为大家详细介绍了java设计模式之装饰器模式Decorator,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    yuminfeng7283732020-07-21
  • Java教程Java移除无效括号的方法实现

    Java移除无效括号的方法实现

    本文主要介绍了Java移除无效括号的方法实现,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    王小二(海阔天空)3882021-11-09
  • Java教程Java通用Mapper UUID简单示例

    Java通用Mapper UUID简单示例

    今天小编就为大家分享一篇关于Java通用Mapper UUID简单示例,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看...

    isea5335312021-06-24
  • Java教程Mybatis 开发注解快速入门

    Mybatis 开发注解快速入门

    mybatis是一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架。这篇文章主要介绍了Mybatis 开发注解快速入门的相关资料,需要的朋友可以参考下 ...

    坚守一辈子的幸福4912020-07-07
  • Java教程Java源码解析TreeMap简介

    Java源码解析TreeMap简介

    今天小编就为大家分享一篇关于Java源码解析TreeMap简介,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看...

    李灿辉7902021-06-29
  • Java教程java TreeMap源码解析详解

    java TreeMap源码解析详解

    这篇文章主要介绍了java TreeMap源码解析详解的相关资料,需要的朋友可以参考下...

    Walker_YAM3062020-09-06
  • Java教程Java遍历集合的三种方式

    Java遍历集合的三种方式

    本文主要对于遍历集合获取其对象,总结的三种简单的方式进行介绍,文章中举了两个案例进行对比,具有很好的参考价值,下面就跟小编一起来看下吧...

    Bigerf5362020-07-14
  • Java教程MyBatis Plus 将查询结果封装到指定实体的方法步骤

    MyBatis Plus 将查询结果封装到指定实体的方法步骤

    这篇文章主要介绍了MyBatis Plus 将查询结果封装到指定实体的方法步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值...

    魔有追求6872020-09-26