ContextRefreshedEvent事件解决初始化

本文介绍在Spring框架下,如何利用监听ContextRefreshedEvent事件进行应用启动时的初始化操作,包括解决web应用中因父子容器导致的事件重复触发问题。
Author:赵志乾
Date:2019-05-16
Declaration:All Right Reserved!!!

实际项目开发中,经常会遇到“应用启动时进行初始化”的诉求。在基于Spring框架的项目中,解决方案如下:

1、监听ContextRefreshedEvent事件

Spring容器初始化完成后(onRefresh)会触发ContextRefreshedEvent事件,因此可以在监听该事件的方法中完成一些初始化操作。

//使用注解@Commponent将MyInit交由Spring IoC容器进行管理
@Component
//实现ApplicationListener接口来作为应用事件监听者,并通过指定泛型参数为
//ContextRefreshedEvent来表明自己只关心ContextRefreshedEvent事件
public class MyInit implements ApplicationListener<ContextRefreshedEvent> {

    @Override
    //事件处理函数
    public void onApplicationEvent(ContextRefreshedEvent event){
        //此处判断主要是用于解决web应用中的重复刷新问题,因为web应用中会存在父子容器,导致
        //事件ContextRefreshedEvent会被触发多次。通过限定只在父容器刷新事件触发时才进行
        //处理,从而解决多次触发问题。
        if(event.getApplicationContext().getParent()==null){
            //初始化函数
            init();
        }
    }

    //自定义初始化
    private void init(){
        //自定义的初始化逻辑
    }
}

 

 

### 解决方案 SaTokenContext 初始化失败的问题通常是因为未正确注入 SaToken 的上下文处理器。根据提供的信息[^1],Sa-Token 底层需要确认最终运行的 Web 容器,并通过抽象的 `SaTokenContext` 接口对接不同的容器。这种对接需要注入具体的实现类,而这个注入工作通常是框架自动完成的。 如果出现 `SaTokenException: 未初始化任何有效上下文处理器` 的错误,可以按照以下方法解决: #### 1. 确保引入了正确的依赖 确保项目中引入了与当前使用的框架匹配的 Sa-Token Starter 依赖。例如,在 Spring Boot 3 项目中,应添加以下依赖[^2]: ```xml <dependency> <groupId>cn.dev33</groupId> <artifactId>sa-token-spring-boot3-starter</artifactId> <version>1.42.0</version> </dependency> ``` #### 2. 配置文件设置 在项目的配置文件(如 `application.yml` 或 `application.properties`)中,确保正确设置了 Sa-Token 的相关配置项。例如: ```yaml sa-token: token-name: satoken timeout: 2592000 is-concurrent: true kickout: false ``` #### 3. 检查上下文处理器是否正确加载 如果仍然出现上下文未初始化的问题,可能是框架未能正确加载上下文处理器。可以通过手动方式指定上下文处理器来解决。例如,在 Spring Boot 中,可以显式地配置 `SaTokenContext` 的实现类: ```java import cn.dev33.sa.token.context.SaTokenContext; import cn.dev33.sa.token.context.SaTokenSpringBoot3Context; public class SaTokenConfig { public static void initSaTokenContext() { // 手动指定 SaTokenContext 的实现类 SaTokenContext.setContext(new SaTokenSpringBoot3Context()); } } ``` 然后在项目启动时调用该方法以初始化上下文。 #### 4. 处理二级上下文支持 如果项目中同时存在基于 HTTP 的 Web 访问和 Dubbo 的 RPC 调用,则需要提供二级上下文支持。可以通过实现 `SaTokenSecondContext` 接口并注册到系统中来解决[^3]。例如: ```java import cn.dev33.sa.token.context.SaTokenContext; import cn.dev33.sa.token.context.SaTokenSecondContext; public class CustomSaTokenSecondContext implements SaTokenSecondContext { @Override public SaRequest getRequest() { // 自定义实现 return null; } @Override public SaResponse getResponse() { // 自定义实现 return null; } @Override public SaStorage getStorage() { // 自定义实现 return null; } @Override public boolean matchPath(String pattern, String path) { // 自定义实现 return false; } @Override public boolean isValid() { // 自定义实现 return false; } } // 注册自定义上下文 SaTokenContext.setContext(new CustomSaTokenSecondContext()); ``` #### 5. 检查项目运行环境 确保项目运行的 Web 容器与 Sa-Token 支持的容器类型一致。如果使用的是非标准容器(如嵌入式容器或自定义容器),可能需要手动实现 `SaTokenContext` 并注册到系统中。 --- ### 注意事项 - 如果项目中仅使用 Feign 进行服务间调用,则无需启用二级上下文支持。 - 确保所有依赖版本兼容,尤其是 Spring Boot 和 Sa-Token 的版本。 --- ### 示例代码 以下是一个完整的配置示例,展示如何初始化 SaTokenContext 并集成到 Spring Boot 项目中: ```java import cn.dev33.sa.token.context.SaTokenContext; import cn.dev33.sa.token.context.SaTokenSpringBoot3Context; import org.springframework.context.ApplicationListener; import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.stereotype.Component; @Component public class SaTokenInitializer implements ApplicationListener<ContextRefreshedEvent> { @Override public void onApplicationEvent(ContextRefreshedEvent event) { // 初始化 SaTokenContext if (SaTokenContext.getContext() == null) { SaTokenContext.setContext(new SaTokenSpringBoot3Context()); } } } ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我叫白小猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值