Merge remote-tracking branch 'origin/master'
commit
7b554b7655
|
|
@ -190,9 +190,7 @@
|
||||||
| 🚀 | Java 监控 | 基于 Spring Boot Admin 实现 Java 应用的监控 |
|
| 🚀 | Java 监控 | 基于 Spring Boot Admin 实现 Java 应用的监控 |
|
||||||
| 🚀 | 链路追踪 | 接入 SkyWalking 组件,实现链路追踪 |
|
| 🚀 | 链路追踪 | 接入 SkyWalking 组件,实现链路追踪 |
|
||||||
| 🚀 | 日志中心 | 接入 SkyWalking 组件,实现日志中心 |
|
| 🚀 | 日志中心 | 接入 SkyWalking 组件,实现日志中心 |
|
||||||
| 🚀 | 分布式锁 | 基于 Redis 实现分布式锁,满足并发场景 |
|
| 🚀 | 服务保障 | 基于 Redis 实现分布式锁、幂等、限流功能,满足高并发场景 |
|
||||||
| 🚀 | 幂等组件 | 基于 Redis 实现幂等组件,解决重复请求问题 |
|
|
||||||
| 🚀 | 服务保障 | 基于 Resilience4j 实现服务的稳定性,包括限流、熔断等功能 |
|
|
||||||
| 🚀 | 日志服务 | 轻量级日志中心,查看远程服务器的日志 |
|
| 🚀 | 日志服务 | 轻量级日志中心,查看远程服务器的日志 |
|
||||||
| 🚀 | 单元测试 | 基于 JUnit + Mockito 实现单元测试,保证功能的正确性、代码的质量等 |
|
| 🚀 | 单元测试 | 基于 JUnit + Mockito 实现单元测试,保证功能的正确性、代码的质量等 |
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,6 @@
|
||||||
<xxl-job.version>2.3.1</xxl-job.version>
|
<xxl-job.version>2.3.1</xxl-job.version>
|
||||||
<!-- 服务保障相关 -->
|
<!-- 服务保障相关 -->
|
||||||
<lock4j.version>2.2.7</lock4j.version>
|
<lock4j.version>2.2.7</lock4j.version>
|
||||||
<resilience4j.version>1.7.1</resilience4j.version>
|
|
||||||
<!-- 监控相关 -->
|
<!-- 监控相关 -->
|
||||||
<skywalking.version>8.12.0</skywalking.version>
|
<skywalking.version>8.12.0</skywalking.version>
|
||||||
<spring-boot-admin.version>2.7.15</spring-boot-admin.version>
|
<spring-boot-admin.version>2.7.15</spring-boot-admin.version>
|
||||||
|
|
@ -343,17 +342,6 @@
|
||||||
</exclusions>
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.github.resilience4j</groupId>
|
|
||||||
<artifactId>resilience4j-ratelimiter</artifactId>
|
|
||||||
<version>${resilience4j.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.github.resilience4j</groupId>
|
|
||||||
<artifactId>resilience4j-spring-boot2</artifactId>
|
|
||||||
<version>${resilience4j.version}</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- 监控相关 -->
|
<!-- 监控相关 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cn.iocoder.cloud</groupId>
|
<groupId>cn.iocoder.cloud</groupId>
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,13 @@
|
||||||
<url>https://github.com/YunaiV/ruoyi-vue-pro</url>
|
<url>https://github.com/YunaiV/ruoyi-vue-pro</url>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
<!-- Web 相关 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.iocoder.cloud</groupId>
|
||||||
|
<artifactId>yudao-spring-boot-starter-web</artifactId>
|
||||||
|
<scope>provided</scope> <!-- 设置为 provided,只有限流、幂等使用到 -->
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- DB 相关 -->
|
<!-- DB 相关 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cn.iocoder.cloud</groupId>
|
<groupId>cn.iocoder.cloud</groupId>
|
||||||
|
|
@ -28,12 +35,6 @@
|
||||||
<artifactId>lock4j-redisson-spring-boot-starter</artifactId>
|
<artifactId>lock4j-redisson-spring-boot-starter</artifactId>
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.github.resilience4j</groupId>
|
|
||||||
<artifactId>resilience4j-spring-boot2</artifactId>
|
|
||||||
<optional>true</optional>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.idempotent.core.aop.IdempotentAspect;
|
||||||
import cn.iocoder.yudao.framework.idempotent.core.keyresolver.impl.DefaultIdempotentKeyResolver;
|
import cn.iocoder.yudao.framework.idempotent.core.keyresolver.impl.DefaultIdempotentKeyResolver;
|
||||||
import cn.iocoder.yudao.framework.idempotent.core.keyresolver.impl.ExpressionIdempotentKeyResolver;
|
import cn.iocoder.yudao.framework.idempotent.core.keyresolver.impl.ExpressionIdempotentKeyResolver;
|
||||||
import cn.iocoder.yudao.framework.idempotent.core.keyresolver.IdempotentKeyResolver;
|
import cn.iocoder.yudao.framework.idempotent.core.keyresolver.IdempotentKeyResolver;
|
||||||
|
import cn.iocoder.yudao.framework.idempotent.core.keyresolver.impl.UserIdempotentKeyResolver;
|
||||||
import cn.iocoder.yudao.framework.idempotent.core.redis.IdempotentRedisDAO;
|
import cn.iocoder.yudao.framework.idempotent.core.redis.IdempotentRedisDAO;
|
||||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||||
import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration;
|
import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration;
|
||||||
|
|
@ -32,6 +33,11 @@ public class YudaoIdempotentConfiguration {
|
||||||
return new DefaultIdempotentKeyResolver();
|
return new DefaultIdempotentKeyResolver();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public UserIdempotentKeyResolver userIdempotentKeyResolver() {
|
||||||
|
return new UserIdempotentKeyResolver();
|
||||||
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public ExpressionIdempotentKeyResolver expressionIdempotentKeyResolver() {
|
public ExpressionIdempotentKeyResolver expressionIdempotentKeyResolver() {
|
||||||
return new ExpressionIdempotentKeyResolver();
|
return new ExpressionIdempotentKeyResolver();
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@ package cn.iocoder.yudao.framework.idempotent.core.annotation;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.idempotent.core.keyresolver.impl.DefaultIdempotentKeyResolver;
|
import cn.iocoder.yudao.framework.idempotent.core.keyresolver.impl.DefaultIdempotentKeyResolver;
|
||||||
import cn.iocoder.yudao.framework.idempotent.core.keyresolver.IdempotentKeyResolver;
|
import cn.iocoder.yudao.framework.idempotent.core.keyresolver.IdempotentKeyResolver;
|
||||||
|
import cn.iocoder.yudao.framework.idempotent.core.keyresolver.impl.ExpressionIdempotentKeyResolver;
|
||||||
|
import cn.iocoder.yudao.framework.idempotent.core.keyresolver.impl.UserIdempotentKeyResolver;
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
|
|
@ -36,6 +38,10 @@ public @interface Idempotent {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 使用的 Key 解析器
|
* 使用的 Key 解析器
|
||||||
|
*
|
||||||
|
* @see DefaultIdempotentKeyResolver 全局级别
|
||||||
|
* @see UserIdempotentKeyResolver 用户级别
|
||||||
|
* @see ExpressionIdempotentKeyResolver 自定义表达式,通过 {@link #keyArg()} 计算
|
||||||
*/
|
*/
|
||||||
Class<? extends IdempotentKeyResolver> keyResolver() default DefaultIdempotentKeyResolver.class;
|
Class<? extends IdempotentKeyResolver> keyResolver() default DefaultIdempotentKeyResolver.class;
|
||||||
/**
|
/**
|
||||||
|
|
@ -43,4 +49,15 @@ public @interface Idempotent {
|
||||||
*/
|
*/
|
||||||
String keyArg() default "";
|
String keyArg() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除 Key,当发生异常时候
|
||||||
|
*
|
||||||
|
* 问题:为什么发生异常时,需要删除 Key 呢?
|
||||||
|
* 回答:发生异常时,说明业务发生错误,此时需要删除 Key,避免下次请求无法正常执行。
|
||||||
|
*
|
||||||
|
* 问题:为什么不搞 deleteWhenSuccess 执行成功时,需要删除 Key 呢?
|
||||||
|
* 回答:这种情况下,本质上是分布式锁,推荐使用 @Lock4j 注解
|
||||||
|
*/
|
||||||
|
boolean deleteKeyWhenException() default true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,14 @@ package cn.iocoder.yudao.framework.idempotent.core.aop;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.common.exception.ServiceException;
|
import cn.iocoder.yudao.framework.common.exception.ServiceException;
|
||||||
import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants;
|
import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants;
|
||||||
|
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||||
import cn.iocoder.yudao.framework.idempotent.core.annotation.Idempotent;
|
import cn.iocoder.yudao.framework.idempotent.core.annotation.Idempotent;
|
||||||
import cn.iocoder.yudao.framework.idempotent.core.keyresolver.IdempotentKeyResolver;
|
import cn.iocoder.yudao.framework.idempotent.core.keyresolver.IdempotentKeyResolver;
|
||||||
import cn.iocoder.yudao.framework.idempotent.core.redis.IdempotentRedisDAO;
|
import cn.iocoder.yudao.framework.idempotent.core.redis.IdempotentRedisDAO;
|
||||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.aspectj.lang.JoinPoint;
|
import org.aspectj.lang.ProceedingJoinPoint;
|
||||||
|
import org.aspectj.lang.annotation.Around;
|
||||||
import org.aspectj.lang.annotation.Aspect;
|
import org.aspectj.lang.annotation.Aspect;
|
||||||
import org.aspectj.lang.annotation.Before;
|
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
@ -36,21 +36,33 @@ public class IdempotentAspect {
|
||||||
this.idempotentRedisDAO = idempotentRedisDAO;
|
this.idempotentRedisDAO = idempotentRedisDAO;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Before("@annotation(idempotent)")
|
@Around(value = "@annotation(idempotent)")
|
||||||
public void beforePointCut(JoinPoint joinPoint, Idempotent idempotent) {
|
public Object aroundPointCut(ProceedingJoinPoint joinPoint, Idempotent idempotent) throws Throwable {
|
||||||
// 获得 IdempotentKeyResolver
|
// 获得 IdempotentKeyResolver
|
||||||
IdempotentKeyResolver keyResolver = keyResolvers.get(idempotent.keyResolver());
|
IdempotentKeyResolver keyResolver = keyResolvers.get(idempotent.keyResolver());
|
||||||
Assert.notNull(keyResolver, "找不到对应的 IdempotentKeyResolver");
|
Assert.notNull(keyResolver, "找不到对应的 IdempotentKeyResolver");
|
||||||
// 解析 Key
|
// 解析 Key
|
||||||
String key = keyResolver.resolver(joinPoint, idempotent);
|
String key = keyResolver.resolver(joinPoint, idempotent);
|
||||||
|
|
||||||
// 锁定 Key。
|
// 1. 锁定 Key
|
||||||
boolean success = idempotentRedisDAO.setIfAbsent(key, idempotent.timeout(), idempotent.timeUnit());
|
boolean success = idempotentRedisDAO.setIfAbsent(key, idempotent.timeout(), idempotent.timeUnit());
|
||||||
// 锁定失败,抛出异常
|
// 锁定失败,抛出异常
|
||||||
if (!success) {
|
if (!success) {
|
||||||
log.info("[beforePointCut][方法({}) 参数({}) 存在重复请求]", joinPoint.getSignature().toString(), joinPoint.getArgs());
|
log.info("[aroundPointCut][方法({}) 参数({}) 存在重复请求]", joinPoint.getSignature().toString(), joinPoint.getArgs());
|
||||||
throw new ServiceException(GlobalErrorCodeConstants.REPEATED_REQUESTS.getCode(), idempotent.message());
|
throw new ServiceException(GlobalErrorCodeConstants.REPEATED_REQUESTS.getCode(), idempotent.message());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 2. 执行逻辑
|
||||||
|
try {
|
||||||
|
return joinPoint.proceed();
|
||||||
|
} catch (Throwable throwable) {
|
||||||
|
// 3. 异常时,删除 Key
|
||||||
|
// 参考美团 GTIS 思路:https://tech.meituan.com/2016/09/29/distributed-system-mutually-exclusive-idempotence-cerberus-gtis.html
|
||||||
|
if (idempotent.deleteKeyWhenException()) {
|
||||||
|
idempotentRedisDAO.delete(key);
|
||||||
|
}
|
||||||
|
throw throwable;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import cn.iocoder.yudao.framework.idempotent.core.keyresolver.IdempotentKeyResol
|
||||||
import org.aspectj.lang.JoinPoint;
|
import org.aspectj.lang.JoinPoint;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 默认幂等 Key 解析器,使用方法名 + 方法参数,组装成一个 Key
|
* 默认(全局级别)幂等 Key 解析器,使用方法名 + 方法参数,组装成一个 Key
|
||||||
*
|
*
|
||||||
* 为了避免 Key 过长,使用 MD5 进行“压缩”
|
* 为了避免 Key 过长,使用 MD5 进行“压缩”
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
package cn.iocoder.yudao.framework.idempotent.core.keyresolver.impl;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import cn.hutool.crypto.SecureUtil;
|
||||||
|
import cn.iocoder.yudao.framework.idempotent.core.annotation.Idempotent;
|
||||||
|
import cn.iocoder.yudao.framework.idempotent.core.keyresolver.IdempotentKeyResolver;
|
||||||
|
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
|
||||||
|
import org.aspectj.lang.JoinPoint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户级别的幂等 Key 解析器,使用方法名 + 方法参数 + userId + userType,组装成一个 Key
|
||||||
|
*
|
||||||
|
* 为了避免 Key 过长,使用 MD5 进行“压缩”
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
public class UserIdempotentKeyResolver implements IdempotentKeyResolver {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String resolver(JoinPoint joinPoint, Idempotent idempotent) {
|
||||||
|
String methodName = joinPoint.getSignature().toString();
|
||||||
|
String argsStr = StrUtil.join(",", joinPoint.getArgs());
|
||||||
|
Long userId = WebFrameworkUtils.getLoginUserId();
|
||||||
|
Integer userType = WebFrameworkUtils.getLoginUserType();
|
||||||
|
return SecureUtil.md5(methodName + argsStr + userId + userType);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -29,6 +29,11 @@ public class IdempotentRedisDAO {
|
||||||
return redisTemplate.opsForValue().setIfAbsent(redisKey, "", timeout, timeUnit);
|
return redisTemplate.opsForValue().setIfAbsent(redisKey, "", timeout, timeUnit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void delete(String key) {
|
||||||
|
String redisKey = formatKey(key);
|
||||||
|
redisTemplate.delete(redisKey);
|
||||||
|
}
|
||||||
|
|
||||||
private static String formatKey(String key) {
|
private static String formatKey(String key) {
|
||||||
return String.format(IDEMPOTENT, key);
|
return String.format(IDEMPOTENT, key);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
package cn.iocoder.yudao.framework.ratelimiter.config;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.ratelimiter.core.aop.RateLimiterAspect;
|
||||||
|
import cn.iocoder.yudao.framework.ratelimiter.core.keyresolver.RateLimiterKeyResolver;
|
||||||
|
import cn.iocoder.yudao.framework.ratelimiter.core.keyresolver.impl.*;
|
||||||
|
import cn.iocoder.yudao.framework.ratelimiter.core.redis.RateLimiterRedisDAO;
|
||||||
|
import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration;
|
||||||
|
import org.redisson.api.RedissonClient;
|
||||||
|
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@AutoConfiguration(after = YudaoRedisAutoConfiguration.class)
|
||||||
|
public class YudaoRateLimiterConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public RateLimiterAspect rateLimiterAspect(List<RateLimiterKeyResolver> keyResolvers, RateLimiterRedisDAO rateLimiterRedisDAO) {
|
||||||
|
return new RateLimiterAspect(keyResolvers, rateLimiterRedisDAO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
|
||||||
|
public RateLimiterRedisDAO rateLimiterRedisDAO(RedissonClient redissonClient) {
|
||||||
|
return new RateLimiterRedisDAO(redissonClient);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== 各种 RateLimiterRedisDAO Bean ==========
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public DefaultRateLimiterKeyResolver defaultRateLimiterKeyResolver() {
|
||||||
|
return new DefaultRateLimiterKeyResolver();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public UserRateLimiterKeyResolver userRateLimiterKeyResolver() {
|
||||||
|
return new UserRateLimiterKeyResolver();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public ClientIpRateLimiterKeyResolver clientIpRateLimiterKeyResolver() {
|
||||||
|
return new ClientIpRateLimiterKeyResolver();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public ServerNodeRateLimiterKeyResolver serverNodeRateLimiterKeyResolver() {
|
||||||
|
return new ServerNodeRateLimiterKeyResolver();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public ExpressionRateLimiterKeyResolver expressionRateLimiterKeyResolver() {
|
||||||
|
return new ExpressionRateLimiterKeyResolver();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
package cn.iocoder.yudao.framework.ratelimiter.core.annotation;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants;
|
||||||
|
import cn.iocoder.yudao.framework.idempotent.core.keyresolver.impl.ExpressionIdempotentKeyResolver;
|
||||||
|
import cn.iocoder.yudao.framework.ratelimiter.core.keyresolver.RateLimiterKeyResolver;
|
||||||
|
import cn.iocoder.yudao.framework.ratelimiter.core.keyresolver.impl.ClientIpRateLimiterKeyResolver;
|
||||||
|
import cn.iocoder.yudao.framework.ratelimiter.core.keyresolver.impl.DefaultRateLimiterKeyResolver;
|
||||||
|
import cn.iocoder.yudao.framework.ratelimiter.core.keyresolver.impl.ServerNodeRateLimiterKeyResolver;
|
||||||
|
import cn.iocoder.yudao.framework.ratelimiter.core.keyresolver.impl.UserRateLimiterKeyResolver;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 限流注解
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
@Target({ElementType.METHOD})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface RateLimiter {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 限流的时间,默认为 1 秒
|
||||||
|
*/
|
||||||
|
int time() default 1;
|
||||||
|
/**
|
||||||
|
* 时间单位,默认为 SECONDS 秒
|
||||||
|
*/
|
||||||
|
TimeUnit timeUnit() default TimeUnit.SECONDS;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 限流次数
|
||||||
|
*/
|
||||||
|
int count() default 100;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提示信息,请求过快的提示
|
||||||
|
*
|
||||||
|
* @see GlobalErrorCodeConstants#TOO_MANY_REQUESTS
|
||||||
|
*/
|
||||||
|
String message() default ""; // 为空时,使用 TOO_MANY_REQUESTS 错误提示
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使用的 Key 解析器
|
||||||
|
*
|
||||||
|
* @see DefaultRateLimiterKeyResolver 全局级别
|
||||||
|
* @see UserRateLimiterKeyResolver 用户 ID 级别
|
||||||
|
* @see ClientIpRateLimiterKeyResolver 用户 IP 级别
|
||||||
|
* @see ServerNodeRateLimiterKeyResolver 服务器 Node 级别
|
||||||
|
* @see ExpressionIdempotentKeyResolver 自定义表达式,通过 {@link #keyArg()} 计算
|
||||||
|
*/
|
||||||
|
Class<? extends RateLimiterKeyResolver> keyResolver() default DefaultRateLimiterKeyResolver.class;
|
||||||
|
/**
|
||||||
|
* 使用的 Key 参数
|
||||||
|
*/
|
||||||
|
String keyArg() default "";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
package cn.iocoder.yudao.framework.ratelimiter.core.aop;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import cn.iocoder.yudao.framework.common.exception.ServiceException;
|
||||||
|
import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants;
|
||||||
|
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||||
|
import cn.iocoder.yudao.framework.ratelimiter.core.annotation.RateLimiter;
|
||||||
|
import cn.iocoder.yudao.framework.ratelimiter.core.keyresolver.RateLimiterKeyResolver;
|
||||||
|
import cn.iocoder.yudao.framework.ratelimiter.core.redis.RateLimiterRedisDAO;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.aspectj.lang.JoinPoint;
|
||||||
|
import org.aspectj.lang.annotation.Aspect;
|
||||||
|
import org.aspectj.lang.annotation.Before;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 拦截声明了 {@link RateLimiter} 注解的方法,实现限流操作
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
@Aspect
|
||||||
|
@Slf4j
|
||||||
|
public class RateLimiterAspect {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RateLimiterKeyResolver 集合
|
||||||
|
*/
|
||||||
|
private final Map<Class<? extends RateLimiterKeyResolver>, RateLimiterKeyResolver> keyResolvers;
|
||||||
|
|
||||||
|
private final RateLimiterRedisDAO rateLimiterRedisDAO;
|
||||||
|
|
||||||
|
public RateLimiterAspect(List<RateLimiterKeyResolver> keyResolvers, RateLimiterRedisDAO rateLimiterRedisDAO) {
|
||||||
|
this.keyResolvers = CollectionUtils.convertMap(keyResolvers, RateLimiterKeyResolver::getClass);
|
||||||
|
this.rateLimiterRedisDAO = rateLimiterRedisDAO;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Before("@annotation(rateLimiter)")
|
||||||
|
public void beforePointCut(JoinPoint joinPoint, RateLimiter rateLimiter) {
|
||||||
|
// 获得 IdempotentKeyResolver 对象
|
||||||
|
RateLimiterKeyResolver keyResolver = keyResolvers.get(rateLimiter.keyResolver());
|
||||||
|
Assert.notNull(keyResolver, "找不到对应的 RateLimiterKeyResolver");
|
||||||
|
// 解析 Key
|
||||||
|
String key = keyResolver.resolver(joinPoint, rateLimiter);
|
||||||
|
|
||||||
|
// 获取 1 次限流
|
||||||
|
boolean success = rateLimiterRedisDAO.tryAcquire(key,
|
||||||
|
rateLimiter.count(), rateLimiter.time(), rateLimiter.timeUnit());
|
||||||
|
if (!success) {
|
||||||
|
log.info("[beforePointCut][方法({}) 参数({}) 请求过于频繁]", joinPoint.getSignature().toString(), joinPoint.getArgs());
|
||||||
|
String message = StrUtil.blankToDefault(rateLimiter.message(),
|
||||||
|
GlobalErrorCodeConstants.TOO_MANY_REQUESTS.getMsg());
|
||||||
|
throw new ServiceException(GlobalErrorCodeConstants.TOO_MANY_REQUESTS.getCode(), message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
package cn.iocoder.yudao.framework.ratelimiter.core.keyresolver;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.ratelimiter.core.annotation.RateLimiter;
|
||||||
|
import org.aspectj.lang.JoinPoint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 限流 Key 解析器接口
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
public interface RateLimiterKeyResolver {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析一个 Key
|
||||||
|
*
|
||||||
|
* @param rateLimiter 限流注解
|
||||||
|
* @param joinPoint AOP 切面
|
||||||
|
* @return Key
|
||||||
|
*/
|
||||||
|
String resolver(JoinPoint joinPoint, RateLimiter rateLimiter);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
package cn.iocoder.yudao.framework.ratelimiter.core.keyresolver.impl;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import cn.hutool.crypto.SecureUtil;
|
||||||
|
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
|
||||||
|
import cn.iocoder.yudao.framework.ratelimiter.core.annotation.RateLimiter;
|
||||||
|
import cn.iocoder.yudao.framework.ratelimiter.core.keyresolver.RateLimiterKeyResolver;
|
||||||
|
import org.aspectj.lang.JoinPoint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IP 级别的限流 Key 解析器,使用方法名 + 方法参数 + IP,组装成一个 Key
|
||||||
|
*
|
||||||
|
* 为了避免 Key 过长,使用 MD5 进行“压缩”
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
public class ClientIpRateLimiterKeyResolver implements RateLimiterKeyResolver {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String resolver(JoinPoint joinPoint, RateLimiter rateLimiter) {
|
||||||
|
String methodName = joinPoint.getSignature().toString();
|
||||||
|
String argsStr = StrUtil.join(",", joinPoint.getArgs());
|
||||||
|
String clientIp = ServletUtils.getClientIP();
|
||||||
|
return SecureUtil.md5(methodName + argsStr + clientIp);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
package cn.iocoder.yudao.framework.ratelimiter.core.keyresolver.impl;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import cn.hutool.crypto.SecureUtil;
|
||||||
|
import cn.iocoder.yudao.framework.ratelimiter.core.annotation.RateLimiter;
|
||||||
|
import cn.iocoder.yudao.framework.ratelimiter.core.keyresolver.RateLimiterKeyResolver;
|
||||||
|
import org.aspectj.lang.JoinPoint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 默认(全局级别)限流 Key 解析器,使用方法名 + 方法参数,组装成一个 Key
|
||||||
|
*
|
||||||
|
* 为了避免 Key 过长,使用 MD5 进行“压缩”
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
public class DefaultRateLimiterKeyResolver implements RateLimiterKeyResolver {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String resolver(JoinPoint joinPoint, RateLimiter rateLimiter) {
|
||||||
|
String methodName = joinPoint.getSignature().toString();
|
||||||
|
String argsStr = StrUtil.join(",", joinPoint.getArgs());
|
||||||
|
return SecureUtil.md5(methodName + argsStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
package cn.iocoder.yudao.framework.ratelimiter.core.keyresolver.impl;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.ArrayUtil;
|
||||||
|
import cn.iocoder.yudao.framework.ratelimiter.core.annotation.RateLimiter;
|
||||||
|
import cn.iocoder.yudao.framework.ratelimiter.core.keyresolver.RateLimiterKeyResolver;
|
||||||
|
import org.aspectj.lang.JoinPoint;
|
||||||
|
import org.aspectj.lang.reflect.MethodSignature;
|
||||||
|
import org.springframework.core.DefaultParameterNameDiscoverer;
|
||||||
|
import org.springframework.core.ParameterNameDiscoverer;
|
||||||
|
import org.springframework.expression.Expression;
|
||||||
|
import org.springframework.expression.ExpressionParser;
|
||||||
|
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||||
|
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 基于 Spring EL 表达式的 {@link RateLimiterKeyResolver} 实现类
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
public class ExpressionRateLimiterKeyResolver implements RateLimiterKeyResolver {
|
||||||
|
|
||||||
|
private final ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
|
||||||
|
|
||||||
|
private final ExpressionParser expressionParser = new SpelExpressionParser();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String resolver(JoinPoint joinPoint, RateLimiter rateLimiter) {
|
||||||
|
// 获得被拦截方法参数名列表
|
||||||
|
Method method = getMethod(joinPoint);
|
||||||
|
Object[] args = joinPoint.getArgs();
|
||||||
|
String[] parameterNames = this.parameterNameDiscoverer.getParameterNames(method);
|
||||||
|
// 准备 Spring EL 表达式解析的上下文
|
||||||
|
StandardEvaluationContext evaluationContext = new StandardEvaluationContext();
|
||||||
|
if (ArrayUtil.isNotEmpty(parameterNames)) {
|
||||||
|
for (int i = 0; i < parameterNames.length; i++) {
|
||||||
|
evaluationContext.setVariable(parameterNames[i], args[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析参数
|
||||||
|
Expression expression = expressionParser.parseExpression(rateLimiter.keyArg());
|
||||||
|
return expression.getValue(evaluationContext, String.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Method getMethod(JoinPoint point) {
|
||||||
|
// 处理,声明在类上的情况
|
||||||
|
MethodSignature signature = (MethodSignature) point.getSignature();
|
||||||
|
Method method = signature.getMethod();
|
||||||
|
if (!method.getDeclaringClass().isInterface()) {
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理,声明在接口上的情况
|
||||||
|
try {
|
||||||
|
return point.getTarget().getClass().getDeclaredMethod(
|
||||||
|
point.getSignature().getName(), method.getParameterTypes());
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
package cn.iocoder.yudao.framework.ratelimiter.core.keyresolver.impl;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import cn.hutool.crypto.SecureUtil;
|
||||||
|
import cn.hutool.system.SystemUtil;
|
||||||
|
import cn.iocoder.yudao.framework.ratelimiter.core.annotation.RateLimiter;
|
||||||
|
import cn.iocoder.yudao.framework.ratelimiter.core.keyresolver.RateLimiterKeyResolver;
|
||||||
|
import org.aspectj.lang.JoinPoint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Server 节点级别的限流 Key 解析器,使用方法名 + 方法参数 + IP,组装成一个 Key
|
||||||
|
*
|
||||||
|
* 为了避免 Key 过长,使用 MD5 进行“压缩”
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
public class ServerNodeRateLimiterKeyResolver implements RateLimiterKeyResolver {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String resolver(JoinPoint joinPoint, RateLimiter rateLimiter) {
|
||||||
|
String methodName = joinPoint.getSignature().toString();
|
||||||
|
String argsStr = StrUtil.join(",", joinPoint.getArgs());
|
||||||
|
String serverNode = String.format("%s@%d", SystemUtil.getHostInfo().getAddress(), SystemUtil.getCurrentPID());
|
||||||
|
return SecureUtil.md5(methodName + argsStr + serverNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
package cn.iocoder.yudao.framework.ratelimiter.core.keyresolver.impl;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import cn.hutool.crypto.SecureUtil;
|
||||||
|
import cn.iocoder.yudao.framework.ratelimiter.core.annotation.RateLimiter;
|
||||||
|
import cn.iocoder.yudao.framework.ratelimiter.core.keyresolver.RateLimiterKeyResolver;
|
||||||
|
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
|
||||||
|
import org.aspectj.lang.JoinPoint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户级别的限流 Key 解析器,使用方法名 + 方法参数 + userId + userType,组装成一个 Key
|
||||||
|
*
|
||||||
|
* 为了避免 Key 过长,使用 MD5 进行“压缩”
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
public class UserRateLimiterKeyResolver implements RateLimiterKeyResolver {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String resolver(JoinPoint joinPoint, RateLimiter rateLimiter) {
|
||||||
|
String methodName = joinPoint.getSignature().toString();
|
||||||
|
String argsStr = StrUtil.join(",", joinPoint.getArgs());
|
||||||
|
Long userId = WebFrameworkUtils.getLoginUserId();
|
||||||
|
Integer userType = WebFrameworkUtils.getLoginUserType();
|
||||||
|
return SecureUtil.md5(methodName + argsStr + userId + userType);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
package cn.iocoder.yudao.framework.ratelimiter.core.redis;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import org.redisson.api.*;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 限流 Redis DAO
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class RateLimiterRedisDAO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 限流操作
|
||||||
|
*
|
||||||
|
* KEY 格式:rate_limiter:%s // 参数为 uuid
|
||||||
|
* VALUE 格式:String
|
||||||
|
* 过期时间:不固定
|
||||||
|
*/
|
||||||
|
private static final String RATE_LIMITER = "rate_limiter:%s";
|
||||||
|
|
||||||
|
private final RedissonClient redissonClient;
|
||||||
|
|
||||||
|
public Boolean tryAcquire(String key, int count, int time, TimeUnit timeUnit) {
|
||||||
|
// 1. 获得 RRateLimiter,并设置 rate 速率
|
||||||
|
RRateLimiter rateLimiter = getRRateLimiter(key, count, time, timeUnit);
|
||||||
|
// 2. 尝试获取 1 个
|
||||||
|
return rateLimiter.tryAcquire();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String formatKey(String key) {
|
||||||
|
return String.format(RATE_LIMITER, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
private RRateLimiter getRRateLimiter(String key, long count, int time, TimeUnit timeUnit) {
|
||||||
|
String redisKey = formatKey(key);
|
||||||
|
RRateLimiter rateLimiter = redissonClient.getRateLimiter(redisKey);
|
||||||
|
long rateInterval = timeUnit.toSeconds(time);
|
||||||
|
// 1. 如果不存在,设置 rate 速率
|
||||||
|
RateLimiterConfig config = rateLimiter.getConfig();
|
||||||
|
if (config == null) {
|
||||||
|
rateLimiter.trySetRate(RateType.OVERALL, count, rateInterval, RateIntervalUnit.SECONDS);
|
||||||
|
return rateLimiter;
|
||||||
|
}
|
||||||
|
// 2. 如果存在,并且配置相同,则直接返回
|
||||||
|
if (config.getRateType() == RateType.OVERALL
|
||||||
|
&& Objects.equals(config.getRate(), count)
|
||||||
|
&& Objects.equals(config.getRateInterval(), TimeUnit.SECONDS.toMillis(rateInterval))) {
|
||||||
|
return rateLimiter;
|
||||||
|
}
|
||||||
|
// 3. 如果存在,并且配置不同,则进行新建
|
||||||
|
rateLimiter.setRate(RateType.OVERALL, count, rateInterval, RateIntervalUnit.SECONDS);
|
||||||
|
return rateLimiter;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
/**
|
||||||
|
* 限流组件,基于 Redisson {@link org.redisson.api.RRateLimiter} 限流实现
|
||||||
|
*/
|
||||||
|
package cn.iocoder.yudao.framework.ratelimiter;
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
/**
|
|
||||||
* 使用 Resilience4j 组件,实现服务保障,包括:
|
|
||||||
* 1. 熔断器
|
|
||||||
* 2. 限流器
|
|
||||||
* 3. 舱壁隔离
|
|
||||||
* 4. 重试
|
|
||||||
* 5. 限时器
|
|
||||||
*/
|
|
||||||
package cn.iocoder.yudao.framework.resilience4j;
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
<https://www.iocoder.cn/Spring-Boot/Resilience4j/?yudao>
|
|
||||||
|
|
@ -1,2 +1,3 @@
|
||||||
cn.iocoder.yudao.framework.idempotent.config.YudaoIdempotentConfiguration
|
cn.iocoder.yudao.framework.idempotent.config.YudaoIdempotentConfiguration
|
||||||
cn.iocoder.yudao.framework.lock4j.config.YudaoLock4jConfiguration
|
cn.iocoder.yudao.framework.lock4j.config.YudaoLock4jConfiguration
|
||||||
|
cn.iocoder.yudao.framework.ratelimiter.config.YudaoRateLimiterConfiguration
|
||||||
|
|
@ -73,13 +73,6 @@
|
||||||
<groupId>io.github.mouzt</groupId>
|
<groupId>io.github.mouzt</groupId>
|
||||||
<artifactId>bizlog-sdk</artifactId>
|
<artifactId>bizlog-sdk</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- 业务组件 -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>cn.iocoder.cloud</groupId>
|
|
||||||
<artifactId>yudao-module-system-api</artifactId> <!-- 需要使用它,进行 Token 的校验 -->
|
|
||||||
<version>${revision}</version>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package cn.iocoder.yudao.framework.apilog.core.annotations;
|
package cn.iocoder.yudao.framework.apilog.core.annotation;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum;
|
import cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum;
|
||||||
|
|
||||||
|
|
@ -7,7 +7,7 @@ import cn.hutool.core.map.MapUtil;
|
||||||
import cn.hutool.core.util.ArrayUtil;
|
import cn.hutool.core.util.ArrayUtil;
|
||||||
import cn.hutool.core.util.BooleanUtil;
|
import cn.hutool.core.util.BooleanUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
import cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum;
|
import cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum;
|
||||||
import cn.iocoder.yudao.framework.apilog.core.service.ApiAccessLogFrameworkService;
|
import cn.iocoder.yudao.framework.apilog.core.service.ApiAccessLogFrameworkService;
|
||||||
import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants;
|
import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants;
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,9 @@ package cn.iocoder.yudao.framework.jackson.config;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||||
import cn.iocoder.yudao.framework.jackson.core.databind.LocalDateTimeDeserializer;
|
|
||||||
import cn.iocoder.yudao.framework.jackson.core.databind.LocalDateTimeSerializer;
|
|
||||||
import cn.iocoder.yudao.framework.jackson.core.databind.NumberSerializer;
|
import cn.iocoder.yudao.framework.jackson.core.databind.NumberSerializer;
|
||||||
|
import cn.iocoder.yudao.framework.jackson.core.databind.TimestampLocalDateTimeDeserializer;
|
||||||
|
import cn.iocoder.yudao.framework.jackson.core.databind.TimestampLocalDateTimeSerializer;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||||
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
|
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
|
||||||
|
|
@ -37,13 +37,13 @@ public class YudaoJacksonAutoConfiguration {
|
||||||
.addDeserializer(LocalDate.class, LocalDateDeserializer.INSTANCE)
|
.addDeserializer(LocalDate.class, LocalDateDeserializer.INSTANCE)
|
||||||
.addSerializer(LocalTime.class, LocalTimeSerializer.INSTANCE)
|
.addSerializer(LocalTime.class, LocalTimeSerializer.INSTANCE)
|
||||||
.addDeserializer(LocalTime.class, LocalTimeDeserializer.INSTANCE)
|
.addDeserializer(LocalTime.class, LocalTimeDeserializer.INSTANCE)
|
||||||
// 新增 LocalDateTime 序列化、反序列化规则
|
// 新增 LocalDateTime 序列化、反序列化规则,使用 Long 时间戳
|
||||||
.addSerializer(LocalDateTime.class, LocalDateTimeSerializer.INSTANCE)
|
.addSerializer(LocalDateTime.class, TimestampLocalDateTimeSerializer.INSTANCE)
|
||||||
.addDeserializer(LocalDateTime.class, LocalDateTimeDeserializer.INSTANCE);
|
.addDeserializer(LocalDateTime.class, TimestampLocalDateTimeDeserializer.INSTANCE);
|
||||||
// 1.2 注册到 objectMapper
|
// 1.2 注册到 objectMapper
|
||||||
objectMappers.forEach(objectMapper -> objectMapper.registerModule(simpleModule));
|
objectMappers.forEach(objectMapper -> objectMapper.registerModule(simpleModule));
|
||||||
|
|
||||||
// 2. 设置 objectMapper 到 JsonUtils {
|
// 2. 设置 objectMapper 到 JsonUtils
|
||||||
JsonUtils.init(CollUtil.getFirst(objectMappers));
|
JsonUtils.init(CollUtil.getFirst(objectMappers));
|
||||||
log.info("[init][初始化 JsonUtils 成功]");
|
log.info("[init][初始化 JsonUtils 成功]");
|
||||||
return new JsonUtils();
|
return new JsonUtils();
|
||||||
|
|
|
||||||
|
|
@ -10,16 +10,18 @@ import java.time.LocalDateTime;
|
||||||
import java.time.ZoneId;
|
import java.time.ZoneId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* LocalDateTime反序列化规则
|
* 基于时间戳的 LocalDateTime 反序列化器
|
||||||
* <p>
|
*
|
||||||
* 会将毫秒级时间戳反序列化为LocalDateTime
|
* @author 老五
|
||||||
*/
|
*/
|
||||||
public class LocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {
|
public class TimestampLocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {
|
||||||
|
|
||||||
public static final LocalDateTimeDeserializer INSTANCE = new LocalDateTimeDeserializer();
|
public static final TimestampLocalDateTimeDeserializer INSTANCE = new TimestampLocalDateTimeDeserializer();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LocalDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
|
public LocalDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
|
||||||
|
// 将 Long 时间戳,转换为 LocalDateTime 对象
|
||||||
return LocalDateTime.ofInstant(Instant.ofEpochMilli(p.getValueAsLong()), ZoneId.systemDefault());
|
return LocalDateTime.ofInstant(Instant.ofEpochMilli(p.getValueAsLong()), ZoneId.systemDefault());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -9,16 +9,18 @@ import java.time.LocalDateTime;
|
||||||
import java.time.ZoneId;
|
import java.time.ZoneId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* LocalDateTime序列化规则
|
* 基于时间戳的 LocalDateTime 序列化器
|
||||||
* <p>
|
*
|
||||||
* 会将LocalDateTime序列化为毫秒级时间戳
|
* @author 老五
|
||||||
*/
|
*/
|
||||||
public class LocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {
|
public class TimestampLocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {
|
||||||
|
|
||||||
public static final LocalDateTimeSerializer INSTANCE = new LocalDateTimeSerializer();
|
public static final TimestampLocalDateTimeSerializer INSTANCE = new TimestampLocalDateTimeSerializer();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
|
public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
|
||||||
|
// 将 LocalDateTime 对象,转换为 Long 时间戳
|
||||||
gen.writeNumber(value.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
|
gen.writeNumber(value.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -3,14 +3,13 @@ package cn.iocoder.yudao.framework.web.core.handler;
|
||||||
import cn.hutool.core.exceptions.ExceptionUtil;
|
import cn.hutool.core.exceptions.ExceptionUtil;
|
||||||
import cn.hutool.core.map.MapUtil;
|
import cn.hutool.core.map.MapUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.hutool.extra.servlet.JakartaServletUtil;
|
import cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLogFrameworkService;
|
||||||
import cn.iocoder.yudao.framework.common.exception.ServiceException;
|
import cn.iocoder.yudao.framework.common.exception.ServiceException;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLogFrameworkService;
|
|
||||||
import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
|
|
||||||
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
|
|
||||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||||
|
import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
|
||||||
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
|
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
|
||||||
|
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
|
||||||
import cn.iocoder.yudao.module.infra.api.logger.dto.ApiErrorLogCreateReqDTO;
|
import cn.iocoder.yudao.module.infra.api.logger.dto.ApiErrorLogCreateReqDTO;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
@ -32,7 +31,6 @@ import javax.validation.ConstraintViolationException;
|
||||||
import javax.validation.ValidationException;
|
import javax.validation.ValidationException;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.*;
|
import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.*;
|
||||||
|
|
||||||
|
|
@ -181,14 +179,6 @@ public class GlobalExceptionHandler {
|
||||||
return CommonResult.error(METHOD_NOT_ALLOWED.getCode(), String.format("请求方法不正确:%s", ex.getMessage()));
|
return CommonResult.error(METHOD_NOT_ALLOWED.getCode(), String.format("请求方法不正确:%s", ex.getMessage()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理 Resilience4j 限流抛出的异常
|
|
||||||
*/
|
|
||||||
public CommonResult<?> requestNotPermittedExceptionHandler(HttpServletRequest req, Throwable ex) {
|
|
||||||
log.warn("[requestNotPermittedExceptionHandler][url({}) 访问过于频繁]", req.getRequestURL(), ex);
|
|
||||||
return CommonResult.error(TOO_MANY_REQUESTS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理 Spring Security 权限不足的异常
|
* 处理 Spring Security 权限不足的异常
|
||||||
*
|
*
|
||||||
|
|
@ -223,12 +213,7 @@ public class GlobalExceptionHandler {
|
||||||
return tableNotExistsResult;
|
return tableNotExistsResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 情况二:部分特殊的库的处理
|
// 情况二:处理异常
|
||||||
if (Objects.equals("io.github.resilience4j.ratelimiter.RequestNotPermitted", ex.getClass().getName())) {
|
|
||||||
return requestNotPermittedExceptionHandler(req, ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 情况三:处理异常
|
|
||||||
log.error("[defaultExceptionHandler]", ex);
|
log.error("[defaultExceptionHandler]", ex);
|
||||||
// 插入异常日志
|
// 插入异常日志
|
||||||
createExceptionLog(req, ex);
|
createExceptionLog(req, ex);
|
||||||
|
|
|
||||||
|
|
@ -38,17 +38,6 @@
|
||||||
<artifactId>spring-boot-starter-websocket</artifactId>
|
<artifactId>spring-boot-starter-websocket</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- Web 相关 -->
|
|
||||||
<dependency>
|
|
||||||
<!-- 为什么是 websocket 依赖 security 呢?而不是 security 拓展 websocket 呢?
|
|
||||||
因为 websocket 和 LoginUser 当前登录的用户有一定的相关性,具体可见 WebSocketSessionManagerImpl 逻辑。
|
|
||||||
如果让 security 拓展 websocket 的话,会导致 websocket 组件的封装很散,进而增大理解成本。
|
|
||||||
-->
|
|
||||||
<groupId>cn.iocoder.cloud</groupId>
|
|
||||||
<artifactId>yudao-spring-boot-starter-security</artifactId>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- 消息队列相关 -->
|
<!-- 消息队列相关 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cn.iocoder.cloud</groupId>
|
<groupId>cn.iocoder.cloud</groupId>
|
||||||
|
|
|
||||||
|
|
@ -35,8 +35,6 @@ mybatis-plus:
|
||||||
|
|
||||||
# Lock4j 配置项(单元测试,禁用 Lock4j)
|
# Lock4j 配置项(单元测试,禁用 Lock4j)
|
||||||
|
|
||||||
# Resilience4j 配置项
|
|
||||||
|
|
||||||
--- #################### 监控相关配置 ####################
|
--- #################### 监控相关配置 ####################
|
||||||
|
|
||||||
--- #################### 芋道相关配置 ####################
|
--- #################### 芋道相关配置 ####################
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package cn.iocoder.yudao.module.crm.controller.admin.business;
|
package cn.iocoder.yudao.module.crm.controller.admin.business;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
|
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package cn.iocoder.yudao.module.crm.controller.admin.clue;
|
package cn.iocoder.yudao.module.crm.controller.admin.clue;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
|
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.crm.controller.admin.contact;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.lang.Assert;
|
import cn.hutool.core.lang.Assert;
|
||||||
import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
|
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.crm.controller.admin.contract;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.lang.Assert;
|
import cn.hutool.core.lang.Assert;
|
||||||
import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.crm.controller.admin.customer;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.map.MapUtil;
|
import cn.hutool.core.map.MapUtil;
|
||||||
import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
import cn.iocoder.yudao.framework.common.core.KeyValue;
|
import cn.iocoder.yudao.framework.common.core.KeyValue;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package cn.iocoder.yudao.module.crm.controller.admin.product;
|
package cn.iocoder.yudao.module.crm.controller.admin.product;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.crm.controller.admin.receivable;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.lang.Assert;
|
import cn.hutool.core.lang.Assert;
|
||||||
import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
|
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.crm.controller.admin.receivable;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.lang.Assert;
|
import cn.hutool.core.lang.Assert;
|
||||||
import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
|
import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
|
||||||
|
|
|
||||||
|
|
@ -39,8 +39,6 @@ mybatis-plus:
|
||||||
|
|
||||||
# Lock4j 配置项(单元测试,禁用 Lock4j)
|
# Lock4j 配置项(单元测试,禁用 Lock4j)
|
||||||
|
|
||||||
# Resilience4j 配置项
|
|
||||||
|
|
||||||
--- #################### 监控相关配置 ####################
|
--- #################### 监控相关配置 ####################
|
||||||
|
|
||||||
--- #################### 芋道相关配置 ####################
|
--- #################### 芋道相关配置 ####################
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package cn.iocoder.yudao.module.erp.controller.admin.finance;
|
package cn.iocoder.yudao.module.erp.controller.admin.finance;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package cn.iocoder.yudao.module.erp.controller.admin.finance;
|
package cn.iocoder.yudao.module.erp.controller.admin.finance;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package cn.iocoder.yudao.module.erp.controller.admin.finance;
|
package cn.iocoder.yudao.module.erp.controller.admin.finance;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package cn.iocoder.yudao.module.erp.controller.admin.product;
|
package cn.iocoder.yudao.module.erp.controller.admin.product;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package cn.iocoder.yudao.module.erp.controller.admin.product;
|
package cn.iocoder.yudao.module.erp.controller.admin.product;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package cn.iocoder.yudao.module.erp.controller.admin.product;
|
package cn.iocoder.yudao.module.erp.controller.admin.product;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package cn.iocoder.yudao.module.erp.controller.admin.purchase;
|
package cn.iocoder.yudao.module.erp.controller.admin.purchase;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package cn.iocoder.yudao.module.erp.controller.admin.purchase;
|
package cn.iocoder.yudao.module.erp.controller.admin.purchase;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package cn.iocoder.yudao.module.erp.controller.admin.purchase;
|
package cn.iocoder.yudao.module.erp.controller.admin.purchase;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package cn.iocoder.yudao.module.erp.controller.admin.purchase;
|
package cn.iocoder.yudao.module.erp.controller.admin.purchase;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package cn.iocoder.yudao.module.erp.controller.admin.sale;
|
package cn.iocoder.yudao.module.erp.controller.admin.sale;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package cn.iocoder.yudao.module.erp.controller.admin.sale;
|
package cn.iocoder.yudao.module.erp.controller.admin.sale;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package cn.iocoder.yudao.module.erp.controller.admin.sale;
|
package cn.iocoder.yudao.module.erp.controller.admin.sale;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package cn.iocoder.yudao.module.erp.controller.admin.sale;
|
package cn.iocoder.yudao.module.erp.controller.admin.sale;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package cn.iocoder.yudao.module.erp.controller.admin.stock;
|
package cn.iocoder.yudao.module.erp.controller.admin.stock;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package cn.iocoder.yudao.module.erp.controller.admin.stock;
|
package cn.iocoder.yudao.module.erp.controller.admin.stock;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package cn.iocoder.yudao.module.erp.controller.admin.stock;
|
package cn.iocoder.yudao.module.erp.controller.admin.stock;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package cn.iocoder.yudao.module.erp.controller.admin.stock;
|
package cn.iocoder.yudao.module.erp.controller.admin.stock;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package cn.iocoder.yudao.module.erp.controller.admin.stock;
|
package cn.iocoder.yudao.module.erp.controller.admin.stock;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package cn.iocoder.yudao.module.erp.controller.admin.stock;
|
package cn.iocoder.yudao.module.erp.controller.admin.stock;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package cn.iocoder.yudao.module.erp.controller.admin.stock;
|
package cn.iocoder.yudao.module.erp.controller.admin.stock;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package cn.iocoder.yudao.module.infra.controller.admin.config;
|
package cn.iocoder.yudao.module.infra.controller.admin.config;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package cn.iocoder.yudao.module.infra.controller.admin.demo.demo01;
|
package cn.iocoder.yudao.module.infra.controller.admin.demo.demo01;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package cn.iocoder.yudao.module.infra.controller.admin.demo.demo02;
|
package cn.iocoder.yudao.module.infra.controller.admin.demo.demo02;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||||
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
|
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package cn.iocoder.yudao.module.infra.controller.admin.demo.demo03;
|
package cn.iocoder.yudao.module.infra.controller.admin.demo.demo03;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package cn.iocoder.yudao.module.infra.controller.admin.logger;
|
package cn.iocoder.yudao.module.infra.controller.admin.logger;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package cn.iocoder.yudao.module.infra.controller.admin.logger;
|
package cn.iocoder.yudao.module.infra.controller.admin.logger;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import cn.hutool.extra.template.TemplateConfig;
|
||||||
import cn.hutool.extra.template.TemplateEngine;
|
import cn.hutool.extra.template.TemplateEngine;
|
||||||
import cn.hutool.extra.template.engine.velocity.VelocityEngine;
|
import cn.hutool.extra.template.engine.velocity.VelocityEngine;
|
||||||
import cn.hutool.system.SystemUtil;
|
import cn.hutool.system.SystemUtil;
|
||||||
import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
import cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum;
|
import cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum;
|
||||||
import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
|
import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
|
|
|
||||||
|
|
@ -41,8 +41,6 @@ mybatis-plus:
|
||||||
|
|
||||||
# Lock4j 配置项(单元测试,禁用 Lock4j)
|
# Lock4j 配置项(单元测试,禁用 Lock4j)
|
||||||
|
|
||||||
# Resilience4j 配置项
|
|
||||||
|
|
||||||
--- #################### 监控相关配置 ####################
|
--- #################### 监控相关配置 ####################
|
||||||
|
|
||||||
--- #################### 芋道相关配置 ####################
|
--- #################### 芋道相关配置 ####################
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package cn.iocoder.yudao.module.product.controller.admin.spu;
|
package cn.iocoder.yudao.module.product.controller.admin.spu;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||||
|
|
|
||||||
|
|
@ -38,8 +38,6 @@ mybatis-plus:
|
||||||
|
|
||||||
# Lock4j 配置项(单元测试,禁用 Lock4j)
|
# Lock4j 配置项(单元测试,禁用 Lock4j)
|
||||||
|
|
||||||
# Resilience4j 配置项
|
|
||||||
|
|
||||||
--- #################### 监控相关配置 ####################
|
--- #################### 监控相关配置 ####################
|
||||||
|
|
||||||
--- #################### 芋道相关配置 ####################
|
--- #################### 芋道相关配置 ####################
|
||||||
|
|
|
||||||
|
|
@ -37,8 +37,6 @@ mybatis:
|
||||||
|
|
||||||
# Lock4j 配置项(单元测试,禁用 Lock4j)
|
# Lock4j 配置项(单元测试,禁用 Lock4j)
|
||||||
|
|
||||||
# Resilience4j 配置项
|
|
||||||
|
|
||||||
--- #################### 监控相关配置 ####################
|
--- #################### 监控相关配置 ####################
|
||||||
|
|
||||||
--- #################### 芋道相关配置 ####################
|
--- #################### 芋道相关配置 ####################
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package cn.iocoder.yudao.module.trade.controller.admin.delivery;
|
package cn.iocoder.yudao.module.trade.controller.admin.delivery;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
|
|
||||||
|
|
@ -37,8 +37,6 @@ mybatis:
|
||||||
|
|
||||||
# Lock4j 配置项(单元测试,禁用 Lock4j)
|
# Lock4j 配置项(单元测试,禁用 Lock4j)
|
||||||
|
|
||||||
# Resilience4j 配置项
|
|
||||||
|
|
||||||
--- #################### 监控相关配置 ####################
|
--- #################### 监控相关配置 ####################
|
||||||
|
|
||||||
--- #################### 芋道相关配置 ####################
|
--- #################### 芋道相关配置 ####################
|
||||||
|
|
|
||||||
|
|
@ -37,8 +37,6 @@ mybatis:
|
||||||
|
|
||||||
# Lock4j 配置项(单元测试,禁用 Lock4j)
|
# Lock4j 配置项(单元测试,禁用 Lock4j)
|
||||||
|
|
||||||
# Resilience4j 配置项
|
|
||||||
|
|
||||||
--- #################### 监控相关配置 ####################
|
--- #################### 监控相关配置 ####################
|
||||||
|
|
||||||
--- #################### 芋道相关配置 ####################
|
--- #################### 芋道相关配置 ####################
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package cn.iocoder.yudao.module.pay.controller.admin.order;
|
package cn.iocoder.yudao.module.pay.controller.admin.order;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollectionUtil;
|
import cn.hutool.core.collection.CollectionUtil;
|
||||||
import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
|
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package cn.iocoder.yudao.module.pay.controller.admin.refund;
|
package cn.iocoder.yudao.module.pay.controller.admin.refund;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollectionUtil;
|
import cn.hutool.core.collection.CollectionUtil;
|
||||||
import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
|
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
|
||||||
|
|
|
||||||
|
|
@ -70,16 +70,6 @@ mybatis-plus:
|
||||||
|
|
||||||
# Lock4j 配置项(单元测试,禁用 Lock4j)
|
# Lock4j 配置项(单元测试,禁用 Lock4j)
|
||||||
|
|
||||||
# Resilience4j 配置项
|
|
||||||
resilience4j:
|
|
||||||
ratelimiter:
|
|
||||||
instances:
|
|
||||||
backendA:
|
|
||||||
limit-for-period: 1 # 每个周期内,允许的请求数。默认为 50
|
|
||||||
limit-refresh-period: 60s # 每个周期的时长,单位:微秒。默认为 500
|
|
||||||
timeout-duration: 1s # 被限流时,阻塞等待的时长,单位:微秒。默认为 5s
|
|
||||||
register-health-indicator: true # 是否注册到健康监测
|
|
||||||
|
|
||||||
--- #################### 监控相关配置 ####################
|
--- #################### 监控相关配置 ####################
|
||||||
|
|
||||||
--- #################### 芋道相关配置 ####################
|
--- #################### 芋道相关配置 ####################
|
||||||
|
|
|
||||||
|
|
@ -42,8 +42,6 @@ mybatis-plus:
|
||||||
|
|
||||||
# Lock4j 配置项(单元测试,禁用 Lock4j)
|
# Lock4j 配置项(单元测试,禁用 Lock4j)
|
||||||
|
|
||||||
# Resilience4j 配置项
|
|
||||||
|
|
||||||
--- #################### 监控相关配置 ####################
|
--- #################### 监控相关配置 ####################
|
||||||
|
|
||||||
--- #################### 芋道相关配置 ####################
|
--- #################### 芋道相关配置 ####################
|
||||||
|
|
|
||||||
|
|
@ -41,8 +41,6 @@ mybatis-plus:
|
||||||
|
|
||||||
# Lock4j 配置项(单元测试,禁用 Lock4j)
|
# Lock4j 配置项(单元测试,禁用 Lock4j)
|
||||||
|
|
||||||
# Resilience4j 配置项
|
|
||||||
|
|
||||||
--- #################### 监控相关配置 ####################
|
--- #################### 监控相关配置 ####################
|
||||||
|
|
||||||
--- #################### 芋道相关配置 ####################
|
--- #################### 芋道相关配置 ####################
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package cn.iocoder.yudao.module.system.controller.admin.dept;
|
package cn.iocoder.yudao.module.system.controller.admin.dept;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package cn.iocoder.yudao.module.system.controller.admin.dict;
|
package cn.iocoder.yudao.module.system.controller.admin.dict;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package cn.iocoder.yudao.module.system.controller.admin.dict;
|
package cn.iocoder.yudao.module.system.controller.admin.dict;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package cn.iocoder.yudao.module.system.controller.admin.errorcode;
|
package cn.iocoder.yudao.module.system.controller.admin.errorcode;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package cn.iocoder.yudao.module.system.controller.admin.logger;
|
package cn.iocoder.yudao.module.system.controller.admin.logger;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package cn.iocoder.yudao.module.system.controller.admin.logger;
|
package cn.iocoder.yudao.module.system.controller.admin.logger;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package cn.iocoder.yudao.module.system.controller.admin.notify;
|
package cn.iocoder.yudao.module.system.controller.admin.notify;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package cn.iocoder.yudao.module.system.controller.admin.permission;
|
package cn.iocoder.yudao.module.system.controller.admin.permission;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package cn.iocoder.yudao.module.system.controller.admin.sensitiveword;
|
package cn.iocoder.yudao.module.system.controller.admin.sensitiveword;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package cn.iocoder.yudao.module.system.controller.admin.sms;
|
package cn.iocoder.yudao.module.system.controller.admin.sms;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package cn.iocoder.yudao.module.system.controller.admin.sms;
|
package cn.iocoder.yudao.module.system.controller.admin.sms;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package cn.iocoder.yudao.module.system.controller.admin.tenant;
|
package cn.iocoder.yudao.module.system.controller.admin.tenant;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package cn.iocoder.yudao.module.system.controller.admin.user;
|
package cn.iocoder.yudao.module.system.controller.admin.user;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import cn.iocoder.yudao.module.system.enums.permission.MenuTypeEnum;
|
||||||
import cn.iocoder.yudao.module.system.service.tenant.TenantService;
|
import cn.iocoder.yudao.module.system.service.tenant.TenantService;
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.compress.utils.Lists;
|
||||||
import org.springframework.cache.annotation.CacheEvict;
|
import org.springframework.cache.annotation.CacheEvict;
|
||||||
import org.springframework.cache.annotation.Cacheable;
|
import org.springframework.cache.annotation.Cacheable;
|
||||||
import org.springframework.context.annotation.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
|
|
@ -130,6 +131,10 @@ public class MenuServiceImpl implements MenuService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<MenuDO> getMenuList(Collection<Long> ids) {
|
public List<MenuDO> getMenuList(Collection<Long> ids) {
|
||||||
|
// 当ids为空时,返回一个空的实例对象
|
||||||
|
if (CollUtil.isEmpty(ids)) {
|
||||||
|
return Lists.newArrayList();
|
||||||
|
}
|
||||||
return menuMapper.selectBatchIds(ids);
|
return menuMapper.selectBatchIds(ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -74,16 +74,6 @@ mybatis:
|
||||||
|
|
||||||
# Lock4j 配置项(单元测试,禁用 Lock4j)
|
# Lock4j 配置项(单元测试,禁用 Lock4j)
|
||||||
|
|
||||||
# Resilience4j 配置项
|
|
||||||
resilience4j:
|
|
||||||
ratelimiter:
|
|
||||||
instances:
|
|
||||||
backendA:
|
|
||||||
limit-for-period: 1 # 每个周期内,允许的请求数。默认为 50
|
|
||||||
limit-refresh-period: 60s # 每个周期的时长,单位:微秒。默认为 500
|
|
||||||
timeout-duration: 1s # 被限流时,阻塞等待的时长,单位:微秒。默认为 5s
|
|
||||||
register-health-indicator: true # 是否注册到健康监测
|
|
||||||
|
|
||||||
--- #################### 监控相关配置 ####################
|
--- #################### 监控相关配置 ####################
|
||||||
|
|
||||||
--- #################### 芋道相关配置 ####################
|
--- #################### 芋道相关配置 ####################
|
||||||
|
|
|
||||||
|
|
@ -42,8 +42,6 @@ mybatis-plus:
|
||||||
|
|
||||||
# Lock4j 配置项(单元测试,禁用 Lock4j)
|
# Lock4j 配置项(单元测试,禁用 Lock4j)
|
||||||
|
|
||||||
# Resilience4j 配置项
|
|
||||||
|
|
||||||
--- #################### 监控相关配置 ####################
|
--- #################### 监控相关配置 ####################
|
||||||
|
|
||||||
--- #################### 芋道相关配置 ####################
|
--- #################### 芋道相关配置 ####################
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue