当前位置:首页 > 技术 > 正文内容

SpringBoot 拦截器中依赖注入的实现方案

访客 技术 2026年9月28日 14

在 SpringBoot 构建 Web 应用的过程中,拦截器(Interceptor)常被用于权限验证、日志记录或请求预处理。然而,默认通过 WebMvcConfigurer 注册的拦截器实例并不受 Spring 容器管理,这导致无法直接在拦截器类中使用 @Autowired 或 @Value 进行依赖注入。本文将介绍两种在拦截器中获取 Spring Bean 的常用技术方案。

一、基础环境准备

项目基于 SpringBoot 框架搭建,核心依赖为 Web 启动器。以下是 Maven 依赖配置:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

二、拦截器实现与问题

首先定义一个基础的访问控制拦截器,实现 HandlerInterceptor 接口。该拦截器旨在校验请求头中的特定标识,若符合预期则放行,否则拦截请求。

<Slf4j>
public class AuthFilterInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String token = request.getHeader("X-Auth-Identifier");
        // 此处硬编码了校验值,实际生产中应从配置中心或数据库获取
        if ("valid-user-token".equals(token)) {
            return true;
        }
        log.warn("权限校验失败,Token: {}", token);
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        log.debug("请求处理完成");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        log.debug("资源清理完成");
    }
}

在主启动类中注册该拦截器:

<RestController>
<SpringBootApplication>
public class WebApplication implements WebMvcConfigurer {

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

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new AuthFilterInterceptor()).addPathPatterns("/**");
    }

    @GetMapping("/data")
    public String getData() {
        return UUID.randomUUID().toString();
    }
}

上述代码中,校验值 valid-user-token 被硬编码在 Java 文件中。若希望从配置文件读取该值,或在拦截器中调用其他 Service Bean,直接添加注解将无法生效,因为拦截器实例是通过 new 关键字手动创建的,不在 Spring 上下文管理范围内。

三、解决方案

1. 静态上下文工具类

第一种方案是创建一个工具类,实现 ApplicationContextAware 接口,将 Spring 容器上下文静态保存。通过该工具类,可以在任何地方手动获取 Bean 或配置属性。

<Component>
public class BeanLocator implements ApplicationContextAware {
    private static ApplicationContext context;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        BeanLocator.context = applicationContext;
    }

    public static <T> T getBean(Class<T> clazz) {
        return context.getBean(clazz);
    }

    public static String getConfig(String key) {
        Environment env = context.getBean(Environment.class);
        return env.getProperty(key);
    }
}

修改拦截器逻辑,通过工具类读取配置:

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    String token = request.getHeader("X-Auth-Identifier");
    String expectedToken = BeanLocator.getConfig("auth.required.token");
    
    if (Objects.equals(expectedToken, token)) {
        return true;
    }
    log.warn("权限校验失败,Token: {}", token);
    return false;
}

此方案通用性强,无需改变拦截器的注册方式,但依赖静态方法,测试稍显不便。

2. 将拦截器注册为 Spring Bean

第二种方案更为优雅,即将拦截器本身声明为 Spring 容器管理的 Bean。这样拦截器内部就可以正常使用依赖注入。在注册拦截器到注册表时,不再手动 new 实例,而是注入已管理的 Bean。

修改主配置类,增加 Bean 定义方法:

<RestController>
<SpringBootApplication>
public class WebApplication implements WebMvcConfigurer {

    @Autowired
    private AuthFilterInterceptor authFilterInterceptor;

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

    @Bean
    public AuthFilterInterceptor authFilterInterceptor() {
        return new AuthFilterInterceptor();
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(authFilterInterceptor).addPathPatterns("/**");
    }

    @GetMapping("/data")
    public String getData() {
        return UUID.randomUUID().toString();
    }
}

此时,AuthFilterInterceptor 类内部可以直接使用 @Autowired 注入其他服务,或使用 @Value 读取配置属性,完全符合 Spring 的标准开发模式。

标签: spring-boot

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

linux screen 用法详情 (nohup 的替代方案)

一、screen 是什么?能干嘛?screen 是一个终端复用器,可以:在一个 SSH 会话中开多个“虚拟终端”SSH 断线后,程序仍然在后台运行随时重新连接到原来的会话特别适合:nohup 的替代方案跑脚本 / 爬虫 / 训练模型运维、远程开发二、安装 screen# CentOS / Rocky / Almayum install -y screen# Debian / Ubuntuapt i...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。