300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > 为基于spring-boot的应用添加根据运行时操作系统环境来提示用户选择active profile的功能...

为基于spring-boot的应用添加根据运行时操作系统环境来提示用户选择active profile的功能...

时间:2022-03-03 21:49:19

相关推荐

为基于spring-boot的应用添加根据运行时操作系统环境来提示用户选择active profile的功能...

spring-boot有一个根据JVM变量-Dspring.profiles.active来设置运行时的active profile的功能,但是有些时候我们也许会不小心忘记设置这个变量,这样在生产环境中会带来一定的困扰,所以我想了一个办法,来给忘记设置-Dspring.profiles.active的程序员一次“secend chance”。

先来讲一下思路:

step0 约定好profiles的命名,“development”代表开发环境(也可以将默认的profile设为开发环境),“production”代表生产环境step1 判断是否设置了-Dspring.profiles.active,如果已经设置,直接跳转step3step2 判断当前操作系统环境,如果不是Linux环境则认定为开发环境,自动倒计时激活开发的profile;如果是Linux环境则认定为生产环境,输出选择profile的控制台信息,并等待用户控制台输入进行选择,并依据用户选择来激活profilestep3SpringApplication.run()

代码如下:

spring-boot配置文件(使用了默认profile作为开发环境):

spring:application:name: comchangyoueurekaserver #注意命名要符合RFC 2396,否则会影响服务发现 详见/questions/37062828/spring-cloud-brixton-rc2-eureka-feign-or-rest-template-configuration-not-worserver:port: 8001eureka:instance:hostname: localhostclient:registerWithEureka: falsefetchRegistry: falseserviceUrl:defaultZone: http://${eureka.instance.hostname}:${server.port}---spring:profiles: productionapplication:name: comchangyoueurekaserverserver:port: 8001eureka:instance:hostname: localhostclient:registerWithEureka: falsefetchRegistry: falseserviceUrl:defaultZone: http://${eureka.instance.hostname}:${server.port}复制代码

BootStarter封装了step1-step3的逻辑:

import mons.lang3.StringUtils;import java.util.Scanner;import java.util.Timer;import java.util.TimerTask;import java.util.regex.Pattern;public class BootStarter {//用于后续Spring Boot操作的回调public interface Callback {void bootRun();}private boolean enableAutomaticallyStart = true;private int automaticallyStartDelay = 10;public boolean isEnableAutomaticallyStart() {return enableAutomaticallyStart;}public void setEnableAutomaticallyStart(boolean enableAutomaticallyStart) {this.enableAutomaticallyStart = enableAutomaticallyStart;}public int getAutomaticallyStartDelay() {return automaticallyStartDelay;}public void setAutomaticallyStartDelay(int automaticallyStartDelay) {this.automaticallyStartDelay = automaticallyStartDelay;}public void startup(boolean enableAutomaticallyStart, int automaticallyStartDelay, Callback callback) {if (StringUtils.isBlank(System.getProperty("spring.profiles.active"))) { //如果没有通过参数spring.profiles.active设置active profile则让用户在控制台自己选择System.out.println("***Please choose active profile:***\n\tp: production\n\td: development");final boolean[] started = {false};Timer timer = new Timer();if (enableAutomaticallyStart && System.getProperty("os.name").lastIndexOf("Linux") == -1) { //如果当前操作系统环境为非Linux环境(一般为开发环境)则automaticallyStartDelay秒后自动设置为开发环境System.out.printf("\nSystem will automatically select 'd' in %d seconds.\n", automaticallyStartDelay);final int[] count = {automaticallyStartDelay};timer.scheduleAtFixedRate(new TimerTask() {@Overridepublic void run() {if (count[0]-- == 0) {timer.cancel();started[0] = true;System.setProperty("spring.profiles.active", "development");callback.bootRun();}}}, 0, 1000);}Scanner scanner = new Scanner(System.in);Pattern pattern = pile("^p|d$");//如果是Linux系统(一般为生产环境)则强制等待用户输入(一般是忘记设置spring.profiles.active了,这等于给了设置active profile的"second chance")while (scanner.hasNextLine()) {if (started[0]) {break;}String line = scanner.nextLine();if (!pattern.matcher(line).find()) {System.out.println("INVALID INPUT!");} else {timer.cancel();System.setProperty("spring.profiles.active", line.equals("d") ? "development" : "production");callback.bootRun();break;}}} else { //如果已经通过参数spring.profiles.active设置了active profile直接启动callback.bootRun();}}public void startup(Callback callback) {startup(this.enableAutomaticallyStart, this.automaticallyStartDelay, callback);}}复制代码

main():

import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.flix.eureka.server.EnableEurekaServer;import org.springframework.context.ApplicationContext;@EnableEurekaServer@SpringBootApplicationpublic class App {private static final Logger LOGGER = LoggerFactory.getLogger(App.class);public static void main(String[] args) {new BootStarter().startup(() -> {ApplicationContext applicationContext = SpringApplication.run(App.class, args);for (String activeProfile : applicationContext.getEnvironment().getActiveProfiles()) {LOGGER.warn("***Running with profile: {}***", activeProfile);}});}}复制代码

运行效果(开发环境Mac OS):

扩展: 其实在这里我们还可以发散一下思维,基于spring-boot的应用比起传统spring应用的一大优势是自己可以掌控main()方法,有了这一点,我们是能玩出很多花样来的,思路不要被局限在tomcat时代了。

main法在手,天下我有。

-1-22更新:增加了线程安全的处理

import mons.lang3.StringUtils;import java.util.Scanner;import java.util.Timer;import java.util.TimerTask;import java.util.regex.Pattern;public class BootStarter {private volatile boolean started;//用于后续Spring Boot操作的回调public interface Callback {void bootRun();}private boolean enableAutomaticallyStart = true;private int automaticallyStartDelay = 3;public boolean isEnableAutomaticallyStart() {return enableAutomaticallyStart;}public void setEnableAutomaticallyStart(boolean enableAutomaticallyStart) {this.enableAutomaticallyStart = enableAutomaticallyStart;}public int getAutomaticallyStartDelay() {return automaticallyStartDelay;}public void setAutomaticallyStartDelay(int automaticallyStartDelay) {this.automaticallyStartDelay = automaticallyStartDelay;}public void startup(boolean enableAutomaticallyStart, int automaticallyStartDelay, Callback callback) {if (StringUtils.isBlank(System.getProperty("spring.profiles.active"))) { //如果没有通过参数spring.profiles.active设置active profile则让用户在控制台自己选择System.out.println("***Please choose active profile:***\n\tp: production\n\td: development");Timer timer = new Timer();if (enableAutomaticallyStart && System.getProperty("os.name").lastIndexOf("Linux") == -1) { //如果当前操作系统环境为非Linux环境(一般为开发环境)则automaticallyStartDelay秒后自动设置为开发环境System.out.printf("\nSystem will automatically select 'd' in %d seconds.\n", automaticallyStartDelay);timer.scheduleAtFixedRate(new TimerTask() {private ThreadLocal<Integer> countDown = ThreadLocal.withInitial(() -> automaticallyStartDelay);@Overridepublic void run() {if (countDown.get() == 0) {timer.cancel();started = true;System.setProperty("spring.profiles.active", "development");callback.bootRun();}countDown.set(countDown.get() - 1);}}, 0, 1000);}Scanner scanner = new Scanner(System.in);Pattern pattern = pile("^p|d$");//如果是Linux系统(一般为生产环境)则强制等待用户输入(一般是忘记设置spring.profiles.active了,这等于给了设置active profile的"second chance")while (scanner.hasNextLine()) {if (started) {break;}String line = scanner.nextLine();if (!pattern.matcher(line).find()) {System.out.println("INVALID INPUT!");} else {timer.cancel();System.setProperty("spring.profiles.active", line.equals("d") ? "development" : "production");callback.bootRun();break;}}} else { //如果已经通过参数spring.profiles.active设置了active profile直接启动callback.bootRun();}}public void startup(Callback callback) {startup(this.enableAutomaticallyStart, this.automaticallyStartDelay, callback);}}复制代码

-01-25更新:

补上了try-with-resource

import mons.lang3.StringUtils;import java.util.Scanner;import java.util.Timer;import java.util.TimerTask;import java.util.regex.Pattern;public class BootStarter {private volatile boolean started;//用于后续Spring Boot操作的回调public interface Callback {void bootRun();}private boolean enableAutomaticallyStart = true;private int automaticallyStartDelay = 3;public boolean isEnableAutomaticallyStart() {return enableAutomaticallyStart;}public void setEnableAutomaticallyStart(boolean enableAutomaticallyStart) {this.enableAutomaticallyStart = enableAutomaticallyStart;}public int getAutomaticallyStartDelay() {return automaticallyStartDelay;}public void setAutomaticallyStartDelay(int automaticallyStartDelay) {this.automaticallyStartDelay = automaticallyStartDelay;}public void startup(boolean enableAutomaticallyStart, int automaticallyStartDelay, Callback callback) {if (StringUtils.isBlank(System.getProperty("spring.profiles.active"))) { //如果没有通过参数spring.profiles.active设置active profile则让用户在控制台自己选择System.out.println("***Please choose active profile:***\n\tp: production\n\td: development");Timer timer = new Timer();if (enableAutomaticallyStart && System.getProperty("os.name").lastIndexOf("Linux") == -1) { //如果当前操作系统环境为非Linux环境(一般为开发环境)则automaticallyStartDelay秒后自动设置为开发环境System.out.printf("\nSystem will automatically select 'd' in %d seconds.\n", automaticallyStartDelay);timer.scheduleAtFixedRate(new TimerTask() {private ThreadLocal<Integer> countDown = ThreadLocal.withInitial(() -> automaticallyStartDelay);@Overridepublic void run() {if (countDown.get() == 0) {timer.cancel();started = true;System.setProperty("spring.profiles.active", "development");callback.bootRun();}countDown.set(countDown.get() - 1);}}, 0, 1000);}try (Scanner scanner = new Scanner(System.in)) {Pattern pattern = pile("^p|d$");//如果是Linux系统(一般为生产环境)则强制等待用户输入(一般是忘记设置spring.profiles.active了,这等于给了设置active profile的"second chance")while (scanner.hasNextLine()) {if (started) {break;}String line = scanner.nextLine();if (!pattern.matcher(line).find()) {System.out.println("INVALID INPUT!");} else {timer.cancel();System.setProperty("spring.profiles.active", line.equals("d") ? "development" : "production");callback.bootRun();break;}}}} else { //如果已经通过参数spring.profiles.active设置了active profile直接启动callback.bootRun();}}public void startup(Callback callback) {startup(this.enableAutomaticallyStart, this.automaticallyStartDelay, callback);}}复制代码

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。