This commit is contained in:
yandanyang 2021-09-24 20:23:29 +08:00
parent f417c8a032
commit eee13c36ea
24 changed files with 786 additions and 89 deletions

View File

@ -33,24 +33,25 @@ public class SmartSecurityMetadataSource extends PrePostAnnotationSecurityMetada
private final PrePostInvocationAttributeFactory attributeFactory; private final PrePostInvocationAttributeFactory attributeFactory;
private String projectModule;
private List<String> noValidUrlList; private List<String> noValidUrlList;
public SmartSecurityMetadataSource(PrePostInvocationAttributeFactory attributeFactory, List<String> noValidUrlList, String projectModule) { public SmartSecurityMetadataSource(PrePostInvocationAttributeFactory attributeFactory, List<String> noValidUrlList) {
super(attributeFactory); super(attributeFactory);
this.attributeFactory = attributeFactory; this.attributeFactory = attributeFactory;
this.projectModule = projectModule;
this.noValidUrlList = noValidUrlList; this.noValidUrlList = noValidUrlList;
} }
@Override @Override
public Collection<ConfigAttribute> getAttributes(Method method, Class<?> targetClass) { public Collection<ConfigAttribute> getAttributes(Method method, Class<?> targetClass) {
//只对固定的包的所有接口进行控制 //自己的控制
if (!targetClass.getName().startsWith(projectModule)) { GetMapping getMapping = method.getAnnotation(GetMapping.class);
PostMapping postMapping = method.getAnnotation(PostMapping.class);
RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);
if (getMapping == null && postMapping == null && requestMapping == null) {
return super.getAttributes(method, targetClass); return super.getAttributes(method, targetClass);
} }
//是否需要权限 //是否需要权限
NoValidPrivilege methodNoValidPrivilege = method.getAnnotation(NoValidPrivilege.class); NoValidPrivilege methodNoValidPrivilege = method.getAnnotation(NoValidPrivilege.class);
if (methodNoValidPrivilege != null) { if (methodNoValidPrivilege != null) {
@ -69,13 +70,6 @@ public class SmartSecurityMetadataSource extends PrePostAnnotationSecurityMetada
if (postAuthorize != null) { if (postAuthorize != null) {
return super.getAttributes(method, targetClass); return super.getAttributes(method, targetClass);
} }
//自己的控制
GetMapping getMapping = method.getAnnotation(GetMapping.class);
PostMapping postMapping = method.getAnnotation(PostMapping.class);
RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);
if (getMapping == null && postMapping == null && requestMapping == null) {
return super.getAttributes(method, targetClass);
}
//获取注解值 //获取注解值
String uriPrefix = SmartSecurityUrl.getUriPrefix(method); String uriPrefix = SmartSecurityUrl.getUriPrefix(method);
List<String> annotationValueList = SmartSecurityUrl.getAnnotationValueList(method, uriPrefix); List<String> annotationValueList = SmartSecurityUrl.getAnnotationValueList(method, uriPrefix);

View File

@ -7,7 +7,12 @@ import org.reflections.Reflections;
import org.reflections.scanners.MethodAnnotationsScanner; import org.reflections.scanners.MethodAnnotationsScanner;
import org.reflections.scanners.TypeAnnotationsScanner; import org.reflections.scanners.TypeAnnotationsScanner;
import org.reflections.util.ConfigurationBuilder; import org.reflections.util.ConfigurationBuilder;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.ReflectionUtils;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -19,7 +24,7 @@ import java.util.Set;
* @author 罗伊 * @author 罗伊
* @date 2021/8/31 10:20 * @date 2021/8/31 10:20
*/ */
public class SmartSecurityUrlMatchers { public class SmartSecurityUrlMatchers implements BeanPostProcessor {
/** /**
* 匿名访问URL * 匿名访问URL
@ -42,7 +47,7 @@ public class SmartSecurityUrlMatchers {
IGNORE_URL.add("/swagger-resources/**"); IGNORE_URL.add("/swagger-resources/**");
IGNORE_URL.add("/webjars/**"); IGNORE_URL.add("/webjars/**");
IGNORE_URL.add("/*/api-docs"); IGNORE_URL.add("/*/api-docs");
IGNORE_URL.add(CommonConst.ApiUrl.API_PREFIX_SUPPORT +"/**"); IGNORE_URL.add(CommonConst.ApiUrl.API_PREFIX_SUPPORT + "/**");
AUTHENTICATED_URL = new ArrayList<>(); AUTHENTICATED_URL = new ArrayList<>();
AUTHENTICATED_URL.add("/admin/**"); AUTHENTICATED_URL.add("/admin/**");
@ -50,14 +55,14 @@ public class SmartSecurityUrlMatchers {
/** /**
* 构造函数 * 构造函数
* @param scanPath 需要扫描的类路径 *
*/ */
public SmartSecurityUrlMatchers(String scanPath){ public SmartSecurityUrlMatchers() {
this.ANONYMOUS_URL = this.initAnonymousUrlList(scanPath);
} }
/** /**
* 获取忽略的URL集合 * 获取忽略的URL集合
*
* @return * @return
*/ */
public List<String> getIgnoreUrlList() { public List<String> getIgnoreUrlList() {
@ -66,6 +71,7 @@ public class SmartSecurityUrlMatchers {
/** /**
* 获取需要匿名访问的url集合 * 获取需要匿名访问的url集合
*
* @return * @return
*/ */
public List<String> getAnonymousUrlList() { public List<String> getAnonymousUrlList() {
@ -74,6 +80,7 @@ public class SmartSecurityUrlMatchers {
/** /**
* 获取需要认证的url集合 * 获取需要认证的url集合
*
* @return * @return
*/ */
public List<String> getAuthenticatedUrlList() { public List<String> getAuthenticatedUrlList() {
@ -82,6 +89,7 @@ public class SmartSecurityUrlMatchers {
/** /**
* 不需要权限校验的 * 不需要权限校验的
*
* @return * @return
*/ */
public List<String> getNoValidUrlList() { public List<String> getNoValidUrlList() {
@ -93,60 +101,52 @@ public class SmartSecurityUrlMatchers {
/** /**
* 获取需要忽略的url集合 * 获取需要忽略的url集合
*
* @return * @return
*/ */
public String [] getIgnoreUrlArray() { public String[] getIgnoreUrlArray() {
String [] ignoreUrlArray = IGNORE_URL.toArray(new String[IGNORE_URL.size()]); String[] ignoreUrlArray = IGNORE_URL.toArray(new String[IGNORE_URL.size()]);
return ignoreUrlArray; return ignoreUrlArray;
} }
/** /**
* 获取需要匿名访问的url集合 * 获取需要匿名访问的url集合
*
* @return * @return
*/ */
public String [] getAnonymousUrlArray() { public String[] getAnonymousUrlArray() {
String [] anonymousUrlArray = ANONYMOUS_URL.toArray(new String[ANONYMOUS_URL.size()]); String[] anonymousUrlArray = ANONYMOUS_URL.toArray(new String[ANONYMOUS_URL.size()]);
return anonymousUrlArray; return anonymousUrlArray;
} }
/** /**
* 获取需要认证的url集合 * 获取需要认证的url集合
*
* @return * @return
*/ */
public String [] getAuthenticatedUrlArray() { public String[] getAuthenticatedUrlArray() {
String [] anonymousUrlArray = AUTHENTICATED_URL.toArray(new String[AUTHENTICATED_URL.size()]); String[] anonymousUrlArray = AUTHENTICATED_URL.toArray(new String[AUTHENTICATED_URL.size()]);
return anonymousUrlArray; return anonymousUrlArray;
} }
/** @Override
* 获取无需登录可以匿名访问的url信息 public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
* Method[] methods = ReflectionUtils.getAllDeclaredMethods(bean.getClass());
* @return if (methods == null) {
*/ return bean;
private List<String> initAnonymousUrlList(String scanPath) {
List<String> anonymousUrlList = Lists.newArrayList();
//添加无需登录注解的uri
Reflections reflections = new Reflections(new ConfigurationBuilder().forPackages(scanPath).addScanners(new MethodAnnotationsScanner(), new TypeAnnotationsScanner()));
Set<Method> methodSet = reflections.getMethodsAnnotatedWith(NoNeedLogin.class);
Set<Class<?>> classSet = reflections.getTypesAnnotatedWith(NoNeedLogin.class);
//方法级别无需登录
for (Method method : methodSet) {
String uriPrefix = SmartSecurityUrl.getUriPrefix(method);
List<String> valueList = SmartSecurityUrl.getAnnotationValueList(method, uriPrefix);
anonymousUrlList.addAll(valueList);
} }
//级别无需登录 //方法级别无需登录
for (Class clazz : classSet) { for (Method method : methods) {
Method[] methods = clazz.getMethods(); NoNeedLogin noNeedLogin = method.getAnnotation(NoNeedLogin.class);
for (Method method : methods) { if(noNeedLogin != null){
String uriPrefix = SmartSecurityUrl.getUriPrefix(method); String uriPrefix = SmartSecurityUrl.getUriPrefix(method);
List<String> valueList = SmartSecurityUrl.getAnnotationValueList(method, uriPrefix); List<String> valueList = SmartSecurityUrl.getAnnotationValueList(method, uriPrefix);
anonymousUrlList.addAll(valueList); this.ANONYMOUS_URL.addAll(valueList);
} }
} }
return anonymousUrlList; return bean;
} }
} }

View File

@ -16,16 +16,6 @@ import java.util.Map;
@Configuration @Configuration
public class AdminWebAppConfig implements WebMvcConfigurer { public class AdminWebAppConfig implements WebMvcConfigurer {
@Autowired
private Map<String, HandlerInterceptor> interceptorMap;
@Override
public void addInterceptors(InterceptorRegistry registry) {
for(Map.Entry<String, HandlerInterceptor> entry : interceptorMap.entrySet()){
registry.addInterceptor(entry.getValue()).addPathPatterns(entry.getKey() + "/**");
}
}
@Override @Override
public void addViewControllers(ViewControllerRegistry registry) { public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/druidMonitor").setViewName("redirect:druid/index.html"); registry.addViewController("/druidMonitor").setViewName("redirect:druid/index.html");

View File

@ -42,6 +42,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
*/ */
@Autowired @Autowired
private EmployeeLoginTokenService loginTokenService; private EmployeeLoginTokenService loginTokenService;
/** /**
* 跨域配置 * 跨域配置
* *

View File

@ -18,9 +18,6 @@ import org.springframework.security.config.annotation.method.configuration.Globa
@EnableGlobalMethodSecurity(prePostEnabled = true) @EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityMethodConfig extends GlobalMethodSecurityConfiguration { public class SecurityMethodConfig extends GlobalMethodSecurityConfiguration {
@Value("${project.module}")
private String projectModule;
/** /**
* 无需登录的url * 无需登录的url
*/ */
@ -30,6 +27,6 @@ public class SecurityMethodConfig extends GlobalMethodSecurityConfiguration {
@Override @Override
public MethodSecurityMetadataSource customMethodSecurityMetadataSource(){ public MethodSecurityMetadataSource customMethodSecurityMetadataSource(){
ExpressionBasedAnnotationAttributeFactory attributeFactory = new ExpressionBasedAnnotationAttributeFactory(this.getExpressionHandler()); ExpressionBasedAnnotationAttributeFactory attributeFactory = new ExpressionBasedAnnotationAttributeFactory(this.getExpressionHandler());
return new SmartSecurityMetadataSource(attributeFactory, smartSecurityUrlMatchers.getNoValidUrlList(),projectModule); return new SmartSecurityMetadataSource(attributeFactory, smartSecurityUrlMatchers.getNoValidUrlList());
} }
} }

View File

@ -14,11 +14,8 @@ import org.springframework.context.annotation.Configuration;
@Configuration @Configuration
public class SecurityUrlConfig { public class SecurityUrlConfig {
@Value("${project.module}")
private String projectModule;
@Bean @Bean
public SmartSecurityUrlMatchers securityUrl() { public SmartSecurityUrlMatchers securityUrl() {
return new SmartSecurityUrlMatchers(projectModule); return new SmartSecurityUrlMatchers();
} }
} }

View File

@ -4,6 +4,7 @@ import lombok.extern.slf4j.Slf4j;
import net.lab1024.smartadmin.service.common.codeconst.ResponseCodeConst; import net.lab1024.smartadmin.service.common.codeconst.ResponseCodeConst;
import net.lab1024.smartadmin.service.common.constant.SystemEnvironmentEnum; import net.lab1024.smartadmin.service.common.constant.SystemEnvironmentEnum;
import net.lab1024.smartadmin.service.common.domain.ResponseDTO; import net.lab1024.smartadmin.service.common.domain.ResponseDTO;
import net.lab1024.smartadmin.service.common.domain.SystemEnvironmentBO;
import net.lab1024.smartadmin.service.common.exception.SmartBusinessException; import net.lab1024.smartadmin.service.common.exception.SmartBusinessException;
import org.springframework.beans.TypeMismatchException; import org.springframework.beans.TypeMismatchException;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -34,7 +35,7 @@ import java.util.stream.Collectors;
public class SmartGlobalExceptionHandler { public class SmartGlobalExceptionHandler {
@Autowired @Autowired
private SystemEnvironmentEnum systemEnvironmentEnum; private SystemEnvironmentBO systemEnvironmentBO;
/** /**
* 添加全局异常处理流程 * 添加全局异常处理流程
@ -95,7 +96,8 @@ public class SmartGlobalExceptionHandler {
log.error("捕获全局异常,URL:{}", uri, e); log.error("捕获全局异常,URL:{}", uri, e);
// 正式环境 不返回错误信息 // 正式环境 不返回错误信息
if (SystemEnvironmentEnum.PROD == systemEnvironmentEnum) { SystemEnvironmentEnum currentEnvironment = systemEnvironmentBO.getCurrentEnvironment();
if (SystemEnvironmentEnum.PROD == currentEnvironment) {
return ResponseDTO.wrap(ResponseCodeConst.SYSTEM_ERROR); return ResponseDTO.wrap(ResponseCodeConst.SYSTEM_ERROR);
} }

View File

@ -0,0 +1,134 @@
package net.lab1024.smartadmin.service.module.support.reload;
import net.lab1024.smartadmin.service.module.support.reload.annotation.SmartReload;
import net.lab1024.smartadmin.service.module.support.reload.domain.AbstractSmartReloadObject;
import net.lab1024.smartadmin.service.module.support.reload.domain.AnnotationReloadObject;
import net.lab1024.smartadmin.service.module.support.reload.domain.InterfaceReloadObject;
import net.lab1024.smartadmin.service.module.support.reload.domain.entity.ReloadItem;
import net.lab1024.smartadmin.service.module.support.reload.domain.entity.SmartReloadResult;
import net.lab1024.smartadmin.service.module.support.reload.interfaces.SmartReloadCommandInterface;
import net.lab1024.smartadmin.service.module.support.reload.interfaces.SmartReloadThreadLogger;
import net.lab1024.smartadmin.service.module.support.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 管理器
* <p>
* 可以在此类中添加 检测任务 以及注册 处理程序
*
* @author zhuoda
*/
public class SmartReloadManager {
private Map<String, AbstractSmartReloadObject> 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("<<SmartReloadManager>> 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("<<SmartReloadManager>> 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");
}
}

View File

@ -0,0 +1,91 @@
package net.lab1024.smartadmin.service.module.support.reload;
import net.lab1024.smartadmin.service.module.support.reload.interfaces.SmartReloadCommandInterface;
import net.lab1024.smartadmin.service.module.support.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("<<SmartReloadScheduler>> 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 = "smart-reload-" + 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;
}
}
}

View File

@ -0,0 +1,66 @@
package net.lab1024.smartadmin.service.module.support.reload.abstracts;
import net.lab1024.smartadmin.service.module.support.reload.SmartReloadManager;
import net.lab1024.smartadmin.service.module.support.reload.domain.entity.ReloadItem;
import net.lab1024.smartadmin.service.module.support.reload.interfaces.SmartReloadCommandInterface;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
/**
* 检测是否 Reload 的类
*
* @author zhuoda
*/
public abstract class AbstractSmartReloadCommand implements SmartReloadCommandInterface {
/**
* 当前ReloadItem的存储器
*/
private ConcurrentHashMap<String, String> currentTags = null;
/**
* Reload的执行类
*/
private SmartReloadManager reloadManager;
public AbstractSmartReloadCommand(SmartReloadManager reloadManager) {
this.reloadManager = reloadManager;
this.currentTags = new ConcurrentHashMap<>();
// 初始获取ReloadItem数据
List<ReloadItem> 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<ReloadItem> 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));
}
}
}
}

View File

@ -0,0 +1,65 @@
package net.lab1024.smartadmin.service.module.support.reload.abstracts;
import net.lab1024.smartadmin.service.module.support.reload.SmartReloadManager;
import net.lab1024.smartadmin.service.module.support.reload.domain.entity.ReloadItem;
import net.lab1024.smartadmin.service.module.support.reload.interfaces.SmartReloadCommandInterface;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
/**
* 检测是否 Reload 的类
*
* @author zhuoda
*/
public abstract class AbstractSmartReloadCommand4Spring implements SmartReloadCommandInterface {
/**
* 当前ReloadItem的存储器
*/
protected ConcurrentHashMap<String, String> currentTags = new ConcurrentHashMap<>();
/**
* Reload的执行类
*/
@Autowired
protected SmartReloadManager reloadManager;
public void init() {
List<ReloadItem> 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<ReloadItem> 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));
}
}
}
}

View File

@ -0,0 +1,18 @@
package net.lab1024.smartadmin.service.module.support.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();
}

View File

@ -0,0 +1,32 @@
package net.lab1024.smartadmin.service.module.support.reload.domain;
import net.lab1024.smartadmin.service.module.support.reload.domain.entity.ReloadItem;
import net.lab1024.smartadmin.service.module.support.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);
}

View File

@ -0,0 +1,57 @@
package net.lab1024.smartadmin.service.module.support.reload.domain;
import net.lab1024.smartadmin.service.module.support.reload.annotation.SmartReload;
import net.lab1024.smartadmin.service.module.support.reload.domain.entity.ReloadItem;
import net.lab1024.smartadmin.service.module.support.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 = ((SmartReload)this.method.getAnnotation(SmartReload.class)).value();
result.setTag(tag);
result.setArgs(reloadItem.getArgs());
result.setIdentification(reloadItem.getIdentification());
result.setResult(true);
int paramCount = this.method.getParameterCount();
if (paramCount > 1) {
result.setResult(false);
result.setException("reload方法" + this.method.getName() + "参数太多");
return result;
} else {
try {
if (paramCount == 0) {
this.method.invoke(this.reloadObject);
} else {
this.method.invoke(this.reloadObject, reloadItem.getArgs());
}
} catch (Throwable var6) {
result.setResult(false);
result.setException(this.getStackTrace(var6));
}
return result;
}
}
}

View File

@ -0,0 +1,37 @@
package net.lab1024.smartadmin.service.module.support.reload.domain;
import net.lab1024.smartadmin.service.module.support.reload.domain.entity.ReloadItem;
import net.lab1024.smartadmin.service.module.support.reload.domain.entity.SmartReloadResult;
import net.lab1024.smartadmin.service.module.support.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;
}
}

View File

@ -0,0 +1,55 @@
package net.lab1024.smartadmin.service.module.support.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 + '\'' + '}';
}
}

View File

@ -0,0 +1,102 @@
package net.lab1024.smartadmin.service.module.support.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 + '\'' +
'}';
}
}

View File

@ -0,0 +1,39 @@
package net.lab1024.smartadmin.service.module.support.reload.interfaces;
import net.lab1024.smartadmin.service.module.support.reload.domain.entity.ReloadItem;
import net.lab1024.smartadmin.service.module.support.reload.domain.entity.SmartReloadResult;
import java.util.List;
/**
* 检测是否 Reload 的类
*
* @author zhuoda
*/
public interface SmartReloadCommandInterface {
/**
* 任务
* 读取数据库中 ReloadItem 数据
* 校验是否发生变化
* 执行重加载动作
*/
void doTask();
/**
* 该方法返回一个List<ReloadItem></>:<br>
* ReloadItem对象的tagIdentify为该tag的 状态状态其实就是个字符串如果该字符串跟上次有变化则进行reload操作<br>
* ReloadItem对象的args为 reload操作需要的参数<br><br>
*
* @return List<ReloadItem>
*/
List<ReloadItem> readReloadItem();
/**
* 处理Reload结果
*
* @param reloadResult
*/
void handleReloadResult(SmartReloadResult reloadResult);
}

View File

@ -0,0 +1,12 @@
package net.lab1024.smartadmin.service.module.support.reload.interfaces;
/**
* SmartReloadThreadLogger 日志类
*/
public interface SmartReloadThreadLogger {
void error(String string);
void error(String string, Throwable e);
}

View File

@ -0,0 +1,19 @@
package net.lab1024.smartadmin.service.module.support.reload.interfaces;
import net.lab1024.smartadmin.service.module.support.reload.domain.entity.ReloadItem;
/**
* reload 接口<br>
* 需要reload的业务实现类
*/
@FunctionalInterface
public interface SmartReloadable {
/**
* reload
*
* @param reloadItem
* @return boolean
*/
boolean reload(ReloadItem reloadItem);
}

View File

@ -24,7 +24,6 @@ import java.util.function.Function;
* @date * @date
*/ */
@Aspect @Aspect
@Order(1)
public class SmartRepeatSubmitAspect { public class SmartRepeatSubmitAspect {
/** /**

View File

@ -5,6 +5,7 @@ import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm; import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.lab1024.smartadmin.service.common.constant.SystemEnvironmentEnum; import net.lab1024.smartadmin.service.common.constant.SystemEnvironmentEnum;
import net.lab1024.smartadmin.service.common.domain.SystemEnvironmentBO;
import net.lab1024.smartadmin.service.module.system.employee.EmployeeService; import net.lab1024.smartadmin.service.module.system.employee.EmployeeService;
import net.lab1024.smartadmin.service.module.system.login.domain.EmployeeLoginBO; import net.lab1024.smartadmin.service.module.system.login.domain.EmployeeLoginBO;
import net.lab1024.smartadmin.service.module.system.login.domain.EmployeeLoginInfoDTO; import net.lab1024.smartadmin.service.module.system.login.domain.EmployeeLoginInfoDTO;
@ -42,7 +43,7 @@ public class EmployeeLoginTokenService {
private EmployeeService employeeService; private EmployeeService employeeService;
@Autowired @Autowired
private SystemEnvironmentEnum systemEnvironment; private SystemEnvironmentBO systemEnvironmentBO;
/** /**
* 生成 JWT TOKEN * 生成 JWT TOKEN
@ -74,7 +75,8 @@ public class EmployeeLoginTokenService {
* 非生产环境 直接使用 token 作为id * 非生产环境 直接使用 token 作为id
* 不需要的话 注释了吧 * 不需要的话 注释了吧
*/ */
if (SystemEnvironmentEnum.PROD != systemEnvironment && NumberUtils.isParsable(token)) { SystemEnvironmentEnum currentEnvironment = systemEnvironmentBO.getCurrentEnvironment();
if (SystemEnvironmentEnum.PROD != currentEnvironment && NumberUtils.isParsable(token)) {
return employeeService.getById(Long.parseLong(token)); return employeeService.getById(Long.parseLong(token));
} }
@ -104,7 +106,8 @@ public class EmployeeLoginTokenService {
* 非生产环境 直接使用 token 作为id * 非生产环境 直接使用 token 作为id
* 不需要的话 注释了吧 * 不需要的话 注释了吧
*/ */
if (SystemEnvironmentEnum.PROD != systemEnvironment && NumberUtils.isParsable(token)) { SystemEnvironmentEnum currentEnvironment = systemEnvironmentBO.getCurrentEnvironment();
if (SystemEnvironmentEnum.PROD != currentEnvironment && NumberUtils.isParsable(token)) {
return employeeService.getBoById(Long.parseLong(token)); return employeeService.getBoById(Long.parseLong(token));
} }

View File

@ -3,8 +3,6 @@ package net.lab1024.smartadmin.service.third;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import net.lab1024.smartadmin.service.module.support.redismq.RedisMqTopicEnum;
import net.lab1024.smartadmin.service.module.support.redismq.RedisMsgDTO;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.*; import org.springframework.data.redis.core.*;
@ -707,15 +705,4 @@ public class SmartRedisService {
} }
} }
/**
* 发送redis消息
*
* @param topicEnum
* @param msgType
* @param jsonData
*/
public void sendMsg(RedisMqTopicEnum topicEnum, Integer msgType, String jsonData) {
RedisMsgDTO redisMsgDTO = new RedisMsgDTO(msgType, jsonData);
stringRedisTemplate.convertAndSend(topicEnum.getValue(), JSONObject.toJSONString(redisMsgDTO));
}
} }

View File

@ -22,9 +22,9 @@ spring.jackson.time-zone=GMT+8
spring.jackson.serialization.write-dates-as-timestamps=false spring.jackson.serialization.write-dates-as-timestamps=false
######################### database ######################### ######################### database #########################
spring.datasource.url=jdbc:p6spy:mysql://127.0.0.1:3306/smart_admin_v2?autoReconnect=true&useServerPreparedStmts=false&rewriteBatchedStatements=true&characterEncoding=UTF-8&useSSL=false&allowMultiQueries=true&serverTimezone=Asia/Shanghai spring.datasource.url=jdbc:p6spy:mysql://115.29.150.222:11024/smart_admin_v2?autoReconnect=true&useServerPreparedStmts=false&rewriteBatchedStatements=true&characterEncoding=UTF-8&useSSL=false&allowMultiQueries=true&serverTimezone=Asia/Shanghai
spring.datasource.username=root spring.datasource.username=root
spring.datasource.password=root spring.datasource.password=11024Lab
spring.datasource.initial-size=2 spring.datasource.initial-size=2
spring.datasource.min-idle=1 spring.datasource.min-idle=1
spring.datasource.max-active=10 spring.datasource.max-active=10
@ -40,14 +40,14 @@ spring.datasource.druid.service.scanner=net.lab1024.smartadmin.module..*Service.
######################### redis ####################################### ######################### redis #######################################
spring.redis.database=1 spring.redis.database=1
spring.redis.host=127.0.0.1 spring.redis.host=115.29.150.222
spring.redis.lettuce.pool.max-active=100 spring.redis.lettuce.pool.max-active=100
spring.redis.lettuce.pool.min-idle=5 spring.redis.lettuce.pool.min-idle=5
spring.redis.lettuce.pool.max-idle=10 spring.redis.lettuce.pool.max-idle=10
spring.redis.lettuce.pool.max-wait=30000ms spring.redis.lettuce.pool.max-wait=30000ms
spring.redis.port=1234 spring.redis.port=21024
spring.redis.timeout=10000ms spring.redis.timeout=10000ms
spring.redis.password=root spring.redis.password=21024Lab
######################### swagger ######################### ######################### swagger #########################
swagger.apiGroupName=smartAdmin swagger.apiGroupName=smartAdmin