Ver código fonte

废弃 AppBootstrap & PropertiesUtil

deason 4 anos atrás
pai
commit
766a3089e0

+ 245 - 245
examcloud-commons/src/main/java/cn/com/qmth/examcloud/commons/util/PropertiesUtil.java

@@ -1,245 +1,245 @@
-package cn.com.qmth.examcloud.commons.util;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.util.Map.Entry;
-import java.util.Properties;
-import java.util.Set;
-
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.lang.StringUtils;
-
-import com.google.common.collect.Sets;
-
-import cn.com.qmth.examcloud.commons.exception.ExamCloudRuntimeException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * 类注释
- *
- * @author WANGWEI
- * @date 2018年10月8日
- * @Copyright (c) 2018-2020 http://www.qmth.com.cn/ All Rights Reserved.
- */
-public class PropertiesUtil {
-
-	private static final Logger LOG = LoggerFactory.getLogger(PropertiesUtil.class);
-
-	private static final Properties PROPS = new Properties();
-
-	private static final Set<String> PROP_FILES = Sets.newConcurrentHashSet();
-
-	/**
-	 * 构造函数
-	 *
-	 */
-	private PropertiesUtil() {
-	}
-
-	/**
-	 * 设置属性
-	 *
-	 * @author WANGWEI
-	 * @param key
-	 * @param value
-	 */
-	public static void setProperty(String key, String value) {
-		PROPS.setProperty(key, value);
-	}
-
-	/**
-	 * 加载配置文件
-	 *
-	 * @author WANGWEI
-	 * @param resourceName
-	 */
-	public static void loadFromResource(String resourceName) {
-		loadFromPath(PathUtil.getResoucePath(resourceName));
-	}
-
-	/**
-	 * 加载配置文件
-	 *
-	 * @author WANGWEI
-	 * @param path
-	 */
-	public static synchronized void loadFromPath(String path) {
-		if (StringUtils.isBlank(path)) {
-			return;
-		}
-		try {
-			File file = new File(path);
-
-			if (PROP_FILES.contains(file.getCanonicalPath())) {
-				return;
-			}
-
-			loadFromFile(file, PROPS);
-
-			PROP_FILES.add(file.getCanonicalPath());
-		} catch (Exception e) {
-			LOG.error("Fail to load and watch file [" + path + "].", e);
-		}
-	}
-
-	/**
-	 * @param resourceName
-	 * @param props
-	 */
-	public static void loadFromResource(String resourceName, Properties props) {
-		if (null != PropertiesUtil.class.getClassLoader()) {
-			InputStream in = PropertiesUtil.class.getClassLoader()
-					.getResourceAsStream(resourceName);
-
-			loadFromStream(in, props);
-		} else {
-			throw new ExamCloudRuntimeException("fail to get class loader");
-		}
-	}
-
-	/**
-	 * @param file
-	 * @param props
-	 * @throws IOException
-	 */
-	public static void loadFromFile(File file, Properties props) {
-		if (null == file) {
-			LOG.error("file is null.");
-			return;
-		}
-		if (!file.isFile()) {
-			LOG.error("file is not a normal file.");
-			return;
-		}
-
-		String path = PathUtil.getCanonicalPath(file);
-		LOG.info("Loading properties from file [" + path + "]");
-
-		try {
-			loadFromStream(new FileInputStream(file), props);
-		} catch (Exception e) {
-			throw new ExamCloudRuntimeException(e);
-		}
-	}
-
-	/**
-	 * @param is
-	 * @param props
-	 */
-	public static void loadFromStream(InputStream is, Properties props) {
-		BufferedReader reader = null;
-		try {
-			reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
-			Properties temp = new Properties();
-			temp.load(reader);
-			for (Entry<Object, Object> entry : temp.entrySet()) {
-				Object key = entry.getKey();
-				Object value = entry.getValue();
-				if (key instanceof String) {
-					key = ((String) key).trim();
-				}
-				if (value instanceof String) {
-					value = ((String) value).trim();
-				}
-				props.put(key, value);
-			}
-
-		} catch (IOException e) {
-			throw new ExamCloudRuntimeException(e);
-		} finally {
-			IOUtils.closeQuietly(reader);
-			IOUtils.closeQuietly(is);
-		}
-	}
-
-	/**
-	 * @param key
-	 * @return
-	 */
-	public static String getString(String key) {
-		String value = PROPS.getProperty(key);
-		if (StringUtils.isNotBlank(value)) {
-			return value.trim();
-		} else {
-			if (LOG.isDebugEnabled()) {
-				LOG.debug("No property value, key = " + key);
-			}
-			return null;
-		}
-	}
-
-	/**
-	 * @param key
-	 * @param defaultValue
-	 * @return
-	 */
-	public static String getString(String key, String defaultValue) {
-		String value = getString(key);
-		if (null != value) {
-			return value;
-		}
-		return defaultValue;
-	}
-
-	/**
-	 * @param key
-	 * @param defaultValue
-	 * @return
-	 */
-	public static int getInt(String key, int defaultValue) {
-		String value = getString(key);
-		if (null != value) {
-			try {
-				return Integer.parseInt(value);
-			} catch (NumberFormatException e) {
-				PROPS.setProperty(key, String.valueOf(defaultValue));
-				return defaultValue;
-			}
-		}
-		return defaultValue;
-	}
-
-	/**
-	 * @param key
-	 * @param defaultValue
-	 * @return
-	 */
-	public static long getLong(String key, long defaultValue) {
-		String value = getString(key);
-		if (null != value) {
-			try {
-				return Long.parseLong(value);
-			} catch (NumberFormatException e) {
-				return defaultValue;
-			}
-		}
-		return defaultValue;
-	}
-
-	/**
-	 * 获取boolean
-	 *
-	 * @author WANGWEI
-	 * @param key
-	 * @param defaultVale
-	 * @return
-	 */
-	public static boolean getBoolean(String key, boolean defaultVale) {
-		String value = getString(key);
-		if (null == value) {
-			return defaultVale;
-		}
-		if (value.equals("true")) {
-			return true;
-		} else if (value.equals("false")) {
-			return false;
-		} else {
-			return defaultVale;
-		}
-	}
-}
+// package cn.com.qmth.examcloud.commons.util;
+//
+// import java.io.BufferedReader;
+// import java.io.File;
+// import java.io.FileInputStream;
+// import java.io.IOException;
+// import java.io.InputStream;
+// import java.io.InputStreamReader;
+// import java.util.Map.Entry;
+// import java.util.Properties;
+// import java.util.Set;
+//
+// import org.apache.commons.io.IOUtils;
+// import org.apache.commons.lang.StringUtils;
+//
+// import com.google.common.collect.Sets;
+//
+// import cn.com.qmth.examcloud.commons.exception.ExamCloudRuntimeException;
+// import org.slf4j.Logger;
+// import org.slf4j.LoggerFactory;
+//
+// /**
+//  * 类注释
+//  *
+//  * @author WANGWEI
+//  * @date 2018年10月8日
+//  * @Copyright (c) 2018-2020 http://www.qmth.com.cn/ All Rights Reserved.
+//  */
+// public class PropertiesUtil {
+//
+// 	private static final Logger LOG = LoggerFactory.getLogger(PropertiesUtil.class);
+//
+// 	private static final Properties PROPS = new Properties();
+//
+// 	private static final Set<String> PROP_FILES = Sets.newConcurrentHashSet();
+//
+// 	/**
+// 	 * 构造函数
+// 	 *
+// 	 */
+// 	private PropertiesUtil() {
+// 	}
+//
+// 	/**
+// 	 * 设置属性
+// 	 *
+// 	 * @author WANGWEI
+// 	 * @param key
+// 	 * @param value
+// 	 */
+// 	public static void setProperty(String key, String value) {
+// 		PROPS.setProperty(key, value);
+// 	}
+//
+// 	/**
+// 	 * 加载配置文件
+// 	 *
+// 	 * @author WANGWEI
+// 	 * @param resourceName
+// 	 */
+// 	public static void loadFromResource(String resourceName) {
+// 		loadFromPath(PathUtil.getResoucePath(resourceName));
+// 	}
+//
+// 	/**
+// 	 * 加载配置文件
+// 	 *
+// 	 * @author WANGWEI
+// 	 * @param path
+// 	 */
+// 	public static synchronized void loadFromPath(String path) {
+// 		if (StringUtils.isBlank(path)) {
+// 			return;
+// 		}
+// 		try {
+// 			File file = new File(path);
+//
+// 			if (PROP_FILES.contains(file.getCanonicalPath())) {
+// 				return;
+// 			}
+//
+// 			loadFromFile(file, PROPS);
+//
+// 			PROP_FILES.add(file.getCanonicalPath());
+// 		} catch (Exception e) {
+// 			LOG.error("Fail to load and watch file [" + path + "].", e);
+// 		}
+// 	}
+//
+// 	/**
+// 	 * @param resourceName
+// 	 * @param props
+// 	 */
+// 	public static void loadFromResource(String resourceName, Properties props) {
+// 		if (null != PropertiesUtil.class.getClassLoader()) {
+// 			InputStream in = PropertiesUtil.class.getClassLoader()
+// 					.getResourceAsStream(resourceName);
+//
+// 			loadFromStream(in, props);
+// 		} else {
+// 			throw new ExamCloudRuntimeException("fail to get class loader");
+// 		}
+// 	}
+//
+// 	/**
+// 	 * @param file
+// 	 * @param props
+// 	 * @throws IOException
+// 	 */
+// 	public static void loadFromFile(File file, Properties props) {
+// 		if (null == file) {
+// 			LOG.error("file is null.");
+// 			return;
+// 		}
+// 		if (!file.isFile()) {
+// 			LOG.error("file is not a normal file.");
+// 			return;
+// 		}
+//
+// 		String path = PathUtil.getCanonicalPath(file);
+// 		LOG.info("Loading properties from file [" + path + "]");
+//
+// 		try {
+// 			loadFromStream(new FileInputStream(file), props);
+// 		} catch (Exception e) {
+// 			throw new ExamCloudRuntimeException(e);
+// 		}
+// 	}
+//
+// 	/**
+// 	 * @param is
+// 	 * @param props
+// 	 */
+// 	public static void loadFromStream(InputStream is, Properties props) {
+// 		BufferedReader reader = null;
+// 		try {
+// 			reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
+// 			Properties temp = new Properties();
+// 			temp.load(reader);
+// 			for (Entry<Object, Object> entry : temp.entrySet()) {
+// 				Object key = entry.getKey();
+// 				Object value = entry.getValue();
+// 				if (key instanceof String) {
+// 					key = ((String) key).trim();
+// 				}
+// 				if (value instanceof String) {
+// 					value = ((String) value).trim();
+// 				}
+// 				props.put(key, value);
+// 			}
+//
+// 		} catch (IOException e) {
+// 			throw new ExamCloudRuntimeException(e);
+// 		} finally {
+// 			IOUtils.closeQuietly(reader);
+// 			IOUtils.closeQuietly(is);
+// 		}
+// 	}
+//
+// 	/**
+// 	 * @param key
+// 	 * @return
+// 	 */
+// 	public static String getString(String key) {
+// 		String value = PROPS.getProperty(key);
+// 		if (StringUtils.isNotBlank(value)) {
+// 			return value.trim();
+// 		} else {
+// 			if (LOG.isDebugEnabled()) {
+// 				LOG.debug("No property value, key = " + key);
+// 			}
+// 			return null;
+// 		}
+// 	}
+//
+// 	/**
+// 	 * @param key
+// 	 * @param defaultValue
+// 	 * @return
+// 	 */
+// 	public static String getString(String key, String defaultValue) {
+// 		String value = getString(key);
+// 		if (null != value) {
+// 			return value;
+// 		}
+// 		return defaultValue;
+// 	}
+//
+// 	/**
+// 	 * @param key
+// 	 * @param defaultValue
+// 	 * @return
+// 	 */
+// 	public static int getInt(String key, int defaultValue) {
+// 		String value = getString(key);
+// 		if (null != value) {
+// 			try {
+// 				return Integer.parseInt(value);
+// 			} catch (NumberFormatException e) {
+// 				PROPS.setProperty(key, String.valueOf(defaultValue));
+// 				return defaultValue;
+// 			}
+// 		}
+// 		return defaultValue;
+// 	}
+//
+// 	/**
+// 	 * @param key
+// 	 * @param defaultValue
+// 	 * @return
+// 	 */
+// 	public static long getLong(String key, long defaultValue) {
+// 		String value = getString(key);
+// 		if (null != value) {
+// 			try {
+// 				return Long.parseLong(value);
+// 			} catch (NumberFormatException e) {
+// 				return defaultValue;
+// 			}
+// 		}
+// 		return defaultValue;
+// 	}
+//
+// 	/**
+// 	 * 获取boolean
+// 	 *
+// 	 * @author WANGWEI
+// 	 * @param key
+// 	 * @param defaultVale
+// 	 * @return
+// 	 */
+// 	public static boolean getBoolean(String key, boolean defaultVale) {
+// 		String value = getString(key);
+// 		if (null == value) {
+// 			return defaultVale;
+// 		}
+// 		if (value.equals("true")) {
+// 			return true;
+// 		} else if (value.equals("false")) {
+// 			return false;
+// 		} else {
+// 			return defaultVale;
+// 		}
+// 	}
+// }

+ 312 - 312
examcloud-web/src/main/java/cn/com/qmth/examcloud/web/bootstrap/AppBootstrap.java

@@ -1,312 +1,312 @@
-package cn.com.qmth.examcloud.web.bootstrap;
-
-import cn.com.qmth.examcloud.commons.exception.ExamCloudRuntimeException;
-import cn.com.qmth.examcloud.commons.util.*;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
-import okhttp3.Response;
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.logging.log4j.ThreadContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.boot.SpringApplication;
-import org.springframework.context.ConfigurableApplicationContext;
-import org.springframework.http.HttpStatus;
-
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Properties;
-import java.util.Set;
-
-/**
- * 系统启动器
- *
- * @author WANGWEI
- * @date 2019年3月25日
- * @Copyright (c) 2018-? http://qmth.com.cn All Rights Reserved.
- */
-public class AppBootstrap {
-
-    private static final Logger LOG = LoggerFactory.getLogger(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 configCenterHost;
-
-    private static String configCenterPort;
-
-    /**
-     * 启动方法
-     *
-     * @param primarySource
-     * @param args
-     * @return
-     * @author WANGWEI
-     */
-    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);
-        // properties.put("spring.application.name", properties.get("spring.application.name") + "-temp");
-
-        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(key, value);
-            PropertiesUtil.setProperty(key, value);
-            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;
-    }
-
-    /**
-     * @return
-     * @author WANGWEI
-     */
-    /*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;
-            }
-        };
-    }*/
-
-    /**
-     * 通知配置中心
-     *
-     * @param message
-     * @author WANGWEI
-     */
-    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("appCode", appCode);
-        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("appCode", appCode);
-        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);
-            String body = resp.body().string();
-            if (resp.code() != HttpStatus.OK.value()) {
-                throw new ExamCloudRuntimeException("fail to get configuration. " + body);
-            }
-
-            String encryptedAppId = resp.header("App-Id");
-            String encryptedSecretKey = resp.header("Secret-Key");
-
-            appId = StringUtil.toLong(BootstrapSecurityUtil.decrypt(encryptedAppId, 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);
-        }
-
-    }
-
-    /**
-     * 检查启动参数
-     *
-     * @param args
-     * @return
-     * @author WANGWEI
-     */
-    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.appCode=")) {
-                    appCode = 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);
-        }
-
-        // appCode
-        if (null == appCode) {
-            String value = props.getProperty("examcloud.startup.appCode");
-            if (StringUtils.isNotBlank(value)) {
-                appCode = value.trim();
-            }
-        }
-        LOG.info("appCode=" + appCode);
-        if (StringUtils.isBlank(appCode)) {
-            LOG.error("property[examcloud.startup.appCode] 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);
-        }
-
-    }
-
-}
+// package cn.com.qmth.examcloud.web.bootstrap;
+//
+// import cn.com.qmth.examcloud.commons.exception.ExamCloudRuntimeException;
+// import cn.com.qmth.examcloud.commons.util.*;
+// import com.google.common.collect.Maps;
+// import com.google.common.collect.Sets;
+// import okhttp3.Response;
+// import org.apache.commons.io.IOUtils;
+// import org.apache.commons.lang3.StringUtils;
+// import org.apache.logging.log4j.ThreadContext;
+// import org.slf4j.Logger;
+// import org.slf4j.LoggerFactory;
+// import org.springframework.boot.SpringApplication;
+// import org.springframework.context.ConfigurableApplicationContext;
+// import org.springframework.http.HttpStatus;
+//
+// import java.util.Map;
+// import java.util.Map.Entry;
+// import java.util.Properties;
+// import java.util.Set;
+//
+// /**
+//  * 系统启动器
+//  *
+//  * @author WANGWEI
+//  * @date 2019年3月25日
+//  * @Copyright (c) 2018-? http://qmth.com.cn All Rights Reserved.
+//  */
+// public class AppBootstrap {
+//
+//     private static final Logger LOG = LoggerFactory.getLogger(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 configCenterHost;
+//
+//     private static String configCenterPort;
+//
+//     /**
+//      * 启动方法
+//      *
+//      * @param primarySource
+//      * @param args
+//      * @return
+//      * @author WANGWEI
+//      */
+//     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);
+//         // properties.put("spring.application.name", properties.get("spring.application.name") + "-temp");
+//
+//         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(key, value);
+//             PropertiesUtil.setProperty(key, value);
+//             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;
+//     }
+//
+//     /**
+//      * @return
+//      * @author WANGWEI
+//      */
+//     /*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;
+//             }
+//         };
+//     }*/
+//
+//     /**
+//      * 通知配置中心
+//      *
+//      * @param message
+//      * @author WANGWEI
+//      */
+//     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("appCode", appCode);
+//         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("appCode", appCode);
+//         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);
+//             String body = resp.body().string();
+//             if (resp.code() != HttpStatus.OK.value()) {
+//                 throw new ExamCloudRuntimeException("fail to get configuration. " + body);
+//             }
+//
+//             String encryptedAppId = resp.header("App-Id");
+//             String encryptedSecretKey = resp.header("Secret-Key");
+//
+//             appId = StringUtil.toLong(BootstrapSecurityUtil.decrypt(encryptedAppId, 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);
+//         }
+//
+//     }
+//
+//     /**
+//      * 检查启动参数
+//      *
+//      * @param args
+//      * @return
+//      * @author WANGWEI
+//      */
+//     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.appCode=")) {
+//                     appCode = 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);
+//         }
+//
+//         // appCode
+//         if (null == appCode) {
+//             String value = props.getProperty("examcloud.startup.appCode");
+//             if (StringUtils.isNotBlank(value)) {
+//                 appCode = value.trim();
+//             }
+//         }
+//         LOG.info("appCode=" + appCode);
+//         if (StringUtils.isBlank(appCode)) {
+//             LOG.error("property[examcloud.startup.appCode] 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);
+//         }
+//
+//     }
+//
+// }