colors = Lists.newArrayList();
+ colors.add(new Color(0, 135, 255));
+ colors.add(new Color(51, 153, 51));
+ colors.add(new Color(255, 102, 102));
+ colors.add(new Color(255, 153, 0));
+ colors.add(new Color(153, 102, 0));
+ colors.add(new Color(153, 102, 153));
+ colors.add(new Color(51, 153, 153));
+ colors.add(new Color(102, 102, 255));
+ colors.add(new Color(0, 102, 204));
+ colors.add(new Color(204, 51, 51));
+ colors.add(new Color(128, 153, 65));
+ Random random = new Random();
+ int colorIndex = random.nextInt(10);
+ return colors.get(colorIndex);
+ }
+}
diff --git a/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/kaptcha/KaptchaNoise.java b/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/kaptcha/KaptchaNoise.java
new file mode 100644
index 00000000..3af2a7ad
--- /dev/null
+++ b/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/kaptcha/KaptchaNoise.java
@@ -0,0 +1,44 @@
+package com.gangquan360.smartadmin.common.kaptcha;
+
+import com.google.code.kaptcha.NoiseProducer;
+import com.google.code.kaptcha.util.Configurable;
+
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.util.Random;
+
+/**
+ * [ 验证码加噪处理 ]
+ *
+ * @author yandanyang
+ * @version 1.0
+ * @company 1024lab.net
+ * @copyright (c) 2018 1024lab.netInc. All rights reserved.
+ * @date 2019/7/6 0006 上午 10:47
+ * @since JDK1.8
+ */
+public class KaptchaNoise extends Configurable implements NoiseProducer {
+ public KaptchaNoise() {
+ }
+
+ @Override
+ public void makeNoise(BufferedImage image, float factorOne, float factorTwo, float factorThree, float factorFour) {
+
+ int width = image.getWidth();
+ int height = image.getHeight();
+ Graphics2D graph = (Graphics2D)image.getGraphics();
+ graph.setRenderingHints(new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON));
+ graph.setStroke(new BasicStroke(1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));
+ Random random = new Random();
+ int noiseLineNum = random.nextInt(3);
+ if(noiseLineNum == 0){
+ noiseLineNum = 1;
+ }
+ for (int i = 0; i < noiseLineNum; i++){
+ graph.setColor(KaptchaColor.getColor());
+ graph.drawLine(random.nextInt(width), random.nextInt(height), 10 + random.nextInt(20), 10 + random.nextInt(20));
+ }
+
+ graph.dispose();
+ }
+}
diff --git a/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/kaptcha/KaptchaWordRenderer.java b/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/kaptcha/KaptchaWordRenderer.java
new file mode 100644
index 00000000..ef0269b1
--- /dev/null
+++ b/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/kaptcha/KaptchaWordRenderer.java
@@ -0,0 +1,75 @@
+package com.gangquan360.smartadmin.common.kaptcha;
+
+import com.google.code.kaptcha.util.Configurable;
+
+import java.awt.*;
+import java.awt.font.FontRenderContext;
+import java.awt.font.GlyphVector;
+import java.awt.image.BufferedImage;
+import java.util.Random;
+
+/**
+ * [ 验证码字体生成 ]
+ *
+ * @author yandanyang
+ * @version 1.0
+ * @company 1024lab.net
+ * @copyright (c) 2018 1024lab.netInc. All rights reserved.
+ * @date 2019/7/6 0006 上午 9:43
+ * @since JDK1.8
+ */
+public class KaptchaWordRenderer extends Configurable implements com.google.code.kaptcha.text.WordRenderer {
+
+ public KaptchaWordRenderer() {
+ }
+
+ @Override
+ public BufferedImage renderWord(String word, int width, int height) {
+ int fontSize = this.getConfig().getTextProducerFontSize();
+ Font[] fonts = this.getConfig().getTextProducerFonts(fontSize);
+ int charSpace = this.getConfig().getTextProducerCharSpace();
+ BufferedImage image = new BufferedImage(width, height, 2);
+
+ Graphics2D g2D = image.createGraphics();
+ g2D.setColor(Color.WHITE);
+ RenderingHints hints = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+ hints.add(new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY));
+ g2D.setRenderingHints(hints);
+ g2D.setStroke(new BasicStroke(1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));
+
+ FontRenderContext frc = g2D.getFontRenderContext();
+ Random random = new Random();
+ int startPosY = (height - fontSize) / 5 + fontSize;
+ char[] wordChars = word.toCharArray();
+ Font[] chosenFonts = new Font[wordChars.length];
+ int[] charWidths = new int[wordChars.length];
+ int widthNeeded = 0;
+
+ int startPosX;
+ for(startPosX = 0; startPosX < wordChars.length; ++startPosX) {
+ chosenFonts[startPosX] = fonts[random.nextInt(fonts.length)];
+ char[] charToDraw = new char[]{wordChars[startPosX]};
+ GlyphVector gv = chosenFonts[startPosX].createGlyphVector(frc, charToDraw);
+ charWidths[startPosX] = (int)gv.getVisualBounds().getWidth();
+ if (startPosX > 0) {
+ widthNeeded += 2;
+ }
+
+ widthNeeded += charWidths[startPosX];
+ }
+
+ startPosX = (width - widthNeeded) / 2;
+
+ for(int i = 0; i < wordChars.length; ++i) {
+ g2D.setColor(KaptchaColor.getColor());
+ g2D.setFont(chosenFonts[i].deriveFont(Font.PLAIN));
+ char[] charToDraw = new char[]{wordChars[i]};
+ g2D.drawChars(charToDraw, 0, charToDraw.length, startPosX, startPosY);
+ startPosX = startPosX + charWidths[i] + charSpace;
+ }
+
+ return image;
+ }
+
+
+}
diff --git a/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/reload/SmartReloadManager.java b/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/reload/SmartReloadManager.java
new file mode 100644
index 00000000..f6e7352e
--- /dev/null
+++ b/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/reload/SmartReloadManager.java
@@ -0,0 +1,134 @@
+package com.gangquan360.smartadmin.common.reload;
+
+import com.gangquan360.smartadmin.common.reload.annotation.SmartReload;
+import com.gangquan360.smartadmin.common.reload.domain.AbstractSmartReloadObject;
+import com.gangquan360.smartadmin.common.reload.domain.AnnotationReloadObject;
+import com.gangquan360.smartadmin.common.reload.domain.InterfaceReloadObject;
+import com.gangquan360.smartadmin.common.reload.domain.entity.ReloadItem;
+import com.gangquan360.smartadmin.common.reload.domain.entity.SmartReloadResult;
+import com.gangquan360.smartadmin.common.reload.interfaces.SmartReloadCommandInterface;
+import com.gangquan360.smartadmin.common.reload.interfaces.SmartReloadThreadLogger;
+import com.gangquan360.smartadmin.common.reload.interfaces.SmartReloadable;
+
+import java.lang.reflect.Method;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.TimeUnit;
+
+import static java.util.Objects.requireNonNull;
+
+/**
+ * SmartReloadManager 管理器
+ *
+ * 可以在此类中添加 检测任务 以及注册 处理程序
+ *
+ * @author zhuoda
+ */
+public class SmartReloadManager {
+
+ private Map tagReloadObject;
+
+ private SmartReloadScheduler reloadScheduler;
+
+ private SmartReloadThreadLogger logger;
+
+ public SmartReloadManager(SmartReloadThreadLogger logger, int threadCount) {
+ this.tagReloadObject = new ConcurrentHashMap<>();
+ if (logger == null) {
+ throw new ExceptionInInitializerError("SmartReloadLoggerImp cannot be null");
+ }
+
+ if (threadCount < 1) {
+ throw new ExceptionInInitializerError("threadCount must be greater than 1");
+ }
+
+ this.logger = logger;
+ this.reloadScheduler = new SmartReloadScheduler(this.logger, threadCount);
+ }
+
+ /**
+ * 默认创建单个线程
+ *
+ * @param logger
+ */
+ public SmartReloadManager(SmartReloadThreadLogger logger) {
+ this(logger, 1);
+ }
+
+ /**
+ * 停止
+ */
+ public void shutdown() {
+ reloadScheduler.shutdown();
+ }
+
+ /**
+ * 添加任务
+ *
+ * @param command SmartReloadCommand实现类
+ * @param initialDelay 第一次执行前的延迟时间
+ * @param delay 任务间隔时间
+ * @param unit 延迟单位 TimeUnit 天、小时、分、秒等
+ */
+ public void addCommand(SmartReloadCommandInterface command, long initialDelay, long delay, TimeUnit unit) {
+ reloadScheduler.addCommand(command, initialDelay, delay, unit);
+ }
+
+ /**
+ * 注册 实现接口的方式
+ *
+ * @param tag
+ * @param reloadable
+ */
+ public void register(String tag, SmartReloadable reloadable) {
+ requireNonNull(reloadable);
+ requireNonNull(tag);
+ if (tagReloadObject.containsKey(tag)) {
+ logger.error("<> register duplicated tag reload : " + tag + " , and it will be cover!");
+ }
+ tagReloadObject.put(tag, new InterfaceReloadObject(reloadable));
+ }
+
+ /**
+ * 注册 要求此类必须包含使用了SmartReload注解的方法
+ *
+ * @param reloadObject
+ */
+ public void register(Object reloadObject) {
+ requireNonNull(reloadObject);
+ Method[] declaredMethods = reloadObject.getClass().getDeclaredMethods();
+ if (declaredMethods != null) {
+ for (int i = 0; i < declaredMethods.length; i++) {
+ Method method = declaredMethods[i];
+ SmartReload annotation = method.getAnnotation(SmartReload.class);
+ if (annotation != null) {
+ String reloadTag = annotation.value();
+ this.register(reloadTag, new AnnotationReloadObject(reloadObject, method));
+ }
+ }
+ }
+ }
+
+ private void register(String tag, AbstractSmartReloadObject reloadObject) {
+ if (tagReloadObject.containsKey(tag)) {
+ logger.error("<> register duplicated tag reload : " + tag + " , and it will be cover!");
+ }
+ tagReloadObject.put(tag, reloadObject);
+ }
+
+ /**
+ * Reload 已注册的ReloadItem
+ *
+ * @param reloadItem
+ * @return SmartReloadResult
+ */
+ public SmartReloadResult doReload(ReloadItem reloadItem) {
+ AbstractSmartReloadObject reloadObject = tagReloadObject.get(reloadItem.getTag());
+ if (reloadObject != null) {
+ return reloadObject.reload(reloadItem);
+ }
+ // 返回注册结果
+ return new SmartReloadResult(reloadItem.getTag(), reloadItem.getArgs(), reloadItem.getIdentification(), false, "No registered reload handler was found");
+ }
+
+}
diff --git a/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/reload/SmartReloadScheduler.java b/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/reload/SmartReloadScheduler.java
new file mode 100644
index 00000000..d0dc0587
--- /dev/null
+++ b/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/reload/SmartReloadScheduler.java
@@ -0,0 +1,87 @@
+package com.gangquan360.smartadmin.common.reload;
+
+import com.gangquan360.smartadmin.common.reload.interfaces.SmartReloadCommandInterface;
+import com.gangquan360.smartadmin.common.reload.interfaces.SmartReloadThreadLogger;
+
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Reload 调度器
+ *
+ * @author zhuoda
+ */
+public class SmartReloadScheduler {
+
+ private ScheduledThreadPoolExecutor executor;
+
+ private SmartReloadThreadLogger logger;
+
+ SmartReloadScheduler(SmartReloadThreadLogger logger, int threadCount) {
+ this.executor = new ScheduledThreadPoolExecutor(threadCount, new SmartReloadSchedulerThreadFactory());
+ this.logger = logger;
+ }
+
+ void shutdown() {
+ try {
+ executor.shutdown();
+ } catch (Throwable e) {
+ logger.error("<> shutdown ", e);
+ }
+ }
+
+ void addCommand(SmartReloadCommandInterface command, long initialDelay, long delay, TimeUnit unit) {
+ executor.scheduleWithFixedDelay(new ScheduleRunnable(command, this.logger), initialDelay, delay, unit);
+ }
+
+ static class ScheduleRunnable implements Runnable {
+
+ private SmartReloadCommandInterface command;
+
+ private SmartReloadThreadLogger logger;
+
+ public ScheduleRunnable(SmartReloadCommandInterface command, SmartReloadThreadLogger logger) {
+ this.command = command;
+ this.logger = logger;
+ }
+
+ @Override
+ public void run() {
+ try {
+ command.doTask();
+ } catch (Throwable e) {
+ logger.error("", e);
+ }
+ }
+ }
+
+ static class SmartReloadSchedulerThreadFactory implements ThreadFactory {
+
+ private static final AtomicInteger poolNumber = new AtomicInteger(1);
+
+ private final ThreadGroup group;
+
+ private final AtomicInteger threadNumber = new AtomicInteger(1);
+
+ private final String namePrefix;
+
+ SmartReloadSchedulerThreadFactory() {
+ SecurityManager s = System.getSecurityManager();
+ group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
+ namePrefix = "smartreload-" + poolNumber.getAndIncrement() + "-thread-";
+ }
+
+ @Override
+ public Thread newThread(Runnable r) {
+ Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0);
+ if (t.isDaemon())
+ t.setDaemon(false);
+ if (t.getPriority() != Thread.NORM_PRIORITY)
+ t.setPriority(Thread.NORM_PRIORITY);
+ return t;
+ }
+ }
+
+}
diff --git a/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/reload/abstracts/AbstractSmartReloadCommand.java b/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/reload/abstracts/AbstractSmartReloadCommand.java
new file mode 100644
index 00000000..b5b90aac
--- /dev/null
+++ b/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/reload/abstracts/AbstractSmartReloadCommand.java
@@ -0,0 +1,66 @@
+package com.gangquan360.smartadmin.common.reload.abstracts;
+
+import com.gangquan360.smartadmin.common.reload.SmartReloadManager;
+import com.gangquan360.smartadmin.common.reload.domain.entity.ReloadItem;
+import com.gangquan360.smartadmin.common.reload.interfaces.SmartReloadCommandInterface;
+
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * 检测是否 Reload 的类
+ *
+ * @author zhuoda
+ */
+public abstract class AbstractSmartReloadCommand implements SmartReloadCommandInterface {
+
+ /**
+ * 当前ReloadItem的存储器
+ */
+ private ConcurrentHashMap currentTags = null;
+
+ /**
+ * Reload的执行类
+ */
+ private SmartReloadManager reloadManager;
+
+ public AbstractSmartReloadCommand(SmartReloadManager reloadManager) {
+ this.reloadManager = reloadManager;
+ this.currentTags = new ConcurrentHashMap<>();
+ // 初始获取ReloadItem数据
+ List readTagStatesFromDb = readReloadItem();
+ if (readTagStatesFromDb != null) {
+ for (ReloadItem reloadItem : readTagStatesFromDb) {
+ String tag = reloadItem.getTag();
+ String tagChangeIdentifier = reloadItem.getIdentification();
+ this.currentTags.put(tag, tagChangeIdentifier);
+ }
+ }
+ }
+ /**
+ * 任务:
+ * 读取数据库中 ReloadItem 数据
+ * 校验是否发生变化
+ * 执行重加载动作
+ */
+ @Override
+ public void doTask() {
+ // 获取数据库数据
+ List readTagStatesFromDb = readReloadItem();
+ String tag;
+ String tagIdentifier;
+ String preTagChangeIdentifier;
+ for (ReloadItem reloadItem : readTagStatesFromDb) {
+ tag = reloadItem.getTag();
+ tagIdentifier = reloadItem.getIdentification();
+ preTagChangeIdentifier = currentTags.get(tag);
+ // 数据不一致
+ if (preTagChangeIdentifier == null || ! preTagChangeIdentifier.equals(tagIdentifier)) {
+ // 更新map数据
+ currentTags.put(tag, tagIdentifier);
+ // 执行重新加载此项的动作
+ handleReloadResult(this.reloadManager.doReload(reloadItem));
+ }
+ }
+ }
+}
diff --git a/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/reload/abstracts/AbstractSmartReloadCommand4Spring.java b/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/reload/abstracts/AbstractSmartReloadCommand4Spring.java
new file mode 100644
index 00000000..4b550591
--- /dev/null
+++ b/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/reload/abstracts/AbstractSmartReloadCommand4Spring.java
@@ -0,0 +1,68 @@
+package com.gangquan360.smartadmin.common.reload.abstracts;
+
+import com.gangquan360.smartadmin.common.reload.SmartReloadManager;
+import com.gangquan360.smartadmin.common.reload.domain.entity.ReloadItem;
+import com.gangquan360.smartadmin.common.reload.interfaces.SmartReloadCommandInterface;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import javax.annotation.PostConstruct;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * 检测是否 Reload 的类
+ *
+ * @author zhuoda
+ */
+public abstract class AbstractSmartReloadCommand4Spring implements SmartReloadCommandInterface {
+
+ /**
+ * 当前ReloadItem的存储器
+ */
+ protected ConcurrentHashMap currentTags = new ConcurrentHashMap<>();
+
+ /**
+ * Reload的执行类
+ */
+ @Autowired
+ protected SmartReloadManager reloadManager;
+
+// @PostConstruct
+ public void init() {
+ List readTagStatesFromDb = readReloadItem();
+ if (readTagStatesFromDb != null) {
+ for (ReloadItem reloadItem : readTagStatesFromDb) {
+ String tag = reloadItem.getTag();
+ String tagChangeIdentifier = reloadItem.getIdentification();
+ this.currentTags.put(tag, tagChangeIdentifier);
+ }
+ }
+ }
+
+ /**
+ * 任务:
+ * 读取数据库中 ReloadItem 数据
+ * 校验是否发生变化
+ * 执行重加载动作
+ */
+ @Override
+ public void doTask() {
+ // 获取数据库数据
+ List readTagStatesFromDb = readReloadItem();
+ String tag;
+ String tagIdentifier;
+ String preTagChangeIdentifier;
+ for (ReloadItem reloadItem : readTagStatesFromDb) {
+ tag = reloadItem.getTag();
+ tagIdentifier = reloadItem.getIdentification();
+ preTagChangeIdentifier = currentTags.get(tag);
+ // 数据不一致
+ if (preTagChangeIdentifier == null || ! preTagChangeIdentifier.equals(tagIdentifier)) {
+ // 更新map数据
+ currentTags.put(tag, tagIdentifier);
+ // 执行重新加载此项的动作
+ handleReloadResult(this.reloadManager.doReload(reloadItem));
+ }
+ }
+ }
+}
diff --git a/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/reload/annotation/SmartReload.java b/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/reload/annotation/SmartReload.java
new file mode 100644
index 00000000..6176ae2d
--- /dev/null
+++ b/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/reload/annotation/SmartReload.java
@@ -0,0 +1,18 @@
+package com.gangquan360.smartadmin.common.reload.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 定义 SmartReload 注解
+ *
+ * @author zhuoda
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface SmartReload {
+
+ String value();
+}
diff --git a/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/reload/domain/AbstractSmartReloadObject.java b/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/reload/domain/AbstractSmartReloadObject.java
new file mode 100644
index 00000000..1f37569d
--- /dev/null
+++ b/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/reload/domain/AbstractSmartReloadObject.java
@@ -0,0 +1,31 @@
+package com.gangquan360.smartadmin.common.reload.domain;
+
+import com.gangquan360.smartadmin.common.reload.domain.entity.ReloadItem;
+import com.gangquan360.smartadmin.common.reload.domain.entity.SmartReloadResult;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+/**
+ * AbstractSmartReloadObject 处理程序的抽象类
+ *
+ * @author zhuoda
+ */
+public abstract class AbstractSmartReloadObject {
+
+ protected String getStackTrace(Throwable e) {
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw);
+ e.printStackTrace(pw);
+ return sw.toString();
+ }
+
+ /**
+ * 通过reloadItem参数reload,获得结果
+ *
+ * @param reloadItem
+ * @return boolean
+ * @author zhuokongming
+ * @date 2016年10月21日 下午2:09:44
+ */
+ public abstract SmartReloadResult reload(ReloadItem reloadItem);
+}
diff --git a/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/reload/domain/AnnotationReloadObject.java b/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/reload/domain/AnnotationReloadObject.java
new file mode 100644
index 00000000..21ea4dea
--- /dev/null
+++ b/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/reload/domain/AnnotationReloadObject.java
@@ -0,0 +1,44 @@
+package com.gangquan360.smartadmin.common.reload.domain;
+
+import com.gangquan360.smartadmin.common.reload.annotation.SmartReload;
+import com.gangquan360.smartadmin.common.reload.domain.entity.ReloadItem;
+import com.gangquan360.smartadmin.common.reload.domain.entity.SmartReloadResult;
+
+import java.lang.reflect.Method;
+
+/**
+ * Reload 处理程序的实现类
+ * 用于包装以注解 SmartReload 实现的处理类
+ *
+ * @author zhuoda
+ */
+public class AnnotationReloadObject extends AbstractSmartReloadObject {
+
+ private Object reloadObject;
+
+ private Method method;
+
+ public AnnotationReloadObject(Object reloadObject, Method method) {
+ super();
+ this.reloadObject = reloadObject;
+ this.method = method;
+ this.method.setAccessible(true);
+ }
+
+ @Override
+ public SmartReloadResult reload(ReloadItem reloadItem) {
+ SmartReloadResult result = new SmartReloadResult();
+ String tag = method.getAnnotation(SmartReload.class).value();
+ result.setTag(tag);
+ result.setArgs(reloadItem.getArgs());
+ result.setIdentification(reloadItem.getIdentification());
+ try {
+ Object invoke = method.invoke(reloadObject, reloadItem.getArgs());
+ result.setResult((Boolean) invoke);
+ } catch (Throwable e) {
+ result.setException(getStackTrace(e));
+ }
+ return result;
+ }
+
+}
diff --git a/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/reload/domain/InterfaceReloadObject.java b/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/reload/domain/InterfaceReloadObject.java
new file mode 100644
index 00000000..409aba0f
--- /dev/null
+++ b/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/reload/domain/InterfaceReloadObject.java
@@ -0,0 +1,37 @@
+package com.gangquan360.smartadmin.common.reload.domain;
+
+import com.gangquan360.smartadmin.common.reload.domain.entity.ReloadItem;
+import com.gangquan360.smartadmin.common.reload.domain.entity.SmartReloadResult;
+import com.gangquan360.smartadmin.common.reload.interfaces.SmartReloadable;
+
+/**
+ * Reload 处理程序的实现类
+ * 用于处理以接口实现的处理类
+ *
+ * @author zhuoda
+ */
+public class InterfaceReloadObject extends AbstractSmartReloadObject {
+
+ private SmartReloadable object;
+
+ public InterfaceReloadObject(SmartReloadable object) {
+ super();
+ this.object = object;
+ }
+
+ @Override
+ public SmartReloadResult reload(ReloadItem reloadItem) {
+ SmartReloadResult reloadResult = new SmartReloadResult();
+ reloadResult.setArgs(reloadItem.getArgs());
+ reloadResult.setIdentification(reloadItem.getIdentification());
+ reloadResult.setTag(reloadItem.getTag());
+ try {
+ boolean res = object.reload(reloadItem);
+ reloadResult.setResult(res);
+ } catch (Throwable e) {
+ reloadResult.setException(getStackTrace(e));
+ }
+ return reloadResult;
+ }
+
+}
diff --git a/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/reload/domain/entity/ReloadItem.java b/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/reload/domain/entity/ReloadItem.java
new file mode 100644
index 00000000..a2e9a40d
--- /dev/null
+++ b/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/reload/domain/entity/ReloadItem.java
@@ -0,0 +1,55 @@
+package com.gangquan360.smartadmin.common.reload.domain.entity;
+/**
+ * ReloadItem 类
+ *
+ * @author zhuoda
+ */
+public class ReloadItem {
+
+ /**
+ * 项名称
+ */
+ private String tag;
+
+ /**
+ * 参数
+ */
+ private String args;
+
+ /**
+ * 标识
+ */
+ private String identification;
+
+ public ReloadItem() {
+
+ }
+ public ReloadItem(String tag, String identification, String args) {
+ this.tag = tag;
+ this.identification = identification;
+ this.args = args;
+ }
+
+ public String getTag() {
+ return tag;
+ }
+ public void setTag(String tag) {
+ this.tag = tag;
+ }
+ public String getIdentification() {
+ return identification;
+ }
+ public void setIdentification(String identification) {
+ this.identification = identification;
+ }
+ public String getArgs() {
+ return args;
+ }
+ public void setArgs(String args) {
+ this.args = args;
+ }
+ @Override
+ public String toString() {
+ return "ReloadItem{" + "tag='" + tag + '\'' + ", identification='" + identification + '\'' + ", args='" + args + '\'' + '}';
+ }
+}
diff --git a/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/reload/domain/entity/SmartReloadResult.java b/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/reload/domain/entity/SmartReloadResult.java
new file mode 100644
index 00000000..a22fba47
--- /dev/null
+++ b/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/reload/domain/entity/SmartReloadResult.java
@@ -0,0 +1,102 @@
+package com.gangquan360.smartadmin.common.reload.domain.entity;
+/**
+ * t_reload_result 表 实体类
+ *
+ * @author zhuoda
+ */
+public class SmartReloadResult {
+
+ /**
+ * 项名称
+ */
+ private String tag;
+
+ /**
+ * 参数
+ */
+ private String args;
+
+ /**
+ * 标识
+ */
+ private String identification;
+
+ /**
+ * 处理结果
+ */
+ private boolean result;
+
+ /**
+ * 异常说明
+ */
+ private String exception;
+
+ public SmartReloadResult() {
+ }
+
+ public SmartReloadResult(String tag, String args, boolean result, String exception) {
+ this.tag = tag;
+ this.args = args;
+ this.result = result;
+ this.exception = exception;
+ }
+
+ public SmartReloadResult(String tag, String args, String identification, boolean result, String exception) {
+ this.tag = tag;
+ this.args = args;
+ this.identification = identification;
+ this.result = result;
+ this.exception = exception;
+ }
+
+ public void setTag(String tag) {
+ this.tag = tag;
+ }
+
+ public void setArgs(String args) {
+ this.args = args;
+ }
+
+ public void setIdentification(String identification) {
+ this.identification = identification;
+ }
+
+ public void setResult(boolean result) {
+ this.result = result;
+ }
+
+ public void setException(String exception) {
+ this.exception = exception;
+ }
+
+ public String getTag() {
+ return tag;
+ }
+
+ public String getArgs() {
+ return args;
+ }
+
+ public String getIdentification() {
+ return identification;
+ }
+
+ public boolean isResult() {
+ return result;
+ }
+
+ public String getException() {
+ return exception;
+ }
+
+ @Override
+ public String toString() {
+ return "SmartReloadResult{" +
+ "tag='" + tag + '\'' +
+ ", args='" + args + '\'' +
+ ", identification='" + identification + '\'' +
+ ", result=" + result +
+ ", exception='" + exception + '\'' +
+ '}';
+ }
+}
diff --git a/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/reload/interfaces/SmartReloadCommandInterface.java b/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/reload/interfaces/SmartReloadCommandInterface.java
new file mode 100644
index 00000000..6adbed3e
--- /dev/null
+++ b/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/reload/interfaces/SmartReloadCommandInterface.java
@@ -0,0 +1,38 @@
+package com.gangquan360.smartadmin.common.reload.interfaces;
+
+import com.gangquan360.smartadmin.common.reload.domain.entity.ReloadItem;
+import com.gangquan360.smartadmin.common.reload.domain.entity.SmartReloadResult;
+
+import java.util.List;
+
+/**
+ * 检测是否 Reload 的类
+ *
+ * @author zhuoda
+ */
+public interface SmartReloadCommandInterface {
+
+ /**
+ * 任务:
+ * 读取数据库中 ReloadItem 数据
+ * 校验是否发生变化
+ * 执行重加载动作
+ */
+ void doTask();
+
+ /**
+ * 该方法返回一个List>:
+ * ReloadItem对象的tagIdentify为:该tag的 状态(状态其实就是个字符串,如果该字符串跟上次有变化则进行reload操作)
+ * ReloadItem对象的args为: reload操作需要的参数
+ *
+ * @return List
+ */
+ List readReloadItem();
+
+ /**
+ * 处理Reload结果
+ *
+ * @param reloadResult
+ */
+ void handleReloadResult(SmartReloadResult reloadResult);
+}
diff --git a/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/reload/interfaces/SmartReloadThreadLogger.java b/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/reload/interfaces/SmartReloadThreadLogger.java
new file mode 100644
index 00000000..5db12541
--- /dev/null
+++ b/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/reload/interfaces/SmartReloadThreadLogger.java
@@ -0,0 +1,12 @@
+package com.gangquan360.smartadmin.common.reload.interfaces;
+
+/**
+ * SmartReloadThreadLogger 日志类
+ */
+public interface SmartReloadThreadLogger {
+
+ void error(String string);
+
+ void error(String string, Throwable e);
+
+}
diff --git a/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/reload/interfaces/SmartReloadable.java b/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/reload/interfaces/SmartReloadable.java
new file mode 100644
index 00000000..66122413
--- /dev/null
+++ b/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/reload/interfaces/SmartReloadable.java
@@ -0,0 +1,18 @@
+package com.gangquan360.smartadmin.common.reload.interfaces;
+
+import com.gangquan360.smartadmin.common.reload.domain.entity.ReloadItem;
+/**
+ * reload 接口
+ * 需要reload的业务实现类
+ */
+@FunctionalInterface
+public interface SmartReloadable {
+
+ /**
+ * reload
+ *
+ * @param reloadItem
+ * @return boolean
+ */
+ boolean reload(ReloadItem reloadItem);
+}
diff --git a/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/swagger/SmartSwaggerApiModelEnumPlugin.java b/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/swagger/SmartSwaggerApiModelEnumPlugin.java
new file mode 100644
index 00000000..cc863c48
--- /dev/null
+++ b/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/swagger/SmartSwaggerApiModelEnumPlugin.java
@@ -0,0 +1,91 @@
+/*
+ *
+ * Copyright 2015 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *
+ */
+
+package com.gangquan360.smartadmin.common.swagger;
+
+import com.gangquan360.smartadmin.common.anno.ApiModelPropertyEnum;
+import com.gangquan360.smartadmin.common.domain.BaseEnum;
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.core.annotation.AnnotationUtils;
+import org.springframework.core.annotation.Order;
+import org.springframework.stereotype.Component;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spi.schema.ModelPropertyBuilderPlugin;
+import springfox.documentation.spi.schema.contexts.ModelPropertyContext;
+import springfox.documentation.swagger.common.SwaggerPluginSupport;
+
+import java.lang.reflect.AnnotatedElement;
+
+import static springfox.documentation.schema.Annotations.findPropertyAnnotation;
+
+/**
+ * swagger 用于说明枚举类字段说明
+ * SWAGGER_PLUGIN_ORDER+1 是将此配置放在原来的后面执行
+ *
+ * @author listen
+ * @date 2019年5月16日 15:36:56
+ */
+public class SmartSwaggerApiModelEnumPlugin implements ModelPropertyBuilderPlugin {
+
+ @Override
+ public void apply(ModelPropertyContext context) {
+ Optional annotation = Optional.absent();
+
+ if (context.getAnnotatedElement().isPresent()) {
+ annotation = annotation.or(findApiModePropertyAnnotation(context.getAnnotatedElement().get()));
+ }
+ if (context.getBeanPropertyDefinition().isPresent()) {
+ annotation = annotation.or(findPropertyAnnotation(context.getBeanPropertyDefinition().get(), ApiModelPropertyEnum.class));
+ }
+
+ if (annotation.isPresent()) {
+ Class extends BaseEnum> aClass = annotation.get().value();
+ String enumInfo = BaseEnum.getInfo(aClass);
+ String enumDesc = annotation.get().enumDesc();
+ context.getBuilder().required(annotation.transform(toIsRequired()).or(false))
+ .description(enumDesc +":"+enumInfo)
+ .example(annotation.transform(toExample()).orNull());
+ }
+ }
+
+ @Override
+ public boolean supports(DocumentationType delimiter) {
+ return SwaggerPluginSupport.pluginDoesApply(delimiter);
+ }
+
+ static Function toIsRequired() {
+ return annotation -> annotation.required();
+ }
+
+ public static Optional findApiModePropertyAnnotation(AnnotatedElement annotated) {
+ return Optional.fromNullable(AnnotationUtils.getAnnotation(annotated, ApiModelPropertyEnum.class));
+ }
+
+ static Function toExample() {
+ return annotation -> {
+ String example = annotation.example();
+ if (StringUtils.isBlank(example)) {
+ return "";
+ }
+ return example;
+ };
+ }
+}
diff --git a/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/validator/bigdecimal/BigDecimalValidator.java b/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/validator/bigdecimal/BigDecimalValidator.java
new file mode 100644
index 00000000..ed0a91fb
--- /dev/null
+++ b/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/validator/bigdecimal/BigDecimalValidator.java
@@ -0,0 +1,73 @@
+package com.gangquan360.smartadmin.common.validator.bigdecimal;
+
+import com.gangquan360.smartadmin.util.SmartBigDecimalUtil;
+
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorContext;
+import java.math.BigDecimal;
+
+/**
+ * BigDecimal 类校验器
+ *
+ * @author listen
+ * @date 2018年3月20日 13:51:46
+ */
+public class BigDecimalValidator implements ConstraintValidator {
+
+ /**
+ * 获取定义的数值
+ */
+ private BigDecimal value;
+
+ /**
+ * 获取比较符
+ */
+ private ComparisonSymbolEnum symbolEnum;
+
+ /**
+ * 是否必须
+ */
+ private boolean required;
+
+ @Override
+ public void initialize(CheckBigDecimal constraintAnnotation) {
+ // 初始化属性
+ value = new BigDecimal(constraintAnnotation.value());
+ symbolEnum = constraintAnnotation.symbolEnum();
+ required = constraintAnnotation.required();
+ }
+
+ @Override
+ public boolean isValid(BigDecimal decimal, ConstraintValidatorContext constraintValidatorContext) {
+
+ // 如果数值为空,校验是否必须
+ if (null == decimal) {
+ return ! required;
+ }
+
+ // 根据操作符,校验结果
+ switch (symbolEnum) {
+ // 等于
+ case EQUAL:
+ return SmartBigDecimalUtil.equals(decimal, value);
+ // 不等于
+ case NOT_EQUAL:
+ return ! SmartBigDecimalUtil.equals(decimal, value);
+ // 小于
+ case LESS_THAN:
+ return SmartBigDecimalUtil.isLessThan(decimal, value);
+ // 小于等于
+ case LESS_THAN_OR_EQUAL:
+ return SmartBigDecimalUtil.isLessThan(decimal, value) || SmartBigDecimalUtil.equals(decimal, value);
+ // 大于
+ case GREATER_THAN:
+ return SmartBigDecimalUtil.isGreaterThan(decimal, value);
+ // 大于等于
+ case GREATER_THAN_OR_EQUAL:
+ return SmartBigDecimalUtil.isGreaterThan(decimal, value) || SmartBigDecimalUtil.equals(decimal, value);
+ default:
+ }
+
+ return false;
+ }
+}
diff --git a/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/validator/bigdecimal/CheckBigDecimal.java b/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/validator/bigdecimal/CheckBigDecimal.java
new file mode 100644
index 00000000..a005fd8b
--- /dev/null
+++ b/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/validator/bigdecimal/CheckBigDecimal.java
@@ -0,0 +1,53 @@
+package com.gangquan360.smartadmin.common.validator.bigdecimal;
+
+import javax.validation.Constraint;
+import javax.validation.Payload;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 自定义的属性校验注解
+ *
+ * @author listen
+ * @date 2018年3月20日 13:53:33
+ */
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+@Constraint(validatedBy = BigDecimalValidator.class)// 自定义验证的处理类
+public @interface CheckBigDecimal {
+
+ /**
+ * 与这个数值校验
+ *
+ * @return
+ */
+ String value();
+
+ /**
+ * 比较符 请使用 ComparisonSymbolEnum 枚举类
+ *
+ * @return
+ */
+ ComparisonSymbolEnum symbolEnum();
+
+ /**
+ * 默认的错误提示信息
+ *
+ * @return String
+ */
+ String message() default "非法的数值";
+
+ /**
+ * 是否必须 : 默认 true
+ *
+ * @return boolean
+ */
+ boolean required() default true;
+
+ //下面这两个属性必须添加 :不然会报错
+ Class>[] groups() default {};
+
+ Class extends Payload>[] payload() default {};
+}
diff --git a/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/validator/bigdecimal/ComparisonSymbolEnum.java b/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/validator/bigdecimal/ComparisonSymbolEnum.java
new file mode 100644
index 00000000..f25948cc
--- /dev/null
+++ b/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/validator/bigdecimal/ComparisonSymbolEnum.java
@@ -0,0 +1,40 @@
+package com.gangquan360.smartadmin.common.validator.bigdecimal;
+
+/**
+ * 比较符枚举类
+ *
+ * @author listen
+ * @date 2018/03/20 14:01
+ */
+public enum ComparisonSymbolEnum {
+
+ /**
+ * 等于
+ */
+ EQUAL,
+
+ /**
+ * 不等于
+ */
+ NOT_EQUAL,
+
+ /**
+ * 小于
+ */
+ LESS_THAN,
+
+ /**
+ * 小于等于
+ */
+ LESS_THAN_OR_EQUAL,
+
+ /**
+ * 大于
+ */
+ GREATER_THAN,
+
+ /**
+ * 大于等于
+ */
+ GREATER_THAN_OR_EQUAL,
+}
diff --git a/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/validator/en/CheckEnum.java b/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/validator/en/CheckEnum.java
new file mode 100644
index 00000000..662dc7ed
--- /dev/null
+++ b/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/validator/en/CheckEnum.java
@@ -0,0 +1,51 @@
+package com.gangquan360.smartadmin.common.validator.en;
+
+
+import com.gangquan360.smartadmin.common.domain.BaseEnum;
+import com.gangquan360.smartadmin.common.validator.en.EnumValidator;
+
+import javax.validation.Constraint;
+import javax.validation.Payload;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 自定义的属性校验注解
+ * 为了方便与校验属性的值是否为合法的枚举值
+ *
+ * @author listen
+ * @date 2017/11/11 15:31
+ */
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+@Constraint(validatedBy = EnumValidator.class)// 自定义验证的处理类
+public @interface CheckEnum {
+
+ /**
+ * 默认的错误提示信息
+ *
+ * @return String
+ */
+ String message() default "非法的枚举值";
+
+ /**
+ * 枚举类对象 必须实现BaseEnum接口
+ *
+ * @return
+ */
+ Class extends BaseEnum> enumClazz();
+
+ /**
+ * 是否必须
+ *
+ * @return boolean
+ */
+ boolean required() default false;
+
+ //下面这两个属性必须添加 :不然会报错
+ Class>[] groups() default {};
+
+ Class extends Payload>[] payload() default {};
+}
diff --git a/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/validator/en/EnumValidator.java b/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/validator/en/EnumValidator.java
new file mode 100644
index 00000000..8cb3004d
--- /dev/null
+++ b/java/smart-admin-api/src/main/java/com/gangquan360/smartadmin/common/validator/en/EnumValidator.java
@@ -0,0 +1,80 @@
+package com.gangquan360.smartadmin.common.validator.en;
+
+import com.gangquan360.smartadmin.common.domain.BaseEnum;
+
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorContext;
+import java.util.List;
+
+/**
+ * 枚举类校验器
+ *
+ * @author listen
+ * @date 2017/11/11 15:34
+ */
+public class EnumValidator implements ConstraintValidator {
+
+ /**
+ * 枚举类的类对象
+ */
+ private Class extends BaseEnum> enumClass;
+
+ /**
+ * 是否必须
+ */
+ private boolean required;
+
+ @Override
+ public void initialize(CheckEnum constraintAnnotation) {
+ // 获取注解传入的枚举类对象
+ enumClass = constraintAnnotation.enumClazz();
+ required = constraintAnnotation.required();
+ }
+
+ @Override
+ public boolean isValid(Object value, ConstraintValidatorContext constraintValidatorContext) {
+ // 判断是否必须
+ if (null == value) {
+ return !required;
+ }
+
+ if (value instanceof List) {
+ // 如果为 List 集合数据
+ return this.checkList((List