mirror of
https://github.com/dromara/RuoYi-Vue-Plus.git
synced 2025-09-24 07:19:46 +08:00
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:
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ import java.util.concurrent.ScheduledExecutorService;
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@Slf4j(topic = "sys-user")
|
||||
@Slf4j
|
||||
@Component
|
||||
public class ShutdownManager {
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user