spring-boot
有一个根据 JVM
变量 -Dspring.profiles.active
来设置运行时的active profile的功能,但是有些时候我们也许会不小心忘记设置这个变量,这样在生产环境中会带来一定的困扰,所以我想了一个办法,来给忘记设置 -Dspring.profiles.active
的程序员一次“secend chance”。
先来讲一下思路:
-Dspring.profiles.active
,如果已经设置,直接跳转 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-wor server: port: 8001 eureka: instance: hostname: localhost client: registerWithEureka: false fetchRegistry: false serviceUrl: defaultZone: http://${eureka.instance.hostname}:${server.port} --- spring: profiles: production application: name: comchangyoueurekaserver server: port: 8001 eureka: instance: hostname: localhost client: registerWithEureka: false fetchRegistry: false serviceUrl: 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 = 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环境(一般为开发环境)则automaticallyChooseThreshold秒后自动选择d System.out.printf("/nSystem will automatically select 'd' in %d seconds./n", automaticallyStartDelay); final int[] count = {automaticallyStartDelay}; timer.scheduleAtFixedRate(new TimerTask() { @Override public void run() { if (count[0]-- == 0) { System.setProperty("spring.profiles.active", System.getProperty("os.name").lastIndexOf("Linux") == -1 ? "development" : "production"); timer.cancel(); callback.bootRun(); } } }, 0, 1000); } Pattern pattern = Pattern.compile("^p|d$"); Scanner scanner = new Scanner(System.in); //如果是Linux系统(一般为生产环境)则强制等待用户输入(一般是忘记设置spring.profiles.active了,这等于给了设置active profile的"second chance") while (scanner.hasNextLine()) { 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"); break; } } } //如果已经通过参数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):