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

先来讲一下思路:

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

代码如下:

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

spring:application:name: comchangyoueurekaserver #注意命名要符合RFC 2396,否则会影响服务发现 详见https://stackoverflow.com/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 org.apache.commons.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 = Pattern.compile("^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.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
import org.springframework.context.ApplicationContext;@EnableEurekaServer
@SpringBootApplication
public 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法在手,天下我有。


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

import org.apache.commons.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 = Pattern.compile("^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);}
}复制代码

2017-01-25更新:

补上了 try-with-resource

import org.apache.commons.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 = Pattern.compile("^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);}
}复制代码

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

  1. 开源oa_圈子哥推荐一款基于 Spring Boot 开发 OA 开源产品,学习/搞外快都是不二选择!...

    点击上方蓝字关注「程序员的技术圈子」 今天圈子哥给大家推荐一套Spring Boot 开发 OA系统,系统功能齐全,不管是用来学习或者搞外快都是不错的选择,clone下来吧! 办公自动化(OA)是面向 ...

  2. Spring Boot –使用执行器端点在运行时配置日志级别

    从Spring Boot 1.5开始,新的loggers器执行器端点允许在运行时查看和更改应用程序记录级别. 将spring-boot-actuator添加到您的项目 <dependency&g ...

  3. 毕业设计-基于spring boot的智慧物业管理系统

    项目描述 这是一个基于spring boot的智慧物业项目,我们的项目实现了用户登录.投诉.保修功能,以及后台物业管理功能.用户可以通过登录界面登录系统,提交投诉或保修请求.管理员可以在后台管理界面查 ...

  4. 基于Spring Boot 2.0的IoT应用集成和使用CSE实践

    本文通过一个IoT的应用展现在Spring Boot 2.0中集成和使用CSE.IoT应用原来使用Spring Boot 2.0开发,通过少量的步骤集成CSE,然后展现了集成后带来了哪些新特性,以及中 ...

  5. Micronaut for Spring支持Spring Boot应用以Micronaut形式运行

    在Micronaut 1.0.1小版本发布的同时,Object Computing, Inc.(OCI)还发布了Micronaut for Spring 1.0 M1.在发布说明中这样写到: Micr ...

  6. 基于Spring Boot+Cloud构建微云架构

    链接:my.oschina.net/u/3636867/blog/1802517 前言 首先,最想说的是,当你要学习一套最新的技术时,官网的英文文档是学习的最佳渠道.因为网上流传的多数资料是官网翻译而 ...

  7. 基于Spring Boot和Spring Cloud实现微服务架构学习--转

    原文地址:http://blog.csdn.net/enweitech/article/details/52582918 看了几周spring相关框架的书籍和官方demo,是时候开始总结下这中间的学习 ...

  8. 基于 Spring Boot 和 Spring Cloud 实现微服务架构

    前言 首先,最想说的是,当你要学习一套最新的技术时,官网的英文文档是学习的最佳渠道.因为网上流传的多数资料是官网翻译而来,很多描述的重点也都偏向于作者自身碰到的问题,这样就很容易让你理解和操作出现偏差 ...

  9. c# 基于layui的通用后台管理系统_基于spring boot和vuejs的通用后台管理系统脚手架 guns-lite...

    Guns-lite 前言 guns-lite是在guns的基础上将数据库层由mybatis替换为spring data jpa的系统. guns-lite是一个基于spring boot的后台管理系统 ...

最新文章

  1. 局域网无法上网解决处理方法
  2. android多线程的本质,[原创]分析unidbg(unidbgMutil)多线程机制
  3. linux 上删除docker 虚悬镜像
  4. 2021-11-14泛型
  5. 关于数据准备时,自动棌番的主键,这一字段数据的注意(IT总结之五)
  6. Dapper Sqlpara where in
  7. 李宏毅机器学习——半监督学习
  8. Leetcode10. Regular Expression Matching
  9. 深度图像配准_巧解图像处理经典难题之图像配准
  10. 一信通短信接口对接_实例分享:验证码短信接口如何对接?接口api哪个好用?...
  11. AE2017 安-装-破-解
  12. 华为手机老是自动截屏_华为手机竟然三种截屏方法 然后打开智能截屏开关
  13. 如何在直播、会议、视频中使用虚拟形象
  14. arm linux 掉电检测,如何实现单片机掉电检测与数据掉电保存?-嵌入式系统-与非网...
  15. usb计算机采集卡,关于usb视频采集卡 hdmi设置你可能不知道
  16. 黑客攻防日记---刘欣
  17. 机器学习-数据科学库 13 政治献金数据案例
  18. JWT 详解及源码分析
  19. 表示颜色的英语单词(图)
  20. 10---字符个数统计

热门文章

  1. java 字符串为空_java判断字符串为空,方法详解
  2. 22_python基础—异常
  3. Linux(二):VMware虚拟机中Ubuntu安装详细过程
  4. PHP条件语句总结,php条件语句的总结
  5. python 字典由值找键_python字典怎么根据值返回键
  6. python源程序文件的扩展名_python程序文件扩展名知识点详解
  7. java 与 .net socket_java.net.ServerSocket和java.net.Socket
  8. 台风路径超级计算机,厄尔尼诺又要来了?2号台风或要生成,超级计算机:路径争议大...
  9. 可以方便的将SQL语句的执行结果显示成表格结果的JAVA类,可以用于不同的数据显示
  10. 客户端产生CLOSE_WAIT状态的解决方案