## 簡介
通常我們啟動工程都是使用`SpringApplication.run(Application.class, args);`來啟動,但是JPower工程已經設置了很多自定義參數用來集成不同組件,故采用`SpringApplicationBuilder`,將其封裝進一個核心類中進行拓展,以便于所有微服務調用啟動之用。
## 自定義啟動器
* 如需要自行新增自定義參數在其核心啟動類中的新增即可。
* 啟動器核心代碼如下
~~~
/**
* @ClassName JpowerApplication
* @Description TODO 項目啟動器
* @Author Ding
* @Date 2020-08-02 17:04
* @Version 1.0
*/
@Slf4j
public class JpowerApplication {
/**
* @Author 郭丁志
* @Description //TODO 項目啟動
* @Date 18:16 2020-08-02
* @Param appName 項目模塊名稱,必須與client表的code值相同
* @return org.springframework.context.ConfigurableApplicationContext
**/
public static ConfigurableApplicationContext run(String appName, Class source, String... args) {
SpringApplicationBuilder builder = createSpringApplicationBuilder(appName, source, args);
return builder.run(args);
}
private static SpringApplicationBuilder createSpringApplicationBuilder(String appName, Class source, String[] args) {
Assert.hasText(appName, "[appName]服務名不能為空");
SpringApplicationBuilder builder = new SpringApplicationBuilder(source);
//讀取環境變量配置
ConfigurableEnvironment environment = new StandardEnvironment();
MutablePropertySources propertySources = environment.getPropertySources();
propertySources.addFirst(new SimpleCommandLinePropertySource(args));
propertySources.addLast(new MapPropertySource("systemProperties", environment.getSystemProperties()));
propertySources.addLast(new SystemEnvironmentPropertySource("systemEnvironment", environment.getSystemEnvironment()));
// 獲取配置的環境變量
String[] activeProfiles = environment.getActiveProfiles();
// 判斷環境:dev、test、prod
List<String> profiles = Arrays.asList(activeProfiles);
List<String> presetProfiles = new ArrayList(Arrays.asList("dev", "test", "prod"));
presetProfiles.retainAll(profiles);
List<String> activeProfileList = new ArrayList<>(presetProfiles);
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) + "]");
}
Properties props = System.getProperties();
props.setProperty("spring.application.name", appName);
props.setProperty("spring.profiles.active", profile);
props.setProperty("logging.config", "classpath:logback-spring.xml");
props.setProperty("jpower.is-local", String.valueOf(isLocalDev()));
props.setProperty("spring.main.allow-bean-definition-overriding", "true");
//nacos配置
props.setProperty("spring.cloud.nacos.discovery.server-addr", "${jpower.".concat(profile).concat(".nacos.server-addr:}"));
props.setProperty("spring.cloud.nacos.config.server-addr", "${jpower.".concat(profile).concat(".nacos.server-addr:}"));
props.setProperty("spring.cloud.nacos.discovery.namespace", "${jpower.".concat(profile).concat(".nacos.namespace:}"));
props.setProperty("spring.cloud.nacos.config.namespace", "${jpower.".concat(profile).concat(".nacos.namespace:}"));
//sentinel配置
props.setProperty("spring.cloud.sentinel.transport.dashboard", "${jpower.".concat(profile).concat(".sentinel.dashboard:}"));
//seata啟用,默認關閉
props.setProperty("seata.enabled", "${jpower.seata.enabled:false}");
List<DeployService> deployServiceList = new ArrayList<>();
ServiceLoader.load(DeployService.class).forEach(deployServiceList::add);
deployServiceList.stream().sorted(Comparator.comparing(DeployService::getOrder)).collect(Collectors.toList())
.forEach(deployService -> deployService.launcher(builder, appName, profile));
log.warn("{}項目已啟動,運行環境:{}",appName,profile);
return builder;
}
/**
* @Author 郭丁志
* @Description //TODO 判斷是否為本地開發環境
* @Date 18:18 2020-08-02
* @return boolean
**/
public static boolean isLocalDev() {
String osName = System.getProperty("os.name");
return StringUtils.hasText(osName) && !(AppConstant.OS_NAME_LINUX.equals(osName.toUpperCase()));
}
}
~~~
## 如何使用
* 以`jpower-system`模塊啟動為例,代碼如下
~~~
/**
* @ClassName SpringBootStartApplication
* @Description TODO 系統管理入口
* @Author Ding
* @Date 2020-02-24 18:41
* @Version 1.0
*/
@EnableTransactionManagement
@SpringBootApplication
@EnableFeignClients
public class SystemStartApplication {
public static void main(String[] args) {
JpowerApplication.run(AppConstant.JPOWER_SYSTEM,SystemStartApplication.class,args);
}
}
~~~
* 可以看到非常簡約,與原生并沒有太多變化,只是多了一個appName的參數,此參數正是做為服務名注冊到注冊中心,用于和其他服務分類。
## 擴展啟動參數
* 有時我們可能單獨一個模塊需要額外加載自己的配置,而其他模塊則無需這些配置,jpower也想到了這種情況,我們只需要在所在模塊繼承`DeployService`接口并實現`launcher`方法即可。
示例代碼如下:
~~~
/**
* @ClassName DeployService
* @Description TODO 擴展啟動參數配置
* @Author 郭丁志
* @Date 2020-08-19 16:22
* @Version 1.0
*/
public class DeployServiceImpl implements DeployService {
@Override
public void launcher(SpringApplicationBuilder builder, String appName, String profile) {
Properties props = System.getProperties();
props.setProperty("spring.cloud.nacos.config.file-extension", NacosConstants.FILE_EXTENSION);
props.setProperty("spring.cloud.nacos.config.shared-configs[0].data-id", NacosConstants.DATA_ID);
props.setProperty("spring.cloud.nacos.config.shared-configs[0].refresh", NacosConstants.CONFIG_REFRESH);
props.setProperty("spring.cloud.nacos.config.shared-configs[0].group", NacosConstants.CONFIG_GROUP);
props.setProperty("spring.cloud.nacos.config.shared-configs[1].data-id", NacosConstants.nacosPublicDataId(profile));
props.setProperty("spring.cloud.nacos.config.shared-configs[1].refresh", NacosConstants.CONFIG_REFRESH);
props.setProperty("spring.cloud.nacos.config.shared-configs[1].group", NacosConstants.CONFIG_GROUP);
}
@Override
public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE;
}
}
~~~
* 看到這里,可能大家也會有疑問,啟動參數、公共參數寫到DeployService里,這相當于是寫死了,那我如果要修改,還得全部重新打包,這豈不是很不方便?我們的理念就是一次打包,處處運行,所以這些問題都能輕松解決
* 若是直接命令行運行,我們可以通過命令行的形式這么覆蓋配置
> java -jar app.jar --spring.profiles.active=test --server.port=8080
* 若是通過docker-compose啟動容器,那么我們可以這么覆蓋配置
~~~
jpower-system:
image: "192.168.0.10:99/jpower/system-server:1.0.1-SNAPSHOT"
privileged: true
volumes:
- /docker/skywalking/agent/:/jpower/skywalking/agent/
environment:
- JAVA_TOOL_OPTIONS=-javaagent:/jpower/skywalking/agent/skywalking-agent.jar
- SW_AGENT_COLLECTOR_BACKEND_SERVICES=skywalking-oap:11800
restart: always
command:
--spring.profiles.active=${PROFILE}
--spring.cloud.nacos.discovery.ip=${ADMIN_IP}
--spring.cloud.nacos.discovery.port=${ADMIN_PORT}
--spring.cloud.sentinel.transport.port=${ADMIN_SENTINEL_PORT}
--spring.cloud.nacos.config.namespace=${NACOS_NAMESPACE}
--spring.cloud.nacos.config.group=${NACOS_GROUP}
--spring.cloud.nacos.config.server-addr=${NACOS_SERVER_ADDR}
--spring.cloud.nacos.discovery.server-addr=${NACOS_SERVER_ADDR}
--spring.cloud.sentinel.transport.dashboard=${SENTINEL_DASHBOARD_ADDR}
--sentinel.heartbeat.client.ip=${ADMIN_IP}
networks:
- jpower_net
~~~
## 注意點
* 自定義啟動器已經將環境變量也設置好,無需再到`application.yml`中配置`spring.profiles.active`再打包。
* 打包后的app啟動時,若不設置`spring.profiles.active`,則默認為`dev`,如需設置只需在啟動的命令行加上即可。
`java -jar app.jar --spring.profiles.active=prod --server.port=2333`
* 無論是打包了fat-jar,還是打包了docker,都只需要打包一次,搭配上注冊中心就可以運行在任何設定好的環境中,這樣一來就實現了`一次打包,處處運行`的理念。
* 開發中,如果要修改為非`DEV`環境,可參考如下配置。

- 序言
- 開發環境準備
- 環境要求
- 環境安裝
- 基礎環境安裝
- Nacos安裝
- Sentinel安裝
- 插件安裝
- 導入工程
- 運行工程
- 工程測試
- JPower特性
- 系統啟動器
- 多終端令牌認證
- 系統鑒權
- 鑒權API
- 鑒權配置
- API權限配置
- 接口放行配置
- 數據權限
- redis緩存
- 動態網關
- 聚合文檔
- SaaS多租戶
- 概念
- 使用
- Xss防注入
- 日志記錄
- 操作日志&錯誤日志
- SQL打印
- feign請求日志&配置
- gateway日志
- 服務日志打印
- 導入導出
- 字典查詢
- 系統文件上傳下載
- 接口監控
- 代碼生成器
- 配置文件共享
- Mybatis過濾器
- 配置說明
- 高級實戰
- nacos動態配置
- Seata分布式事務
- 簡介
- docker啟動
- 微服務配置
- 微服務遠程調用
- 聲明式服務調用 Feign
- 熔斷機制 Sentinel
- sentinel流控
- 簡介
- 微服務配置
- 配置nacos對接
- APM監控&鏈路追蹤
- 簡介
- 安裝
- 微服務接入
- SpringBootAdmin監控
- ELK分布式日志追蹤系統
- ELK簡介
- ELK一鍵部署
- 微服務日志對接ELK
- JPower-Chat
- 配置說明
- 生產部署
- docker部署
- docker安裝
- docker-compose安裝
- harbor安裝
- 部署步驟
- 版本升級
- 1.0.1升級到2.0.0
- 2.0.0升級到2.0.2
- 2.0.2升級2.1.0
- 2.1.0升級到2.1.1
- 2.1.1升級到2.1.2
- 2.1.2升級到2.1.4