xiejun
2024-11-01 80b6cbfc9c861469146318d0b3dd5f8b8b525b8a
Source/BladeX-Tool/blade-core-launch/src/main/java/org/springblade/core/launch/BladeApplication.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,130 @@
/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill åº„骞 (smallchill@163.com)
 */
package org.springblade.core.launch;
import org.springblade.core.launch.constant.AppConstant;
import org.springblade.core.launch.constant.NacosConstant;
import org.springblade.core.launch.service.LauncherService;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.*;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
 * é¡¹ç›®å¯åŠ¨å™¨ï¼Œæžå®šçŽ¯å¢ƒå˜é‡é—®é¢˜
 *
 * @author Chill
 */
public class BladeApplication {
   /**
    * Create an application context
    * java -jar app.jar --spring.profiles.active=prod --server.port=2333
    *
    * @param appName application name
    * @param source  The sources
    * @return an application context created from the current state
    */
   public static ConfigurableApplicationContext run(String appName, Class source, String... args) {
      SpringApplicationBuilder builder = createSpringApplicationBuilder(appName, source, args);
      return builder.run(args);
   }
   public static SpringApplicationBuilder createSpringApplicationBuilder(String appName, Class source, String... args) {
      Assert.hasText(appName, "[appName]服务名不能为空");
      // è¯»å–环境变量,使用spring boot的规则
      ConfigurableEnvironment environment = new StandardEnvironment();
      MutablePropertySources propertySources = environment.getPropertySources();
      propertySources.addFirst(new SimpleCommandLinePropertySource(args));
      propertySources.addLast(new MapPropertySource(StandardEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, environment.getSystemProperties()));
      propertySources.addLast(new SystemEnvironmentPropertySource(StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, environment.getSystemEnvironment()));
      // èŽ·å–é…ç½®çš„çŽ¯å¢ƒå˜é‡
      String[] activeProfiles = environment.getActiveProfiles();
      // åˆ¤æ–­çŽ¯å¢ƒ:dev、test、prod
      List<String> profiles = Arrays.asList(activeProfiles);
      // é¢„设的环境
      List<String> presetProfiles = new ArrayList<>(Arrays.asList(AppConstant.DEV_CODE, AppConstant.TEST_CODE, AppConstant.PROD_CODE));
      // äº¤é›†
      presetProfiles.retainAll(profiles);
      // å½“前使用
      List<String> activeProfileList = new ArrayList<>(profiles);
      Function<Object[], String> joinFun = StringUtils::arrayToCommaDelimitedString;
      SpringApplicationBuilder builder = new SpringApplicationBuilder(source);
      String profile;
      if (activeProfileList.isEmpty()) {
         // é»˜è®¤dev开发
         profile = AppConstant.DEV_CODE;
         activeProfileList.add(profile);
         builder.profiles(profile);
      } else if (activeProfileList.size() == 1) {
         profile = activeProfileList.get(0);
      } else {
         // åŒæ—¶å­˜åœ¨dev、test、prod环境时
         throw new RuntimeException("同时存在环境变量:[" + StringUtils.arrayToCommaDelimitedString(activeProfiles) + "]");
      }
      String startJarPath = BladeApplication.class.getResource("/").getPath().split("!")[0];
      String activePros = joinFun.apply(activeProfileList.toArray());
      System.out.printf("----启动中,读取到的环境变量:[%s],jar地址:[%s]----%n", activePros, startJarPath);
      Properties props = System.getProperties();
      props.setProperty("spring.application.name", appName);
      props.setProperty("spring.profiles.active", profile);
      props.setProperty("info.version", AppConstant.APPLICATION_VERSION);
      props.setProperty("info.desc", appName);
      props.setProperty("file.encoding", StandardCharsets.UTF_8.name());
      props.setProperty("blade.env", profile);
      props.setProperty("blade.name", appName);
      props.setProperty("blade.is-local", String.valueOf(isLocalDev()));
      props.setProperty("blade.dev-mode", profile.equals(AppConstant.PROD_CODE) ? "false" : "true");
      props.setProperty("blade.service.version", AppConstant.APPLICATION_VERSION);
      props.setProperty("loadbalancer.client.name", appName);
      Properties defaultProperties = new Properties();
      defaultProperties.setProperty("spring.main.allow-bean-definition-overriding", "true");
      defaultProperties.setProperty("spring.sleuth.sampler.percentage", "1.0");
      defaultProperties.setProperty("spring.cloud.alibaba.seata.tx-service-group", appName.concat(NacosConstant.NACOS_GROUP_SUFFIX));
      defaultProperties.setProperty("spring.cloud.nacos.config.file-extension", NacosConstant.NACOS_CONFIG_FORMAT);
      defaultProperties.setProperty("spring.cloud.nacos.config.shared-configs[0].data-id", NacosConstant.sharedDataId());
      defaultProperties.setProperty("spring.cloud.nacos.config.shared-configs[0].group", NacosConstant.NACOS_CONFIG_GROUP);
      defaultProperties.setProperty("spring.cloud.nacos.config.shared-configs[0].refresh", NacosConstant.NACOS_CONFIG_REFRESH);
      defaultProperties.setProperty("spring.cloud.nacos.config.shared-configs[1].data-id", NacosConstant.sharedDataId(profile));
      defaultProperties.setProperty("spring.cloud.nacos.config.shared-configs[1].group", NacosConstant.NACOS_CONFIG_GROUP);
      defaultProperties.setProperty("spring.cloud.nacos.config.shared-configs[1].refresh", NacosConstant.NACOS_CONFIG_REFRESH);
      builder.properties(defaultProperties);
      // åŠ è½½è‡ªå®šä¹‰ç»„ä»¶
      List<LauncherService> launcherList = new ArrayList<>();
      ServiceLoader.load(LauncherService.class).forEach(launcherList::add);
      launcherList.stream().sorted(Comparator.comparing(LauncherService::getOrder)).collect(Collectors.toList())
         .forEach(launcherService -> launcherService.launcher(builder, appName, profile, isLocalDev()));
      return builder;
   }
   /**
    * åˆ¤æ–­æ˜¯å¦ä¸ºæœ¬åœ°å¼€å‘环境
    *
    * @return boolean
    */
   public static boolean isLocalDev() {
      String osName = System.getProperty("os.name");
      return StringUtils.hasText(osName) && !(AppConstant.OS_NAME_LINUX.equalsIgnoreCase(osName));
   }
}