dede静态网站模板下载,营销型网站制作服务商,怎么做网页个人信息,wordpress 科技公司背景
最近需要实现一个对于系统的授权检测功能#xff0c;即当SpringBoot应用被启动时#xff0c;需要当前设备是否具有有效的的授权许可信息#xff0c;若无则直接退出应用。具体的实现方案请继续看下文。
环境
Ruoyi-Vue SpringBoot3 RuoYi-Vue: #x1f389; 基于Spr…背景
最近需要实现一个对于系统的授权检测功能即当SpringBoot应用被启动时需要当前设备是否具有有效的的授权许可信息若无则直接退出应用。具体的实现方案请继续看下文。
环境
Ruoyi-Vue SpringBoot3 RuoYi-Vue: 基于SpringBootSpring SecurityJWTVue Element 的前后端分离权限管理系统同时提供了 Vue3 的版本 - Gitee.comhttps://gitee.com/y_project/RuoYi-Vue/tree/springboot3/
初始实现
基于文章开头所提到需求很容易想到可以在主启动类中编写相关代码来实现由于我们需要的是在类加载初期校验并且我们可能需要从配置文件中获取部分信息因此需要使用如下方法来编写代码。
首先在当前主启动类所在的包下新建utils包用于校验代码的编写 新建校验工具类InitCheckUtil代码如下
Component
public class InitCheckUtil {Value(${init.key})private String key;PostConstructpublic void check() {if (StringUtils.isBlank(key) || !ruoyi.equals(key)) {System.out.println(系统未授权请联系管理员);System.exit(0);}else{System.out.println(current key is: key system is authorized);}}
}不难看出这个校验工具的逻辑为首先从配置文件(application.yml)中加载了init.key的值配文件信息如下: 之后通过check方法来判断获取的key是否为 ruoyi 若不满足条件则直接退出。执行代码后结果如下: 可以看到已经打印了当前key值并表明系统已经进行了了授权。需要注意的是这里的PostConstruct注解确保了Spring容器启动时就会执行这个方法。
目前来看似乎已经完成了我们的需求但是如果现在想要在项目启动前就执行呢而不是等到容器加载时在校验可以看到输出当前key信息之前已经有其它的日志信息更为复杂的项目在启动时往往伴随着更多的前置初始化的东西那么如何在SpringBoot类启动前就进行校验呢?
ApplicationContextInitializer
上一小节我们已经实现了一个初步版本而为了能够满足新的启动之前的即校验需求我们需要做进一步的改动。首先可以想到的便是在主启动类中进行加载直接在启动方法之前使用创建InitCheckUtil对象的方式然后调用其check方法。 如果此时直接启动项目将会出现如下效果 看起来似乎实现了启动前的校验但是我们并没有更改配置文件中的key值正常情况下服务应该是启动成功的状态。但目前状况的原因是由于我们现在的代码先于Spring容器执行因此Value注解将无法正常读取到key值进而校验失败因此InitCheckUtil类的代码变为:
public class InitCheckUtil {private String key;public InitCheckUtil(){}public InitCheckUtil(String key){this.key key;}public void check() {if (StringUtils.isBlank(key) || !ruoyi.equals(key)) {System.out.println(系统未授权请联系管理员);System.exit(0);}else{System.out.println(current key is: key , system is authorized);}}
}
但由于没有了Spring容器的能力的加持此时对于配置文件读取就无法直接使用Value注解来获取了因此我们现在使用使用一种新的方式来实现对配置文件的读取即通过ApplicationContextInitializer 接口它的作用在于当容器启动之前就可以读取配置文件中的值从而满足我们当前的需求具体实现如下新建CheckConfigInitlnitializer类并实现 ApplicationContextInitializer 接口的 initialize 方法在该方法中通过applicationContext获取ConfigurableEnvironment 对象进而获取配置文件中的信息后传入校验类中实现校验:
public class CheckConfigInitializer implements ApplicationContextInitializer {Overridepublic void initialize(ConfigurableApplicationContext applicationContext) {ConfigurableEnvironment environment applicationContext.getEnvironment();String initKey environment.getProperty(init.key);InitCheckUtil checkUtil new InitCheckUtil(initKey);checkUtil.check();}
}
由于我们更改了配置文件的获取方式因此主启动类的中内容也需要做相关的更改如下所示增加了对于初始化器的注册从而可以确保可以在整个容器启动之前完成校验。
SpringBootApplication(exclude { DataSourceAutoConfiguration.class })
public class RuoYiApplication
{public static void main(String[] args){SpringApplication application new SpringApplication(RuoYiApplication.class);application.addInitializers(new CheckConfigInitializer());application.run( args);System.out.println((♥◠‿◠) 若依启动成功 ლ(´ڡლ) \n .-------. ____ __ \n | _ _ \\ \\ \\ / / \n | ( ) | \\ _. / \n |(_ o _) / _( )_ . \n | (_,_). __ ___(_ o _) \n | |\\ \\ | || |(_,_) \n | | \\ /| - / \n | | \\ / \\ / \n - - -..- );}
} 此时系统可正常启动并输出相应的校验信息如下 自动装配
在上一步中我们已经基本实现了对于文章开头提出需求问题的解决但是若后续存在类似需求时需要我们不断往主主启动类中添加代码。这种方法看起来极为的不优雅整个启动类会变得愈发臃肿。因此我们可以通过SpringBoot中的自动装配机制对上面的代码进行进一步的调整优化。
其实目前优化的方式严格意义上时上一步的另一种实现方式这里将通过使用spring.factories文件来代替在主启动类中显式的注册初始化类。通过在项目当前模块的resources目录下新建META-INF 文件夹(不存在则新建)并新增 spring.factories 文件该文件的内容将在Spring容器启动前进行扫描并加载若为了实现通用性可将其迁移至common模块中此处仅做展示用方便起见未进行迁移。 在spring.factories 文件中添加如下内容其中 key 为 org.springframework.context.ApplicationContextInitialize 固定值value 为我们自定义的实现的全包名。
org.springframework.context.ApplicationContextInitializercom.ruoyi.utils.CheckConfigInitializer
这个时候就可以将启动类中的代码还原为原始的状态再次启动程序后发现系统可以正常运行其原理为当SpringApplication初始化时通过SpringFactoriesLoader获取到配置在 META-INF/spring.factories 文件中的 ApplicationContextInitializer 的所有实现类进而加载到容器中而在这个过程中将实现对了系统启动的初步校验。