Merge remote-tracking branch 'origin/dev' into satoken

# Conflicts:
#	pom.xml
#	ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysLogininforController.java
#	ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysOperlogController.java
#	ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java
#	ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java
#	ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java
#	ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictDataController.java
#	ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictTypeController.java
#	ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java
#	ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysMenuController.java
#	ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysNoticeController.java
#	ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysPostController.java
#	ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java
#	ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java
#	ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java
#	ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginUser.java
#	ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestDemoController.java
#	ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestTreeController.java
#	ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java
#	ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RepeatSubmitAspect.java
#	ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java
#	ruoyi-framework/src/main/java/com/ruoyi/framework/config/SwaggerConfig.java
#	ruoyi-framework/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java
#	ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobController.java
#	ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobLogController.java
#	ruoyi-system/src/main/java/com/ruoyi/system/service/PermissionService.java
#	ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserOnlineServiceImpl.java
#	ruoyi-system/src/main/java/com/ruoyi/system/service/impl/UserDetailsServiceImpl.java
This commit is contained in:
疯狂的狮子li
2021-11-29 13:56:25 +08:00
206 changed files with 2216 additions and 4674 deletions

View File

@ -7,6 +7,7 @@ import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.reflect.ReflectUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

View File

@ -1,13 +1,12 @@
package com.ruoyi.framework.aspectj;
import cn.dev33.satoken.SaManager;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import com.baomidou.lock.LockInfo;
import com.baomidou.lock.LockTemplate;
import com.ruoyi.common.annotation.RepeatSubmit;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.JsonUtils;
import com.ruoyi.common.utils.RedisUtils;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.config.properties.RepeatSubmitProperties;
@ -18,8 +17,14 @@ import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindingResult;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* 防止重复提交
@ -33,7 +38,6 @@ import javax.servlet.http.HttpServletRequest;
public class RepeatSubmitAspect {
private final RepeatSubmitProperties repeatSubmitProperties;
private final LockTemplate lockTemplate;
@Before("@annotation(repeatSubmit)")
public void doBefore(JoinPoint point, RepeatSubmit repeatSubmit) throws Throwable {
@ -46,7 +50,7 @@ public class RepeatSubmitAspect {
throw new ServiceException("重复提交间隔时间不能小于'1'秒");
}
HttpServletRequest request = ServletUtils.getRequest();
String nowParams = StrUtil.join(",", point.getArgs());
String nowParams = argsArrayToString(point.getArgs());
// 请求地址作为存放cache的key值
String url = request.getRequestURI();
@ -59,10 +63,58 @@ public class RepeatSubmitAspect {
submitKey = SecureUtil.md5(submitKey + ":" + nowParams);
// 唯一标识指定key + 消息头)
String cacheRepeatKey = Constants.REPEAT_SUBMIT_KEY + submitKey;
LockInfo lock = lockTemplate.lock(cacheRepeatKey, interval, interval / 2);
if (lock == null) {
String key = RedisUtils.getCacheObject(cacheRepeatKey);
if (key == null) {
RedisUtils.setCacheObject(cacheRepeatKey, "", interval, TimeUnit.MILLISECONDS);
} else {
throw new ServiceException(repeatSubmit.message());
}
}
/**
* 参数拼装
*/
private String argsArrayToString(Object[] paramsArray) {
StringBuilder params = new StringBuilder();
if (paramsArray != null && paramsArray.length > 0) {
for (Object o : paramsArray) {
if (StringUtils.isNotNull(o) && !isFilterObject(o)) {
try {
params.append(JsonUtils.toJsonString(o)).append(" ");
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
return params.toString().trim();
}
/**
* 判断是否需要过滤的对象。
*
* @param o 对象信息。
* @return 如果是需要过滤的对象则返回true否则返回false。
*/
@SuppressWarnings("rawtypes")
public boolean isFilterObject(final Object o) {
Class<?> clazz = o.getClass();
if (clazz.isArray()) {
return clazz.getComponentType().isAssignableFrom(MultipartFile.class);
} else if (Collection.class.isAssignableFrom(clazz)) {
Collection collection = (Collection) o;
for (Object value : collection) {
return value instanceof MultipartFile;
}
} else if (Map.class.isAssignableFrom(clazz)) {
Map map = (Map) o;
for (Object value : map.entrySet()) {
Map.Entry entry = (Map.Entry) value;
return entry.getValue() instanceof MultipartFile;
}
}
return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse
|| o instanceof BindingResult;
}
}

View File

@ -1,95 +0,0 @@
package com.ruoyi.framework.config;
import feign.*;
import okhttp3.ConnectionPool;
import okhttp3.OkHttpClient;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.cloud.openfeign.FeignAutoConfiguration;
import org.springframework.cloud.openfeign.support.SpringMvcContract;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.concurrent.TimeUnit;
/**
* openfeign配置类
*
* @author Lion Li
* @deprecated 由于使用人数较少 决定与 3.4.0 版本移除
*/
@Deprecated
@EnableFeignClients("${feign.package}")
@Configuration
@ConditionalOnClass(Feign.class)
@AutoConfigureBefore(FeignAutoConfiguration.class)
public class FeignConfig {
@Bean
public OkHttpClient okHttpClient(){
return new OkHttpClient.Builder()
.readTimeout(60, TimeUnit.SECONDS)
.connectTimeout(60, TimeUnit.SECONDS)
.writeTimeout(120, TimeUnit.SECONDS)
.connectionPool(new ConnectionPool())
.build();
}
@Bean
public Contract feignContract() {
return new SpringMvcContract();
}
@Bean
public Logger.Level feignLoggerLevel() {
return Logger.Level.BASIC;
}
@Bean
public Request.Options feignRequestOptions() {
return new Request.Options(10, TimeUnit.SECONDS, 60,TimeUnit.SECONDS,true);
}
@Bean
public Retryer feignRetry() {
return new Retryer.Default();
}
// /**
// * 自定义异常解码器
// * 用于自定义返回体异常熔断
// */
// @Bean
// public ErrorDecoder errorDecoder() {
// return new CustomErrorDecoder();
// }
//
//
// /**
// * 自定义返回体解码器
// */
// @Slf4j
// public static class CustomErrorDecoder implements ErrorDecoder {
//
// @Override
// public Exception decode(String methodKey, Response response) {
// Exception exception = null;
// try {
// // 获取原始的返回内容
// String json = JsonUtils.toJsonString(response.body().asReader(StandardCharsets.UTF_8));
// exception = new RuntimeException(json);
// // 将返回内容反序列化为Result这里应根据自身项目作修改
// AjaxResult result = JsonUtils.parseObject(json, AjaxResult.class);
// // 业务异常抛出简单的 RuntimeException保留原来错误信息
// if (result.getCode() != 200) {
// exception = new RuntimeException(result.getMsg());
// }
// } catch (IOException e) {
// log.error(e.getMessage(), e);
// }
// return exception;
// }
// }
}

View File

@ -20,7 +20,6 @@ import java.util.Map;
* @author Lion Li
*/
@Configuration
@ConditionalOnProperty(value = "xss.enabled", havingValue = "true")
public class FilterConfig {
@Autowired
@ -28,6 +27,7 @@ public class FilterConfig {
@SuppressWarnings({"rawtypes", "unchecked"})
@Bean
@ConditionalOnProperty(value = "xss.enabled", havingValue = "true")
public FilterRegistrationBean xssFilterRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setDispatcherTypes(DispatcherType.REQUEST);

View File

@ -1,7 +1,6 @@
package com.ruoyi.framework.config;
import cn.hutool.core.util.StrUtil;
import org.jetbrains.annotations.NotNull;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
@ -28,7 +27,6 @@ public class I18nConfig {
*/
static class I18nLocaleResolver implements LocaleResolver {
@NotNull
@Override
public Locale resolveLocale(HttpServletRequest httpServletRequest) {
String language = httpServletRequest.getHeader("content-language");
@ -41,7 +39,7 @@ public class I18nConfig {
}
@Override
public void setLocale(@NotNull HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) {
public void setLocale(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) {
}
}

View File

@ -2,6 +2,7 @@ package com.ruoyi.framework.config;
import cn.dev33.satoken.config.SaTokenConfig;
import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
import com.github.xiaoymin.knife4j.spring.extension.OpenApiExtensionResolver;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.framework.config.properties.SwaggerProperties;
@ -34,6 +35,9 @@ public class SwaggerConfig {
@Autowired
private SaTokenConfig saTokenConfig;
@Autowired
private OpenApiExtensionResolver openApiExtensionResolver;
/**
* 创建API
*/
@ -58,6 +62,7 @@ public class SwaggerConfig {
// 设置安全模式swagger可以设置访问token
.securitySchemes(securitySchemes())
.securityContexts(securityContexts())
.extensions(openApiExtensionResolver.buildExtensions(group.getName()))
.pathMapping(swaggerProperties.getPathMapping());
String beanName = StringUtils.substringAfterLast(basePackage, ".") + "Docket";
SpringUtils.registerBean(beanName, docket);

View File

@ -1,7 +1,6 @@
package com.ruoyi.framework.config;
import com.yomahub.tlog.core.aop.AspectLogAop;
import com.yomahub.tlog.feign.filter.TLogFeignFilter;
import com.yomahub.tlog.spring.TLogPropertyInit;
import com.yomahub.tlog.spring.TLogSpringAware;
import com.yomahub.tlog.springboot.property.TLogProperty;
@ -41,9 +40,4 @@ public class TLogConfig {
return new AspectLogAop();
}
@Bean
public TLogFeignFilter tLogFeignFilter() {
return new TLogFeignFilter();
}
}

View File

@ -1,12 +1,14 @@
package com.ruoyi.framework.config;
import org.hibernate.validator.HibernateValidator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import java.util.Properties;
/**
* 校验框架配置类
@ -16,16 +18,26 @@ import javax.validation.ValidatorFactory;
@Configuration
public class ValidatorConfig {
@Autowired
private MessageSource messageSource;
/**
* 配置校验框架 快速返回模式
*/
@Bean
public Validator validator() {
ValidatorFactory validatorFactory = Validation.byProvider(HibernateValidator.class)
.configure()
.failFast(true)
.buildValidatorFactory();
return validatorFactory.getValidator();
LocalValidatorFactoryBean factoryBean = new LocalValidatorFactoryBean();
// 国际化
factoryBean.setValidationMessageSource(messageSource);
// 设置使用 HibernateValidator 校验器
factoryBean.setProviderClass(HibernateValidator.class);
Properties properties = new Properties();
// 设置 快速异常返回
properties.setProperty("hibernate.validator.fail_fast", "true");
factoryBean.setValidationProperties(properties);
// 加载配置
factoryBean.afterPropertiesSet();
return factoryBean.getValidator();
}
}

View File

@ -14,7 +14,7 @@ import java.util.concurrent.ScheduledExecutorService;
*
* @author Lion Li
*/
@Slf4j(topic = "sys-user")
@Slf4j
@Component
public class ShutdownManager {

View File

@ -16,7 +16,9 @@ import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.stream.Collectors;
/**
* 全局异常处理器
@ -104,7 +106,9 @@ public class GlobalExceptionHandler {
@ExceptionHandler(BindException.class)
public AjaxResult<Void> handleBindException(BindException e) {
log.error(e.getMessage(), e);
String message = e.getAllErrors().get(0).getDefaultMessage();
String message = e.getAllErrors().stream()
.map(DefaultMessageSourceResolvable::getDefaultMessage)
.collect(Collectors.joining(", "));
return AjaxResult.error(message);
}
@ -114,7 +118,9 @@ public class GlobalExceptionHandler {
@ExceptionHandler(ConstraintViolationException.class)
public AjaxResult<Void> constraintViolationException(ConstraintViolationException e) {
log.error(e.getMessage(), e);
String message = e.getConstraintViolations().iterator().next().getMessage();
String message = e.getConstraintViolations().stream()
.map(ConstraintViolation::getMessage)
.collect(Collectors.joining(", "));
return AjaxResult.error(message);
}