123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325 |
- package cn.com.qmth.examcloud.web.bootstrap;
- import java.util.Map;
- import java.util.Map.Entry;
- import java.util.Properties;
- import java.util.Set;
- import org.apache.commons.io.IOUtils;
- import org.apache.commons.lang3.StringUtils;
- import org.apache.logging.log4j.ThreadContext;
- import org.springframework.boot.SpringApplication;
- import org.springframework.context.ConfigurableApplicationContext;
- import org.springframework.http.HttpStatus;
- import com.google.common.collect.Maps;
- import com.google.common.collect.Sets;
- import cn.com.qmth.examcloud.commons.exception.ExamCloudRuntimeException;
- import cn.com.qmth.examcloud.commons.logging.ExamCloudLog;
- import cn.com.qmth.examcloud.commons.logging.ExamCloudLogFactory;
- import cn.com.qmth.examcloud.commons.util.HttpMethod;
- import cn.com.qmth.examcloud.commons.util.JsonUtil;
- import cn.com.qmth.examcloud.commons.util.OKHttpUtil;
- import cn.com.qmth.examcloud.commons.util.PropertiesUtil;
- import cn.com.qmth.examcloud.commons.util.StringUtil;
- import cn.com.qmth.examcloud.commons.util.Util;
- import cn.com.qmth.examcloud.web.cloud.AppSelf;
- import cn.com.qmth.examcloud.web.cloud.AppSelfHolder;
- import okhttp3.Response;
- /**
- * 系统启动器
- *
- * @author WANGWEI
- * @date 2019年3月25日
- * @Copyright (c) 2018-? http://qmth.com.cn All Rights Reserved.
- */
- public class AppBootstrap {
- private static ExamCloudLog log = ExamCloudLogFactory.getLog(AppBootstrap.class);
- private static Map<String, String> properties;
- private static String active;
- private static String startupCode;
- private static Long appId;
- private static String secretKey;
- private static String appCode;
- private static String appSimpleName;
- private static String configCenterHost;
- private static String configCenterPort;
- /**
- * 启动方法
- *
- * @author WANGWEI
- * @param primarySource
- * @param args
- * @return
- */
- public static synchronized ConfigurableApplicationContext run(Class<?> primarySource,
- String... args) {
- ThreadContext.put("TRACE_ID", Thread.currentThread().getName());
- log.info("Starting...");
- checkBootstrapParams(args);
- sendStartupRequest2ConfigCenter();
- if (null != args) {
- for (String arg : args) {
- arg = arg.trim();
- if (arg.startsWith("--")) {
- String key = arg.substring(2, arg.indexOf("=")).trim();
- String value = arg.substring(arg.indexOf("=") + 1).trim();
- properties.put(key, value);
- }
- }
- }
- // 网卡选择
- String preferredNetworks = properties.get("examcloud.inet.preferredNetworks");
- if (StringUtils.isNotBlank(preferredNetworks)) {
- System.setProperty("spring.cloud.inetutils.preferred-networks", preferredNetworks);
- properties.put("spring.cloud.inetutils.preferred-networks", preferredNetworks);
- }
- properties.put("spring.profiles.active", active);
- Set<String> argSet = Sets.newLinkedHashSet();
- for (Entry<String, String> p : properties.entrySet()) {
- String key = p.getKey();
- String value = p.getValue();
- if (StringUtils.isBlank(key) || StringUtils.isBlank(value)) {
- continue;
- }
- key = key.trim();
- value = value.trim();
- PropertyHolder.setProperty(p.getKey(), p.getValue());
- String arg = "--" + key + "=" + value;
- argSet.add(arg);
- }
- AppSelfHolder.set(buildAppSelf());
- String[] newArgs = argSet.toArray(new String[argSet.size()]);
- ConfigurableApplicationContext context = null;
- try {
- context = SpringApplication.run(primarySource, newArgs);
- noticeConfigCenter("success");
- } catch (Exception e) {
- String stackTrace = Util.getStackTrace(e);
- noticeConfigCenter("failure:\n" + stackTrace);
- log.error("fail to run spring app.", e);
- System.exit(-1);
- }
- return context;
- }
- /**
- * 创建 {@link AppSelf} 实例
- *
- * @author WANGWEI
- * @return
- */
- private static AppSelf buildAppSelf() {
- return new AppSelf() {
- @Override
- public Long getAppId() {
- return appId;
- }
- @Override
- public String getAppCode() {
- return appCode;
- }
- @Override
- public String getSecretKey() {
- return secretKey;
- }
- };
- }
- /**
- * 通知配置中心
- *
- * @author WANGWEI
- * @param message
- */
- private static void noticeConfigCenter(String message) {
- String url = "http://" + configCenterHost + ":" + configCenterPort + "/configCenter/notice";
- Map<String, String> req = Maps.newHashMap();
- req.put("active", active);
- req.put("appSimpleName", appSimpleName);
- req.put("startupCode", startupCode);
- req.put("message", message);
- Response resp = null;
- try {
- Map<String, String> headers = Maps.newHashMap();
- headers.put("Trace-Id", startupCode);
- resp = OKHttpUtil.call(HttpMethod.POST, url.toString(), headers, req);
- } catch (Exception e) {
- log.error("fail to notice config center.", e);
- System.exit(-1);
- } finally {
- IOUtils.closeQuietly(resp);
- }
- }
- /**
- * 向配置中心发送启动请求
- *
- * @author WANGWEI
- */
- private static void sendStartupRequest2ConfigCenter() {
- StringBuilder url = new StringBuilder(
- "http://" + configCenterHost + ":" + configCenterPort + "/configCenter/startup");
- Map<String, String> req = Maps.newHashMap();
- req.put("active", active);
- req.put("appSimpleName", appSimpleName);
- req.put("startupCode", startupCode);
- Response resp = null;
- try {
- Map<String, String> headers = Maps.newHashMap();
- headers.put("Trace-Id", startupCode);
- resp = OKHttpUtil.call(HttpMethod.POST, url.toString(), headers, req);
- if (resp.code() != HttpStatus.OK.value()) {
- throw new ExamCloudRuntimeException("fail to get configuration");
- }
- String body = resp.body().string();
- String encryptedAppId = resp.header("App-Id");
- String encryptedAppCode = resp.header("App-Code");
- String encryptedSecretKey = resp.header("Secret-Key");
- appId = StringUtil.toLong(BootstrapSecurityUtil.decrypt(encryptedAppId, startupCode));
- appCode = BootstrapSecurityUtil.decrypt(encryptedAppCode, startupCode);
- secretKey = BootstrapSecurityUtil.decrypt(encryptedSecretKey, startupCode);
- String decryptedBody = BootstrapSecurityUtil.decrypt(body, startupCode);
- @SuppressWarnings("unchecked")
- Map<String, String> map = JsonUtil.fromJson(decryptedBody, Map.class);
- properties = map;
- } catch (Exception e) {
- log.error("fail to send startup request to config center.", e);
- System.exit(-1);
- } finally {
- IOUtils.closeQuietly(resp);
- }
- }
- /**
- * 检查启动参数
- *
- * @author WANGWEI
- * @param args
- * @return
- */
- private static void checkBootstrapParams(String... args) {
- Properties props = new Properties();
- PropertiesUtil.loadFromResource("application.properties", props);
- if (null != args) {
- for (String s : args) {
- s = s.trim();
- if (s.startsWith("--spring.profiles.active=")) {
- active = s.substring(s.indexOf("=") + 1);
- } else if (s.startsWith("--examcloud.startup.startupCode=")) {
- startupCode = s.substring(s.indexOf("=") + 1);
- } else if (s.startsWith("--examcloud.startup.configCenterHost=")) {
- configCenterHost = s.substring(s.indexOf("=") + 1);
- } else if (s.startsWith("--examcloud.startup.configCenterPort=")) {
- configCenterPort = s.substring(s.indexOf("=") + 1);
- } else if (s.startsWith("--examcloud.startup.appSimpleName=")) {
- appSimpleName = s.substring(s.indexOf("=") + 1);
- }
- }
- }
- // active
- if (null == active) {
- String value = props.getProperty("spring.profiles.active");
- if (StringUtils.isNotBlank(value)) {
- active = value.trim();
- }
- }
- log.info("active=" + active);
- if (StringUtils.isBlank(active)) {
- log.error("property[spring.profiles.active] is not specified");
- System.exit(-1);
- }
- // startupCode
- if (null == startupCode) {
- String value = props.getProperty("examcloud.startup.startupCode");
- if (StringUtils.isNotBlank(value)) {
- startupCode = value.trim();
- }
- }
- log.info("startupCode=" + startupCode);
- if (StringUtils.isBlank(startupCode)) {
- log.error("property[examcloud.startup.startupCode] is not specified");
- System.exit(-1);
- }
- // appSimpleName
- if (null == appSimpleName) {
- String value = props.getProperty("examcloud.startup.appSimpleName");
- if (StringUtils.isNotBlank(value)) {
- appSimpleName = value.trim();
- }
- }
- log.info("appSimpleName=" + appSimpleName);
- if (StringUtils.isBlank(appSimpleName)) {
- log.error("property[examcloud.startup.appSimpleName] is not specified");
- System.exit(-1);
- }
- // configCenterHost
- if (null == configCenterHost) {
- String value = props.getProperty("examcloud.startup.configCenterHost");
- if (StringUtils.isNotBlank(value)) {
- configCenterHost = value.trim();
- }
- }
- log.info("configCenterHost=" + configCenterHost);
- if (StringUtils.isBlank(configCenterHost)) {
- log.error("property[examcloud.startup.configCenterHost] is not specified");
- System.exit(-1);
- }
- // configCenterPort
- if (null == configCenterPort) {
- String value = props.getProperty("examcloud.startup.configCenterPort");
- if (StringUtils.isNotBlank(value)) {
- configCenterPort = value.trim();
- }
- }
- log.info("configCenterPort=" + configCenterPort);
- if (null == configCenterPort) {
- log.error("property[examcloud.startup.configCenterPort] is not specified");
- System.exit(-1);
- }
- }
- }
|