浏览代码

Merge branch 'branch_other' 8

deason 5 年之前
父节点
当前提交
a34e6cff45

+ 18 - 0
shell/jenkins.sh

@@ -0,0 +1,18 @@
+#!/bin/bash
+pwd
+
+rm -rf  ~/project/examcloud/examcloud-config-center-distribution.zip
+rm -rf  ~/project/examcloud/examcloud-config-center/lib
+
+cp target/examcloud-config-center-distribution.zip ~/project/examcloud/
+
+cd  ~/project/examcloud/
+unzip -o examcloud-config-center-distribution.zip
+
+cd examcloud-config-center
+echo "--spring.profiles.active=test" > start.args
+echo "-server -Xms128m -Xmx128m  -XX:-UseGCOverheadLimit" > start.vmoptions
+
+
+
+

+ 1 - 0
shell/start.args

@@ -0,0 +1 @@
+--spring.profiles.active=test

+ 25 - 0
shell/start.sh

@@ -0,0 +1,25 @@
+#!/bin/bash
+
+FILE_PATH=$(cd `dirname $0`; pwd)
+APP_VERSION=`cat $FILE_PATH/version`
+APP_MAIN_JAR="examcloud-config-center-"$APP_VERSION"-SNAPSHOT.jar"
+
+JAVA_OPTS=`cat $FILE_PATH/start.vmoptions`
+APP_ARGS=`cat $FILE_PATH/start.args`
+
+PID_LIST=`ps -ef|grep $APP_MAIN_JAR|grep java|awk '{print $2}'`
+
+if [ ! -z "$PID_LIST" ]; then
+    echo "[ERROR] : APP is already running!"
+    exit -1
+fi
+
+echo "java options:"
+echo "$JAVA_OPTS"
+echo "args:"
+echo "$APP_ARGS"
+
+java $JAVA_OPTS -jar $FILE_PATH/lib/$APP_MAIN_JAR $APP_ARGS 
+
+exit 0
+

+ 1 - 0
shell/start.vmoptions

@@ -0,0 +1 @@
+-server -Xms2g -Xmx2g

+ 18 - 0
shell/stop.sh

@@ -0,0 +1,18 @@
+#!/bin/bash
+
+FILE_PATH=$(cd `dirname $0`; pwd)
+APP_VERSION=`cat $FILE_PATH/version`
+APP_MAIN_JAR="examcloud-config-center-"$APP_VERSION"-SNAPSHOT.jar"
+
+PID_LIST=`ps -ef|grep $APP_MAIN_JAR|grep java|awk '{print $2}'`
+
+if [ ! -z "$PID_LIST" ]; then
+    echo "Runnable jar is $APP_MAIN_JAR."
+    for PID in $PID_LIST 
+    do
+        kill -9 $PID
+    done
+    echo "stopped !"
+fi
+
+exit 0

+ 1 - 0
shell/version

@@ -0,0 +1 @@
+2019

+ 143 - 0
src/main/java/cn/com/qmth/examcloud/config/center/ConfigCenterStarter.java

@@ -0,0 +1,143 @@
+package cn.com.qmth.examcloud.config.center;
+
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.commons.compress.utils.IOUtils;
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.logging.log4j.ThreadContext;
+import org.jline.reader.LineReader;
+import org.jline.reader.LineReaderBuilder;
+import org.jline.terminal.Terminal;
+import org.jline.terminal.TerminalBuilder;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+
+import cn.com.qmth.examcloud.commons.helpers.BlackHolePrintStreamBuilder;
+import cn.com.qmth.examcloud.commons.logging.ExamCloudLog;
+import cn.com.qmth.examcloud.commons.logging.ExamCloudLogFactory;
+import cn.com.qmth.examcloud.config.center.core.BootstrapSecurityManager;
+import cn.com.qmth.examcloud.config.center.core.CommandInterpreter;
+import cn.com.qmth.examcloud.config.center.core.ConfigCenterBootstrap;
+
+/**
+ * 配置中心启动类
+ *
+ * @author WANGWEI
+ * @date 2019年3月29日
+ * @Copyright (c) 2018-? http://qmth.com.cn All Rights Reserved.
+ */
+@SpringBootApplication
+@Configuration
+@ComponentScan(basePackages = {"cn.com.qmth"})
+@EnableAutoConfiguration(exclude = {RedisAutoConfiguration.class,
+		DataSourceAutoConfiguration.class})
+public class ConfigCenterStarter {
+
+	private static PrintStream stdOut = null;
+
+	private static PrintStream stdErrOut = null;
+
+	private static PrintStream blackHoleOut = null;
+
+	private static Long action = System.currentTimeMillis();
+
+	/**
+	 * 启动方法
+	 *
+	 * @author WANGWEI
+	 * @param args
+	 */
+	public static void run(String[] args) {
+		ExamCloudLog log = ExamCloudLogFactory.getLog(ConfigCenterStarter.class);
+		ThreadContext.put("TRACE_ID", Thread.currentThread().getName());
+		log.info("Starting...");
+
+		blackHoleOut = BlackHolePrintStreamBuilder.build();
+		stdOut = System.out;
+		stdErrOut = System.err;
+
+		Terminal terminal = null;
+		LineReader reader = null;
+		try {
+			System.setOut(blackHoleOut);
+			System.setErr(blackHoleOut);
+			terminal = TerminalBuilder.terminal();
+			reader = LineReaderBuilder.builder().terminal(terminal).build();
+			System.setOut(stdOut);
+			System.setErr(stdErrOut);
+		} catch (IOException e) {
+			System.setOut(stdOut);
+			System.setErr(stdErrOut);
+			IOUtils.closeQuietly(terminal);
+			e.printStackTrace();
+			System.exit(-1);
+		}
+
+		String secretKey = null;
+		while (true) {
+			try {
+				secretKey = reader.readLine("Enter secret key>", (char) 0);
+				System.setOut(blackHoleOut);
+				System.setErr(blackHoleOut);
+				args = (String[]) ArrayUtils.add(args,
+						"--examcloud.startup.secretKey=" + secretKey);
+
+				ConfigCenterBootstrap.run(ConfigCenterStarter.class, args);
+				System.setOut(stdOut);
+				System.setErr(stdErrOut);
+				break;
+			} catch (Exception e) {
+				System.setOut(stdOut);
+				System.setErr(stdErrOut);
+				System.out.println(e.getMessage());
+				System.out.println("Try again... ...");
+				continue;
+			}
+		}
+
+		System.out.println("I am running... ...");
+		String active = BootstrapSecurityManager.getInstance().getActive();
+		System.out.println("active=" + active);
+
+		new Thread() {
+			@Override
+			public void run() {
+				while (true) {
+					if (System.currentTimeMillis() - action > CommandInterpreter.getInstance()
+							.getSessionTimeout()) {
+						System.exit(0);
+					}
+					try {
+						TimeUnit.SECONDS.sleep(5);
+					} catch (InterruptedException e) {
+						e.printStackTrace();
+					}
+				}
+
+			};
+		}.start();
+
+		IOUtils.closeQuietly(blackHoleOut);
+		action = System.currentTimeMillis();
+
+		while (true) {
+			action = System.currentTimeMillis();
+			String cmd = reader.readLine("$>");
+			if (cmd.equals("q")) {
+				break;
+			}
+
+			CommandInterpreter.getInstance().interpret(cmd);
+		}
+
+		IOUtils.closeQuietly(terminal);
+		System.exit(0);
+	}
+
+}

+ 25 - 0
src/main/java/cn/com/qmth/examcloud/config/center/configuration/ExamCloudAppSelf.java

@@ -0,0 +1,25 @@
+package cn.com.qmth.examcloud.config.center.configuration;
+
+import org.springframework.stereotype.Component;
+
+import cn.com.qmth.examcloud.web.cloud.AppSelf;
+
+@Component
+public class ExamCloudAppSelf implements AppSelf {
+
+	@Override
+	public Long getAppId() {
+		return -1L;
+	}
+
+	@Override
+	public String getSecretKey() {
+		return null;
+	}
+
+	@Override
+	public String getAppCode() {
+		return "CC";
+	}
+
+}

+ 24 - 0
src/main/java/cn/com/qmth/examcloud/config/center/configuration/ExamCloudWebMvcConfigurer.java

@@ -0,0 +1,24 @@
+package cn.com.qmth.examcloud.config.center.configuration;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+import cn.com.qmth.examcloud.web.interceptor.FirstInterceptor;
+
+/**
+ * WebMvcConfigurer
+ *
+ * @author WANGWEI
+ * @date 2019年1月30日
+ * @Copyright (c) 2018-2020 http://www.qmth.com.cn/ All Rights Reserved.
+ */
+@Configuration
+public class ExamCloudWebMvcConfigurer implements WebMvcConfigurer {
+
+	@Override
+	public void addInterceptors(InterceptorRegistry registry) {
+		registry.addInterceptor(new FirstInterceptor()).addPathPatterns("/**");
+	}
+
+}

+ 86 - 0
src/main/java/cn/com/qmth/examcloud/config/center/controller/ConfigCenterController.java

@@ -0,0 +1,86 @@
+package cn.com.qmth.examcloud.config.center.controller;
+
+import java.util.Map;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import cn.com.qmth.examcloud.commons.logging.ExamCloudLog;
+import cn.com.qmth.examcloud.commons.logging.ExamCloudLogFactory;
+import cn.com.qmth.examcloud.commons.util.JsonUtil;
+import cn.com.qmth.examcloud.config.center.core.BootstrapSecurityManager;
+import cn.com.qmth.examcloud.config.center.core.PropertiesLoader;
+import cn.com.qmth.examcloud.web.bootstrap.BootstrapSecurityUtil;
+import io.swagger.annotations.ApiOperation;
+
+@Controller
+@RequestMapping("configCenter")
+public class ConfigCenterController {
+
+	private static ExamCloudLog log = ExamCloudLogFactory.getLog("APP_STARTUP_LOGGER");
+
+	@ApiOperation(value = "消息通知")
+	@PostMapping("notice")
+	public ResponseEntity<String> notice(@RequestParam(required = true) String active,
+			@RequestParam(required = true) String appCode,
+			@RequestParam(required = true) String startupCode,
+			@RequestParam(required = true) String message) {
+
+		String mainInfo = "notice(). active=" + active + "; appCode=" + appCode + "; startupCode="
+				+ startupCode + "; message=" + message;
+		log.debug(mainInfo);
+
+		String configCenterActive = BootstrapSecurityManager.getInstance().getActive();
+		if (!configCenterActive.equals(active)) {
+			log.error("active is wrong");
+			return new ResponseEntity<>("active is wrong", HttpStatus.INTERNAL_SERVER_ERROR);
+		}
+
+		return new ResponseEntity<String>("OK", HttpStatus.OK);
+	}
+
+	@ApiOperation(value = "启动请求")
+	@PostMapping("startup")
+	public ResponseEntity<String> startup(@RequestParam(required = true) String active,
+			@RequestParam(required = true) String appCode,
+			@RequestParam(required = true) String startupCode, HttpServletResponse response) {
+
+		String mainInfo = "startup(). active=" + active + "; appCode=" + appCode + "; startupCode="
+				+ startupCode;
+
+		log.debug(mainInfo);
+
+		String configCenterActive = BootstrapSecurityManager.getInstance().getActive();
+		if (!configCenterActive.equals(active)) {
+			log.error("active is wrong");
+			return new ResponseEntity<>("active is wrong", HttpStatus.INTERNAL_SERVER_ERROR);
+		}
+
+		Map<String, String> map = null;
+		try {
+			map = PropertiesLoader.getProperties(appCode, active);
+		} catch (Exception e) {
+			log.error(e.getMessage());
+			return new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
+		}
+
+		String ret = JsonUtil.toJson(map);
+		ret = BootstrapSecurityUtil.encrypt(ret, startupCode);
+
+		String appId = map.get("examcloud.bootstrap.app.appId");
+		String secretKey = map.get("examcloud.bootstrap.app.secretKey");
+
+		response.setHeader("App-Id", BootstrapSecurityUtil.encrypt(appId, startupCode));
+		response.setHeader("App-Code", appCode);
+		response.setHeader("Secret-Key", BootstrapSecurityUtil.encrypt(secretKey, startupCode));
+
+		return new ResponseEntity<>(ret, HttpStatus.OK);
+	}
+
+}

+ 61 - 0
src/main/java/cn/com/qmth/examcloud/config/center/core/BootstrapSecurityManager.java

@@ -0,0 +1,61 @@
+package cn.com.qmth.examcloud.config.center.core;
+
+/**
+ * 启动安全管理器
+ *
+ * @author WANGWEI
+ * @date 2019年3月25日
+ * @Copyright (c) 2018-? http://qmth.com.cn All Rights Reserved.
+ */
+public class BootstrapSecurityManager {
+
+	private static BootstrapSecurityManager mgr;
+
+	private static final Object LOCK = new Object();
+
+	private String secretKey;
+
+	private String active;
+
+	/**
+	 * 构造函数
+	 */
+	private BootstrapSecurityManager() {
+	}
+
+	/**
+	 * 获取单例
+	 *
+	 * @author WANGWEI
+	 * @return
+	 */
+	public static BootstrapSecurityManager getInstance() {
+		if (null == mgr) {
+			synchronized (LOCK) {
+				if (null == mgr) {
+					mgr = new BootstrapSecurityManager();
+				}
+				return mgr;
+			}
+		} else {
+			return mgr;
+		}
+	}
+
+	public String getSecretKey() {
+		return secretKey;
+	}
+
+	public void setSecretKey(String secretKey) {
+		this.secretKey = secretKey;
+	}
+
+	public String getActive() {
+		return active;
+	}
+
+	public void setActive(String active) {
+		this.active = active;
+	}
+
+}

+ 116 - 0
src/main/java/cn/com/qmth/examcloud/config/center/core/CommandInterpreter.java

@@ -0,0 +1,116 @@
+package cn.com.qmth.examcloud.config.center.core;
+
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.commons.lang3.StringUtils;
+
+import cn.com.qmth.examcloud.commons.logging.ExamCloudLog;
+import cn.com.qmth.examcloud.commons.logging.ExamCloudLogFactory;
+import cn.com.qmth.examcloud.commons.util.MapUtil;
+import cn.com.qmth.examcloud.commons.util.RegExpUtil;
+import cn.com.qmth.examcloud.commons.util.StringUtil;
+
+/**
+ * 命令解释器
+ *
+ * @author WANGWEI
+ * @date 2018年12月5日
+ * @Copyright (c) 2018-? http://qmth.com.cn All Rights Reserved.
+ */
+public class CommandInterpreter {
+
+	private static ExamCloudLog log = ExamCloudLogFactory.getLog("COMMAND_LOGGER");
+
+	private static CommandInterpreter interpreter;
+
+	private static final Object LOCK = new Object();
+
+	private static long sessionTimeout = 1000 * 60 * 5;
+
+	/**
+	 * 构造函数
+	 */
+	private CommandInterpreter() {
+	}
+
+	/**
+	 * 获取单例
+	 *
+	 * @author WANGWEI
+	 * @return
+	 */
+	public static CommandInterpreter getInstance() {
+		if (null == interpreter) {
+			synchronized (LOCK) {
+				if (null == interpreter) {
+					interpreter = new CommandInterpreter();
+				}
+				return interpreter;
+			}
+		} else {
+			return interpreter;
+		}
+	}
+
+	/**
+	 * 解释
+	 *
+	 * @author WANGWEI
+	 */
+	public void interpret(String cmd) {
+		try {
+			process(cmd);
+		} catch (Exception e) {
+			log.error(e.getMessage());
+		}
+	}
+
+	/**
+	 * 处理
+	 *
+	 * @author WANGWEI
+	 */
+	public void process(String cmd) {
+		cmd = cmd.trim();
+		if (StringUtils.isBlank(cmd)) {
+			return;
+		}
+
+		// 设置进程退出:session 10
+		if (cmd.matches("\\s*session\\s+[1-9]\\d*")) {
+			String timeout = RegExpUtil.find(cmd, "\\s*session\\s+([1-9]\\d*)", 1);
+			timeout = timeout.length() > 4 ? "9999" : timeout;
+			long timeoutLong = StringUtil.toLong(timeout);
+			timeoutLong = timeoutLong > 60 ? 60 : timeoutLong;
+			log.info("sessionTimeout = " + timeoutLong + " minutes");
+			sessionTimeout = timeoutLong * 1000 * 60;
+		}
+
+		// 加载配置:load <appSimpleName>
+		else if (cmd.matches("\\s*load\\s+([^\\s]+)\\s*")) {
+			String appSimpleName = RegExpUtil.find(cmd, "\\s*load\\s+([^\\s]+)\\s*", 1);
+			String active = BootstrapSecurityManager.getInstance().getActive();
+			Map<String, String> properties = PropertiesLoader.getProperties(appSimpleName, active);
+
+			properties = MapUtil.sortMapByKey(properties, true);
+			StringBuilder sb = new StringBuilder("properties about ").append(appSimpleName)
+					.append(" [").append(active).append("]:");
+			for (Entry<String, String> entry : properties.entrySet()) {
+				sb.append("\n   ").append(entry.getKey()).append(" : ").append(entry.getValue());
+			}
+			log.info(sb.toString());
+		}
+
+		// 错误命令
+		else {
+			log.error("error command !");
+		}
+
+	}
+
+	public long getSessionTimeout() {
+		return sessionTimeout;
+	}
+
+}

+ 115 - 0
src/main/java/cn/com/qmth/examcloud/config/center/core/ConfigCenterBootstrap.java

@@ -0,0 +1,115 @@
+package cn.com.qmth.examcloud.config.center.core;
+
+import java.util.Map.Entry;
+import java.util.Properties;
+import java.util.Set;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.boot.SpringApplication;
+import org.springframework.context.ConfigurableApplicationContext;
+
+import com.google.common.collect.Sets;
+
+import cn.com.qmth.examcloud.commons.logging.ExamCloudLog;
+import cn.com.qmth.examcloud.commons.logging.ExamCloudLogFactory;
+import cn.com.qmth.examcloud.commons.util.PropertiesUtil;
+import cn.com.qmth.examcloud.web.bootstrap.BootstrapSecurityUtil;
+
+/**
+ * 配置中心启动器
+ *
+ * @author WANGWEI
+ * @date 2019年3月25日
+ * @Copyright (c) 2018-? http://qmth.com.cn All Rights Reserved.
+ */
+public class ConfigCenterBootstrap {
+
+	private static ExamCloudLog log = ExamCloudLogFactory.getLog(ConfigCenterBootstrap.class);
+
+	/**
+	 * 启动配置中心
+	 *
+	 * @author WANGWEI
+	 * @param primarySource
+	 * @param password
+	 * @return
+	 */
+	public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
+
+		Properties props = new Properties();
+		PropertiesUtil.loadFromResource("application.properties", props);
+
+		String active = null;
+		String secretKey = null;
+		if (null != args) {
+			for (String s : args) {
+				s = s.trim();
+				if (s.startsWith("--examcloud.startup.secretKey=")) {
+					secretKey = s.substring(s.indexOf("=") + 1);
+				}
+				if (s.startsWith("--spring.profiles.active=")) {
+					active = 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);
+		}
+
+		if (StringUtils.isBlank(secretKey)) {
+			throw new RuntimeException("secret key is specified !");
+		}
+
+		PropertiesUtil.loadFromResource("application-" + active + ".properties", props);
+		props.setProperty("spring.profiles.active", active);
+
+		String test = props.getProperty("$$.examcloud.test");
+		if (StringUtils.isBlank(test)) {
+			log.error("property[$$.examcloud.test] is not configured");
+			System.exit(-1);
+		}
+		try {
+			BootstrapSecurityUtil.decrypt(test.trim(), secretKey);
+		} catch (Exception e) {
+			throw new RuntimeException("secret key is wrong !");
+		}
+
+		try {
+			BootstrapSecurityUtil.decrypt(props, secretKey);
+		} catch (Exception e) {
+			log.error("fail to decrypt !");
+			System.exit(-1);
+		}
+
+		Set<String> argSet = Sets.newLinkedHashSet();
+		for (Entry<Object, Object> p : props.entrySet()) {
+			String arg = "--" + p.getKey() + "=" + p.getValue();
+			argSet.add(arg);
+		}
+
+		String[] newArgs = argSet.toArray(new String[argSet.size()]);
+
+		BootstrapSecurityManager.getInstance().setSecretKey(secretKey);
+		BootstrapSecurityManager.getInstance().setActive(active);
+
+		ConfigurableApplicationContext context = null;
+		try {
+			context = SpringApplication.run(primarySource, newArgs);
+		} catch (Exception e) {
+			log.error("fail to run spring app.", e);
+			System.exit(-1);
+		}
+		return context;
+	}
+
+}

+ 85 - 0
src/main/java/cn/com/qmth/examcloud/config/center/core/PropertiesLoader.java

@@ -0,0 +1,85 @@
+package cn.com.qmth.examcloud.config.center.core;
+
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Properties;
+import java.util.Set;
+
+import org.apache.commons.lang3.StringUtils;
+
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+
+import cn.com.qmth.examcloud.commons.util.PropertiesUtil;
+import cn.com.qmth.examcloud.web.bootstrap.BootstrapSecurityUtil;
+
+/**
+ * 配置加载器
+ *
+ * @author WANGWEI
+ * @date 2019年5月15日
+ * @Copyright (c) 2018-? http://qmth.com.cn All Rights Reserved.
+ */
+public class PropertiesLoader {
+
+	/**
+	 * 保存启动配置属性
+	 *
+	 * @author WANGWEI
+	 * @param appCode
+	 * @param active
+	 */
+	public static Map<String, String> getProperties(String appCode, String active) {
+
+		Properties props = new Properties();
+		String resource1 = active + "/application.properties";
+		String resource2 = active + "/application-" + appCode + ".properties";
+
+		try {
+			PropertiesUtil.loadFromResource(resource1, props);
+		} catch (Exception e) {
+			String errorMessage = "fail to load properties file [" + resource1 + "]";
+			throw new RuntimeException(errorMessage);
+		}
+
+		BootstrapSecurityUtil.decrypt(props, BootstrapSecurityManager.getInstance().getSecretKey());
+
+		try {
+			PropertiesUtil.loadFromResource(resource2, props);
+		} catch (Exception e) {
+			String errorMessage = "fail to load properties file [" + resource2 + "]";
+			throw new RuntimeException(errorMessage);
+		}
+
+		BootstrapSecurityUtil.decrypt(props, BootstrapSecurityManager.getInstance().getSecretKey());
+
+		Map<String, String> map = Maps.newHashMap();
+		for (Entry<Object, Object> entry : props.entrySet()) {
+			map.put(String.valueOf(entry.getKey()), String.valueOf(entry.getValue()));
+		}
+
+		filter(map);
+		return map;
+	}
+
+	private static void filter(Map<String, String> properties) {
+		Set<String> removedKeySet = Sets.newHashSet();
+
+		String datasourceType = properties.get("spring.datasource.type");
+		if (StringUtils.isNotBlank(datasourceType)) {
+			if (datasourceType.equalsIgnoreCase("null")) {
+				for (String key : properties.keySet()) {
+					if (key.startsWith("spring.datasource")) {
+						removedKeySet.add(key);
+					}
+				}
+			}
+		}
+
+		for (String key : removedKeySet) {
+			properties.remove(key);
+		}
+
+	}
+
+}

+ 49 - 0
src/main/java/cn/com/qmth/examcloud/config/center/test/Rpc.java

@@ -0,0 +1,49 @@
+package cn.com.qmth.examcloud.config.center.test;
+
+import java.io.IOException;
+import java.util.Map;
+
+import com.google.common.collect.Maps;
+
+import cn.com.qmth.examcloud.commons.util.ByteUtil;
+import cn.com.qmth.examcloud.commons.util.HttpMethod;
+import cn.com.qmth.examcloud.commons.util.OKHttpUtil;
+import cn.com.qmth.examcloud.commons.util.SHA256;
+import cn.com.qmth.examcloud.commons.util.StringUtil;
+import cn.com.qmth.examcloud.commons.util.ThreadLocalUtil;
+import okhttp3.Response;
+
+/**
+ * RPC
+ *
+ * @author WANGWEI
+ * @date 2019年6月13日
+ * @Copyright (c) 2018-? http://qmth.com.cn All Rights Reserved.
+ */
+public class Rpc {
+
+	public static void main(String[] args) throws IOException {
+
+		Map<String, String> headers = Maps.newHashMap();
+		long startTime = System.currentTimeMillis();
+		String appId = "1";
+		String appCode = "B";
+		String secretKey = "123456";
+
+		headers.put("Trace-Id", ThreadLocalUtil.getTraceId());
+		headers.put("timestamp", String.valueOf(startTime));
+		headers.put("App-Id", appId);
+		headers.put("App-Code", appCode);
+
+		String joinStr = StringUtil.join(appId, appCode, startTime, secretKey);
+		byte[] bytes = SHA256.encode(joinStr);
+		String accessToken = ByteUtil.toHexAscii(bytes);
+		headers.put("Access-Token", accessToken);
+
+		String url = "http://192.168.10.39:8001/cache/refresh";
+		String reqBody = "{\"className\":\"cn.com.qmth.examcloud.core.examwork.service.cache.ExamOrgPropertyCache\",\"keys\":[\"a\",\"3\",\"WARN_THRESHOLD\"],\"typeArray\":[\"LONG\",\"LONG\",\"STRING\"]}";
+		Response response = OKHttpUtil.call(HttpMethod.POST, url, headers, reqBody);
+
+		System.out.println(response.body().string());
+	}
+}

+ 13 - 0
src/main/java/cn/com/qmth/examcloud/config/center/test/Test.java

@@ -0,0 +1,13 @@
+package cn.com.qmth.examcloud.config.center.test;
+
+import cn.com.qmth.examcloud.web.bootstrap.BootstrapSecurityUtil;
+
+public class Test {
+	public static void main(String[] args) {
+		String s = "";
+		String secretKey = "";
+		System.out.println(BootstrapSecurityUtil.encrypt(s, secretKey));
+		// System.out.println(BootstrapSecurityUtil.decrypt(s, secretKey));
+	}
+
+}

+ 14 - 0
src/main/java/cn/com/qmth/examcloud/config/center/test/Test2.java

@@ -0,0 +1,14 @@
+package cn.com.qmth.examcloud.config.center.test;
+
+import cn.com.qmth.examcloud.commons.util.ByteUtil;
+import cn.com.qmth.examcloud.commons.util.SHA256;
+
+public class Test2 {
+	public static void main(String[] args) {
+		String str1 = "1";
+		String str2 = "123456";
+		String encoded = ByteUtil.toHexAscii(SHA256.encode(str1 + str2));
+		System.out.println(encoded);
+	}
+
+}

+ 37 - 0
src/main/resources/log4j2.xml

@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Configuration status="WARN" monitorInterval="30">
+
+	<Appenders>
+		<Console name="CONSOLE" target="SYSTEM_OUT">
+			<PatternLayout pattern="%n%d{HH:mm:ss}| %level | %X{TRACE_ID} | %m | %l%n$>" />
+		</Console>
+		<Console name="APP_STARTUP_CONSOLE" target="SYSTEM_OUT">
+			<PatternLayout pattern="%n%d{HH:mm:ss}| %level | %X{TRACE_ID} | %m%n$>" />
+		</Console>
+		<Console name="COMMAND_CONSOLE" target="SYSTEM_OUT">
+			<PatternLayout pattern="%d{HH:mm:ss}| %level | CMD | %m%n" />
+		</Console>
+	</Appenders>
+
+	<Loggers>
+		<Logger name="APP_STARTUP_LOGGER" level="DEBUG" additivity="false">
+			<AppenderRef ref="APP_STARTUP_CONSOLE" />
+		</Logger>
+
+		<Logger name="COMMAND_LOGGER" level="DEBUG" additivity="false">
+			<AppenderRef ref="COMMAND_CONSOLE" />
+		</Logger>
+
+		<Logger name="INTERFACE_LOGGER" level="OFF" additivity="false">
+			<AppenderRef ref="CONSOLE" />
+		</Logger>
+
+		<Logger name="org.quartz.core" level="ERROR" />
+
+		<Root level="ERROR">
+			<AppenderRef ref="CONSOLE" />
+		</Root>
+
+	</Loggers>
+
+</Configuration>