mirror of
https://github.com/dromara/RuoYi-Vue-Plus.git
synced 2025-09-24 07:19:46 +08:00
Merge remote-tracking branch 'origin/dev' into satoken
# Conflicts: # pom.xml # ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java # ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java # ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java # ruoyi-common/pom.xml # ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java # ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginUser.java # ruoyi-common/src/main/java/com/ruoyi/common/utils/SecurityUtils.java # ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestDemoController.java # ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java # ruoyi-framework/src/main/java/com/ruoyi/framework/security/handle/LogoutSuccessHandlerImpl.java # ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/PermissionService.java # ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java # ruoyi-system/src/main/java/com/ruoyi/system/service/SysLoginService.java # ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java # ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java # ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TokenServiceImpl.java # ruoyi-system/src/main/java/com/ruoyi/system/service/impl/UserDetailsServiceImpl.java
This commit is contained in:
@ -46,23 +46,33 @@
|
||||
<artifactId>druid-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- dynamic-datasource 多数据源-->
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<!-- sql性能分析插件 -->
|
||||
<dependency>
|
||||
<groupId>p6spy</groupId>
|
||||
<artifactId>p6spy</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>de.codecentric</groupId>
|
||||
<artifactId>spring-boot-admin-starter-client</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 系统模块-->
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-common</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.yomahub</groupId>
|
||||
<artifactId>tlog-web-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
@ -12,15 +12,15 @@ import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Before;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 数据过滤处理
|
||||
*
|
||||
* @author Lion Li
|
||||
* @deprecated 3.6.0 移除 {@link com.ruoyi.framework.handler.PlusDataPermissionHandler}
|
||||
*/
|
||||
@Aspect
|
||||
@Component
|
||||
@Deprecated
|
||||
public class DataScopeAspect {
|
||||
|
||||
/**
|
||||
@ -131,9 +131,6 @@ public class DataScopeAspect {
|
||||
if (params instanceof BaseEntity) {
|
||||
BaseEntity baseEntity = (BaseEntity) params;
|
||||
baseEntity.getParams().put(DATA_SCOPE, sql);
|
||||
} else {
|
||||
Map<String, Object> invoke = ReflectUtils.invokeGetter(params, "params");
|
||||
invoke.put(DATA_SCOPE, sql);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,10 +18,12 @@ import java.util.Objects;
|
||||
* 多数据源处理
|
||||
*
|
||||
* @author Lion Li
|
||||
* @deprecated 3.6.0 移除 使用原生方法处理 功能更全
|
||||
*/
|
||||
@Aspect
|
||||
@Order(-500)
|
||||
@Component
|
||||
@Deprecated
|
||||
public class DataSourceAspect {
|
||||
|
||||
@Pointcut("@annotation(com.ruoyi.common.annotation.DataSource)"
|
||||
|
@ -54,7 +54,7 @@ public class RateLimiterAspect {
|
||||
stringBuffer.append(ServletUtils.getClientIP()).append("-");
|
||||
} else if (rateLimiter.limitType() == LimitType.CLUSTER){
|
||||
// 获取客户端实例id
|
||||
stringBuffer.append(RedisUtils.getClientId()).append("-");
|
||||
stringBuffer.append(RedisUtils.getClient().getId()).append("-");
|
||||
}
|
||||
MethodSignature signature = (MethodSignature) point.getSignature();
|
||||
Method method = signature.getMethod();
|
||||
|
@ -1,6 +1,9 @@
|
||||
package com.ruoyi.framework.config;
|
||||
|
||||
import cn.hutool.core.net.NetUtil;
|
||||
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
|
||||
import com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator;
|
||||
import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator;
|
||||
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
|
||||
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
|
||||
import com.baomidou.mybatisplus.core.injector.ISqlInjector;
|
||||
@ -10,6 +13,7 @@ import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInt
|
||||
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
|
||||
import com.ruoyi.common.core.mybatisplus.methods.InsertAll;
|
||||
import com.ruoyi.framework.handler.CreateAndUpdateMetaObjectHandler;
|
||||
import com.ruoyi.framework.interceptor.PlusDataPermissionInterceptor;
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@ -30,6 +34,8 @@ public class MybatisPlusConfig {
|
||||
@Bean
|
||||
public MybatisPlusInterceptor mybatisPlusInterceptor() {
|
||||
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
|
||||
// 数据权限处理
|
||||
interceptor.addInnerInterceptor(dataPermissionInterceptor());
|
||||
// 分页插件
|
||||
interceptor.addInnerInterceptor(paginationInnerInterceptor());
|
||||
// 乐观锁插件
|
||||
@ -37,6 +43,13 @@ public class MybatisPlusConfig {
|
||||
return interceptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据权限拦截器
|
||||
*/
|
||||
public PlusDataPermissionInterceptor dataPermissionInterceptor() {
|
||||
return new PlusDataPermissionInterceptor();
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页插件,自动识别数据库类型
|
||||
*/
|
||||
@ -79,24 +92,33 @@ public class MybatisPlusConfig {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用网卡信息绑定雪花生成器
|
||||
* 防止集群雪花ID重复
|
||||
*/
|
||||
@Bean
|
||||
public IdentifierGenerator idGenerator() {
|
||||
return new DefaultIdentifierGenerator(NetUtil.getLocalhost());
|
||||
}
|
||||
|
||||
/**
|
||||
* PaginationInnerInterceptor 分页插件,自动识别数据库类型
|
||||
* https://baomidou.com/guide/interceptor-pagination.html
|
||||
* https://baomidou.com/pages/97710a/
|
||||
* OptimisticLockerInnerInterceptor 乐观锁插件
|
||||
* https://baomidou.com/guide/interceptor-optimistic-locker.html
|
||||
* https://baomidou.com/pages/0d93c0/
|
||||
* MetaObjectHandler 元对象字段填充控制器
|
||||
* https://baomidou.com/guide/auto-fill-metainfo.html
|
||||
* https://baomidou.com/pages/4c6bcf/
|
||||
* ISqlInjector sql注入器
|
||||
* https://baomidou.com/guide/sql-injector.html
|
||||
* https://baomidou.com/pages/42ea4a/
|
||||
* BlockAttackInnerInterceptor 如果是对全表的删除或更新操作,就会终止该操作
|
||||
* https://baomidou.com/guide/interceptor-block-attack.html
|
||||
* https://baomidou.com/pages/f9a237/
|
||||
* IllegalSQLInnerInterceptor sql性能规范插件(垃圾SQL拦截)
|
||||
* IdentifierGenerator 自定义主键策略
|
||||
* https://baomidou.com/guide/id-generator.html
|
||||
* https://baomidou.com/pages/568eb2/
|
||||
* TenantLineInnerInterceptor 多租户插件
|
||||
* https://baomidou.com/guide/interceptor-tenant-line.html
|
||||
* https://baomidou.com/pages/aef2f2/
|
||||
* DynamicTableNameInnerInterceptor 动态表名插件
|
||||
* https://baomidou.com/guide/interceptor-dynamic-table-name.html
|
||||
* https://baomidou.com/pages/2a45ff/
|
||||
*/
|
||||
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* redis配置
|
||||
@ -34,158 +35,164 @@ import java.util.Map;
|
||||
@EnableCaching
|
||||
public class RedisConfig extends CachingConfigurerSupport {
|
||||
|
||||
private static final String REDIS_PROTOCOL_PREFIX = "redis://";
|
||||
private static final String REDISS_PROTOCOL_PREFIX = "rediss://";
|
||||
private static final String REDIS_PROTOCOL_PREFIX = "redis://";
|
||||
private static final String REDISS_PROTOCOL_PREFIX = "rediss://";
|
||||
|
||||
@Autowired
|
||||
private RedisProperties redisProperties;
|
||||
@Autowired
|
||||
private RedisProperties redisProperties;
|
||||
|
||||
@Autowired
|
||||
private RedissonProperties redissonProperties;
|
||||
@Autowired
|
||||
private RedissonProperties redissonProperties;
|
||||
|
||||
@Bean(destroyMethod = "shutdown")
|
||||
@ConditionalOnMissingBean(RedissonClient.class)
|
||||
public RedissonClient redisson() throws IOException {
|
||||
String prefix = REDIS_PROTOCOL_PREFIX;
|
||||
if (redisProperties.isSsl()) {
|
||||
prefix = REDISS_PROTOCOL_PREFIX;
|
||||
}
|
||||
Config config = new Config();
|
||||
config.setThreads(redissonProperties.getThreads())
|
||||
.setNettyThreads(redissonProperties.getNettyThreads())
|
||||
.setCodec(JsonJacksonCodec.INSTANCE)
|
||||
.setTransportMode(redissonProperties.getTransportMode());
|
||||
@Bean(destroyMethod = "shutdown")
|
||||
@ConditionalOnMissingBean(RedissonClient.class)
|
||||
public RedissonClient redisson() throws IOException {
|
||||
String prefix = REDIS_PROTOCOL_PREFIX;
|
||||
if (redisProperties.isSsl()) {
|
||||
prefix = REDISS_PROTOCOL_PREFIX;
|
||||
}
|
||||
Config config = new Config();
|
||||
config.setThreads(redissonProperties.getThreads())
|
||||
.setNettyThreads(redissonProperties.getNettyThreads())
|
||||
.setCodec(JsonJacksonCodec.INSTANCE)
|
||||
.setTransportMode(redissonProperties.getTransportMode());
|
||||
|
||||
RedissonProperties.SingleServerConfig singleServerConfig = redissonProperties.getSingleServerConfig();
|
||||
if (ObjectUtil.isNotNull(singleServerConfig)) {
|
||||
// 使用单机模式
|
||||
config.useSingleServer()
|
||||
.setAddress(prefix + redisProperties.getHost() + ":" + redisProperties.getPort())
|
||||
.setConnectTimeout(((Long) redisProperties.getTimeout().toMillis()).intValue())
|
||||
.setDatabase(redisProperties.getDatabase())
|
||||
.setPassword(StringUtils.isNotBlank(redisProperties.getPassword()) ? redisProperties.getPassword() : null)
|
||||
.setTimeout(singleServerConfig.getTimeout())
|
||||
.setRetryAttempts(singleServerConfig.getRetryAttempts())
|
||||
.setRetryInterval(singleServerConfig.getRetryInterval())
|
||||
.setSubscriptionsPerConnection(singleServerConfig.getSubscriptionsPerConnection())
|
||||
.setClientName(singleServerConfig.getClientName())
|
||||
.setIdleConnectionTimeout(singleServerConfig.getIdleConnectionTimeout())
|
||||
.setSubscriptionConnectionMinimumIdleSize(singleServerConfig.getSubscriptionConnectionMinimumIdleSize())
|
||||
.setSubscriptionConnectionPoolSize(singleServerConfig.getSubscriptionConnectionPoolSize())
|
||||
.setConnectionMinimumIdleSize(singleServerConfig.getConnectionMinimumIdleSize())
|
||||
.setConnectionPoolSize(singleServerConfig.getConnectionPoolSize())
|
||||
.setDnsMonitoringInterval(singleServerConfig.getDnsMonitoringInterval());
|
||||
}
|
||||
// 集群配置方式 参考下方注释
|
||||
RedissonProperties.ClusterServersConfig clusterServersConfig = redissonProperties.getClusterServersConfig();
|
||||
if (ObjectUtil.isNotNull(clusterServersConfig)) {
|
||||
// 使用集群模式
|
||||
config.useClusterServers()
|
||||
.setConnectTimeout(((Long) redisProperties.getTimeout().toMillis()).intValue())
|
||||
.setPassword(StringUtils.isNotBlank(redisProperties.getPassword()) ? redisProperties.getPassword() : null)
|
||||
.setTimeout(clusterServersConfig.getTimeout())
|
||||
.setRetryAttempts(clusterServersConfig.getRetryAttempts())
|
||||
.setRetryInterval(clusterServersConfig.getRetryInterval())
|
||||
.setSubscriptionsPerConnection(clusterServersConfig.getSubscriptionsPerConnection())
|
||||
.setClientName(clusterServersConfig.getClientName())
|
||||
.setIdleConnectionTimeout(clusterServersConfig.getIdleConnectionTimeout())
|
||||
.setPingConnectionInterval(clusterServersConfig.getPingConnectionInterval())
|
||||
.setSubscriptionConnectionMinimumIdleSize(clusterServersConfig.getSubscriptionConnectionMinimumIdleSize())
|
||||
.setSubscriptionConnectionPoolSize(clusterServersConfig.getSubscriptionConnectionPoolSize())
|
||||
.setMasterConnectionMinimumIdleSize(clusterServersConfig.getMasterConnectionMinimumIdleSize())
|
||||
.setMasterConnectionPoolSize(clusterServersConfig.getMasterConnectionPoolSize())
|
||||
.setSlaveConnectionMinimumIdleSize(clusterServersConfig.getSlaveConnectionMinimumIdleSize())
|
||||
.setSlaveConnectionPoolSize(clusterServersConfig.getSlaveConnectionPoolSize())
|
||||
.setDnsMonitoringInterval(clusterServersConfig.getDnsMonitoringInterval())
|
||||
.setFailedSlaveReconnectionInterval(clusterServersConfig.getFailedSlaveReconnectionInterval())
|
||||
.setScanInterval(clusterServersConfig.getScanInterval())
|
||||
.setReadMode(clusterServersConfig.getReadMode())
|
||||
.setSubscriptionMode(clusterServersConfig.getSubscriptionMode())
|
||||
.setNodeAddresses(redisProperties.getCluster().getNodes());
|
||||
}
|
||||
RedissonClient redissonClient = Redisson.create(config);
|
||||
log.info("初始化 redis 配置");
|
||||
return redissonClient;
|
||||
}
|
||||
RedissonProperties.SingleServerConfig singleServerConfig = redissonProperties.getSingleServerConfig();
|
||||
if (ObjectUtil.isNotNull(singleServerConfig)) {
|
||||
// 使用单机模式
|
||||
config.useSingleServer()
|
||||
.setAddress(prefix + redisProperties.getHost() + ":" + redisProperties.getPort())
|
||||
.setConnectTimeout(((Long) redisProperties.getTimeout().toMillis()).intValue())
|
||||
.setDatabase(redisProperties.getDatabase())
|
||||
.setPassword(StringUtils.isNotBlank(redisProperties.getPassword()) ? redisProperties.getPassword() : null)
|
||||
.setTimeout(singleServerConfig.getTimeout())
|
||||
.setRetryAttempts(singleServerConfig.getRetryAttempts())
|
||||
.setRetryInterval(singleServerConfig.getRetryInterval())
|
||||
.setSubscriptionsPerConnection(singleServerConfig.getSubscriptionsPerConnection())
|
||||
.setClientName(singleServerConfig.getClientName())
|
||||
.setIdleConnectionTimeout(singleServerConfig.getIdleConnectionTimeout())
|
||||
.setSubscriptionConnectionMinimumIdleSize(singleServerConfig.getSubscriptionConnectionMinimumIdleSize())
|
||||
.setSubscriptionConnectionPoolSize(singleServerConfig.getSubscriptionConnectionPoolSize())
|
||||
.setConnectionMinimumIdleSize(singleServerConfig.getConnectionMinimumIdleSize())
|
||||
.setConnectionPoolSize(singleServerConfig.getConnectionPoolSize())
|
||||
.setDnsMonitoringInterval(singleServerConfig.getDnsMonitoringInterval());
|
||||
}
|
||||
// 集群配置方式 参考下方注释
|
||||
RedissonProperties.ClusterServersConfig clusterServersConfig = redissonProperties.getClusterServersConfig();
|
||||
if (ObjectUtil.isNotNull(clusterServersConfig)) {
|
||||
// 使用集群模式
|
||||
String finalPrefix = prefix;
|
||||
List<String> nodes = redisProperties.getCluster().getNodes()
|
||||
.stream()
|
||||
.map(node -> finalPrefix + node)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
/**
|
||||
* 整合spring-cache
|
||||
*/
|
||||
@Bean
|
||||
public CacheManager cacheManager(RedissonClient redissonClient) {
|
||||
List<RedissonProperties.CacheGroup> cacheGroup = redissonProperties.getCacheGroup();
|
||||
Map<String, CacheConfig> config = new HashMap<>();
|
||||
for (RedissonProperties.CacheGroup group : cacheGroup) {
|
||||
CacheConfig cacheConfig = new CacheConfig(group.getTtl(), group.getMaxIdleTime());
|
||||
cacheConfig.setMaxSize(group.getMaxSize());
|
||||
config.put(group.getGroupId(), cacheConfig);
|
||||
}
|
||||
return new RedissonSpringCacheManager(redissonClient, config, JsonJacksonCodec.INSTANCE);
|
||||
}
|
||||
config.useClusterServers()
|
||||
.setConnectTimeout(((Long) redisProperties.getTimeout().toMillis()).intValue())
|
||||
.setPassword(StringUtils.isNotBlank(redisProperties.getPassword()) ? redisProperties.getPassword() : null)
|
||||
.setTimeout(clusterServersConfig.getTimeout())
|
||||
.setRetryAttempts(clusterServersConfig.getRetryAttempts())
|
||||
.setRetryInterval(clusterServersConfig.getRetryInterval())
|
||||
.setSubscriptionsPerConnection(clusterServersConfig.getSubscriptionsPerConnection())
|
||||
.setClientName(clusterServersConfig.getClientName())
|
||||
.setIdleConnectionTimeout(clusterServersConfig.getIdleConnectionTimeout())
|
||||
.setPingConnectionInterval(clusterServersConfig.getPingConnectionInterval())
|
||||
.setSubscriptionConnectionMinimumIdleSize(clusterServersConfig.getSubscriptionConnectionMinimumIdleSize())
|
||||
.setSubscriptionConnectionPoolSize(clusterServersConfig.getSubscriptionConnectionPoolSize())
|
||||
.setMasterConnectionMinimumIdleSize(clusterServersConfig.getMasterConnectionMinimumIdleSize())
|
||||
.setMasterConnectionPoolSize(clusterServersConfig.getMasterConnectionPoolSize())
|
||||
.setSlaveConnectionMinimumIdleSize(clusterServersConfig.getSlaveConnectionMinimumIdleSize())
|
||||
.setSlaveConnectionPoolSize(clusterServersConfig.getSlaveConnectionPoolSize())
|
||||
.setDnsMonitoringInterval(clusterServersConfig.getDnsMonitoringInterval())
|
||||
.setFailedSlaveReconnectionInterval(clusterServersConfig.getFailedSlaveReconnectionInterval())
|
||||
.setScanInterval(clusterServersConfig.getScanInterval())
|
||||
.setReadMode(clusterServersConfig.getReadMode())
|
||||
.setSubscriptionMode(clusterServersConfig.getSubscriptionMode())
|
||||
.setNodeAddresses(nodes);
|
||||
}
|
||||
RedissonClient redissonClient = Redisson.create(config);
|
||||
log.info("初始化 redis 配置");
|
||||
return redissonClient;
|
||||
}
|
||||
|
||||
/**
|
||||
* redis集群配置 yml
|
||||
*
|
||||
* --- # redis 集群配置(单机与集群只能开启一个另一个需要注释掉)
|
||||
* spring:
|
||||
* redis:
|
||||
* cluster:
|
||||
* nodes:
|
||||
* - 192.168.0.100:6379
|
||||
* - 192.168.0.101:6379
|
||||
* - 192.168.0.102:6379
|
||||
* # 密码
|
||||
* password:
|
||||
* # 连接超时时间
|
||||
* timeout: 10s
|
||||
* # 是否开启ssl
|
||||
* ssl: false
|
||||
*
|
||||
* redisson:
|
||||
* # 线程池数量
|
||||
* threads: 16
|
||||
* # Netty线程池数量
|
||||
* nettyThreads: 32
|
||||
* # 传输模式
|
||||
* transportMode: "NIO"
|
||||
* # 集群配置
|
||||
* clusterServersConfig:
|
||||
* # 客户端名称
|
||||
* clientName: ${ruoyi.name}
|
||||
* # master最小空闲连接数
|
||||
* masterConnectionMinimumIdleSize: 32
|
||||
* # master连接池大小
|
||||
* masterConnectionPoolSize: 64
|
||||
* # slave最小空闲连接数
|
||||
* slaveConnectionMinimumIdleSize: 32
|
||||
* # slave连接池大小
|
||||
* slaveConnectionPoolSize: 64
|
||||
* # 连接空闲超时,单位:毫秒
|
||||
* idleConnectionTimeout: 10000
|
||||
* # ping连接间隔
|
||||
* pingConnectionInterval: 1000
|
||||
* # 命令等待超时,单位:毫秒
|
||||
* timeout: 3000
|
||||
* # 如果尝试在此限制之内发送成功,则开始启用 timeout 计时。
|
||||
* retryAttempts: 3
|
||||
* # 命令重试发送时间间隔,单位:毫秒
|
||||
* retryInterval: 1500
|
||||
* # 从可用服务器的内部列表中排除 Redis Slave 重新连接尝试的间隔。
|
||||
* failedSlaveReconnectionInterval: 3000
|
||||
* # 发布和订阅连接池最小空闲连接数
|
||||
* subscriptionConnectionMinimumIdleSize: 1
|
||||
* # 发布和订阅连接池大小
|
||||
* subscriptionConnectionPoolSize: 50
|
||||
* # 单个连接最大订阅数量
|
||||
* subscriptionsPerConnection: 5
|
||||
* # 扫描间隔
|
||||
* scanInterval: 1000
|
||||
* # DNS监测时间间隔,单位:毫秒
|
||||
* dnsMonitoringInterval: 5000
|
||||
* # 读取模式
|
||||
* readMode: "SLAVE"
|
||||
* # 订阅模式
|
||||
* subscriptionMode: "MASTER"
|
||||
*/
|
||||
/**
|
||||
* 整合spring-cache
|
||||
*/
|
||||
@Bean
|
||||
public CacheManager cacheManager(RedissonClient redissonClient) {
|
||||
List<RedissonProperties.CacheGroup> cacheGroup = redissonProperties.getCacheGroup();
|
||||
Map<String, CacheConfig> config = new HashMap<>();
|
||||
for (RedissonProperties.CacheGroup group : cacheGroup) {
|
||||
CacheConfig cacheConfig = new CacheConfig(group.getTtl(), group.getMaxIdleTime());
|
||||
cacheConfig.setMaxSize(group.getMaxSize());
|
||||
config.put(group.getGroupId(), cacheConfig);
|
||||
}
|
||||
return new RedissonSpringCacheManager(redissonClient, config, JsonJacksonCodec.INSTANCE);
|
||||
}
|
||||
|
||||
/**
|
||||
* redis集群配置 yml
|
||||
*
|
||||
* --- # redis 集群配置(单机与集群只能开启一个另一个需要注释掉)
|
||||
* spring:
|
||||
* redis:
|
||||
* cluster:
|
||||
* nodes:
|
||||
* - 192.168.0.100:6379
|
||||
* - 192.168.0.101:6379
|
||||
* - 192.168.0.102:6379
|
||||
* # 密码
|
||||
* password:
|
||||
* # 连接超时时间
|
||||
* timeout: 10s
|
||||
* # 是否开启ssl
|
||||
* ssl: false
|
||||
*
|
||||
* redisson:
|
||||
* # 线程池数量
|
||||
* threads: 16
|
||||
* # Netty线程池数量
|
||||
* nettyThreads: 32
|
||||
* # 传输模式
|
||||
* transportMode: "NIO"
|
||||
* # 集群配置
|
||||
* clusterServersConfig:
|
||||
* # 客户端名称
|
||||
* clientName: ${ruoyi.name}
|
||||
* # master最小空闲连接数
|
||||
* masterConnectionMinimumIdleSize: 32
|
||||
* # master连接池大小
|
||||
* masterConnectionPoolSize: 64
|
||||
* # slave最小空闲连接数
|
||||
* slaveConnectionMinimumIdleSize: 32
|
||||
* # slave连接池大小
|
||||
* slaveConnectionPoolSize: 64
|
||||
* # 连接空闲超时,单位:毫秒
|
||||
* idleConnectionTimeout: 10000
|
||||
* # ping连接间隔
|
||||
* pingConnectionInterval: 1000
|
||||
* # 命令等待超时,单位:毫秒
|
||||
* timeout: 3000
|
||||
* # 如果尝试在此限制之内发送成功,则开始启用 timeout 计时。
|
||||
* retryAttempts: 3
|
||||
* # 命令重试发送时间间隔,单位:毫秒
|
||||
* retryInterval: 1500
|
||||
* # 从可用服务器的内部列表中排除 Redis Slave 重新连接尝试的间隔。
|
||||
* failedSlaveReconnectionInterval: 3000
|
||||
* # 发布和订阅连接池最小空闲连接数
|
||||
* subscriptionConnectionMinimumIdleSize: 1
|
||||
* # 发布和订阅连接池大小
|
||||
* subscriptionConnectionPoolSize: 50
|
||||
* # 单个连接最大订阅数量
|
||||
* subscriptionsPerConnection: 5
|
||||
* # 扫描间隔
|
||||
* scanInterval: 1000
|
||||
* # DNS监测时间间隔,单位:毫秒
|
||||
* dnsMonitoringInterval: 5000
|
||||
* # 读取模式
|
||||
* readMode: "SLAVE"
|
||||
* # 订阅模式
|
||||
* subscriptionMode: "MASTER"
|
||||
*/
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
package com.ruoyi.framework.config;
|
||||
|
||||
import com.ruoyi.framework.Interceptor.PlusWebInvokeTimeInterceptor;
|
||||
import com.ruoyi.framework.interceptor.PlusWebInvokeTimeInterceptor;
|
||||
import com.yomahub.tlog.web.interceptor.TLogWebInterceptor;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
@ -1,13 +1,8 @@
|
||||
package com.ruoyi.framework.config;
|
||||
|
||||
import com.yomahub.tlog.core.aop.AspectLogAop;
|
||||
import com.yomahub.tlog.spring.TLogPropertyInit;
|
||||
import com.yomahub.tlog.spring.TLogSpringAware;
|
||||
import com.yomahub.tlog.springboot.property.TLogProperty;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import com.yomahub.tlog.springboot.TLogWebAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.core.annotation.Order;
|
||||
|
||||
/**
|
||||
* 整合 TLog 框架配置
|
||||
@ -15,29 +10,9 @@ import org.springframework.core.annotation.Order;
|
||||
* @author Lion Li
|
||||
* @since 3.3.0
|
||||
*/
|
||||
@Order(-999)
|
||||
@Configuration
|
||||
@Import(TLogProperty.class)
|
||||
// 排除 web 自动配置 自定义实现
|
||||
@EnableAutoConfiguration(exclude = TLogWebAutoConfiguration.class)
|
||||
public class TLogConfig {
|
||||
|
||||
@Bean
|
||||
public TLogPropertyInit tLogPropertyInit(TLogProperty tLogProperty) {
|
||||
TLogPropertyInit tLogPropertyInit = new TLogPropertyInit();
|
||||
tLogPropertyInit.setPattern(tLogProperty.getPattern());
|
||||
tLogPropertyInit.setEnableInvokeTimePrint(tLogProperty.enableInvokeTimePrint());
|
||||
tLogPropertyInit.setIdGenerator(tLogProperty.getIdGenerator());
|
||||
tLogPropertyInit.setMdcEnable(tLogProperty.getMdcEnable());
|
||||
return tLogPropertyInit;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public TLogSpringAware tLogSpringAware(){
|
||||
return new TLogSpringAware();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AspectLogAop aspectLogAop() {
|
||||
return new AspectLogAop();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,192 @@
|
||||
package com.ruoyi.framework.handler;
|
||||
|
||||
import cn.hutool.core.annotation.AnnotationUtil;
|
||||
import cn.hutool.core.collection.ConcurrentHashSet;
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.hutool.core.util.ClassUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.ruoyi.common.annotation.DataColumn;
|
||||
import com.ruoyi.common.annotation.DataPermission;
|
||||
import com.ruoyi.common.core.domain.entity.SysRole;
|
||||
import com.ruoyi.common.core.domain.entity.SysUser;
|
||||
import com.ruoyi.common.core.service.UserService;
|
||||
import com.ruoyi.common.enums.DataScopeType;
|
||||
import com.ruoyi.common.exception.ServiceException;
|
||||
import com.ruoyi.common.helper.DataPermissionHelper;
|
||||
import com.ruoyi.common.utils.SecurityUtils;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.common.utils.spring.SpringUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.sf.jsqlparser.JSQLParserException;
|
||||
import net.sf.jsqlparser.expression.Expression;
|
||||
import net.sf.jsqlparser.expression.Parenthesis;
|
||||
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
|
||||
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
|
||||
import org.springframework.context.expression.BeanFactoryResolver;
|
||||
import org.springframework.expression.BeanResolver;
|
||||
import org.springframework.expression.ExpressionParser;
|
||||
import org.springframework.expression.ParserContext;
|
||||
import org.springframework.expression.common.TemplateParserContext;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 数据权限过滤
|
||||
*
|
||||
* @author Lion Li
|
||||
* @version 3.5.0
|
||||
*/
|
||||
@Slf4j
|
||||
public class PlusDataPermissionHandler {
|
||||
|
||||
/**
|
||||
* 方法或类(名称) 与 注解的映射关系缓存
|
||||
*/
|
||||
private final Map<String, DataPermission> dataPermissionCacheMap = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* 无效注解方法缓存用于快速返回
|
||||
*/
|
||||
private final Set<String> inavlidCacheSet = new ConcurrentHashSet<>();
|
||||
|
||||
/**
|
||||
* spel 解析器
|
||||
*/
|
||||
private final ExpressionParser parser = new SpelExpressionParser();
|
||||
private final ParserContext parserContext = new TemplateParserContext();
|
||||
/**
|
||||
* bean解析器 用于处理 spel 表达式中对 bean 的调用
|
||||
*/
|
||||
private final BeanResolver beanResolver = new BeanFactoryResolver(SpringUtils.getBeanFactory());
|
||||
|
||||
|
||||
public Expression getSqlSegment(Expression where, String mappedStatementId, boolean isSelect) {
|
||||
DataColumn[] dataColumns = findAnnotation(mappedStatementId);
|
||||
if (ArrayUtil.isEmpty(dataColumns)) {
|
||||
inavlidCacheSet.add(mappedStatementId);
|
||||
return where;
|
||||
}
|
||||
SysUser currentUser = DataPermissionHelper.getVariable("user");
|
||||
if (ObjectUtil.isNull(currentUser)) {
|
||||
currentUser = SpringUtils.getBean(UserService.class).selectUserById(SecurityUtils.getUserId());
|
||||
DataPermissionHelper.setVariable("user", currentUser);
|
||||
}
|
||||
// 如果是超级管理员,则不过滤数据
|
||||
if (ObjectUtil.isNull(currentUser) || currentUser.isAdmin()) {
|
||||
return where;
|
||||
}
|
||||
String dataFilterSql = buildDataFilter(dataColumns, isSelect);
|
||||
if (StringUtils.isBlank(dataFilterSql)) {
|
||||
return where;
|
||||
}
|
||||
try {
|
||||
Expression expression = CCJSqlParserUtil.parseExpression(dataFilterSql);
|
||||
// 数据权限使用单独的括号 防止与其他条件冲突
|
||||
Parenthesis parenthesis = new Parenthesis(expression);
|
||||
if (ObjectUtil.isNotNull(where)) {
|
||||
return new AndExpression(where, parenthesis);
|
||||
} else {
|
||||
return parenthesis;
|
||||
}
|
||||
} catch (JSQLParserException e) {
|
||||
throw new ServiceException("数据权限解析异常 => " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造数据过滤sql
|
||||
*/
|
||||
private String buildDataFilter(DataColumn[] dataColumns, boolean isSelect) {
|
||||
StringBuilder sqlString = new StringBuilder();
|
||||
// 更新或删除需满足所有条件
|
||||
String joinStr = isSelect ? " OR " : " AND ";
|
||||
SysUser user = DataPermissionHelper.getVariable("user");
|
||||
StandardEvaluationContext context = new StandardEvaluationContext();
|
||||
context.setBeanResolver(beanResolver);
|
||||
DataPermissionHelper.getContext().forEach(context::setVariable);
|
||||
for (SysRole role : user.getRoles()) {
|
||||
user.setRoleId(role.getRoleId());
|
||||
// 获取角色权限泛型
|
||||
DataScopeType type = DataScopeType.findCode(role.getDataScope());
|
||||
if (ObjectUtil.isNull(type)) {
|
||||
throw new ServiceException("角色数据范围异常 => " + role.getDataScope());
|
||||
}
|
||||
// 全部数据权限直接返回
|
||||
if (type == DataScopeType.ALL) {
|
||||
return "";
|
||||
}
|
||||
boolean isSuccess = false;
|
||||
for (DataColumn dataColumn : dataColumns) {
|
||||
// 不包含 key 变量 则不处理
|
||||
if (!StringUtils.contains(type.getSqlTemplate(), "#" + dataColumn.key())) {
|
||||
continue;
|
||||
}
|
||||
// 设置注解变量 key 为表达式变量 value 为变量值
|
||||
context.setVariable(dataColumn.key(), dataColumn.value());
|
||||
|
||||
// 解析sql模板并填充
|
||||
String sql = parser.parseExpression(type.getSqlTemplate(), parserContext).getValue(context, String.class);
|
||||
sqlString.append(joinStr).append(sql);
|
||||
isSuccess = true;
|
||||
}
|
||||
// 未处理成功则填充兜底方案
|
||||
if (!isSuccess) {
|
||||
sqlString.append(joinStr).append(type.getElseSql());
|
||||
}
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(sqlString.toString())) {
|
||||
return sqlString.substring(joinStr.length());
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private DataColumn[] findAnnotation(String mappedStatementId) {
|
||||
StringBuilder sb = new StringBuilder(mappedStatementId);
|
||||
int index = sb.lastIndexOf(".");
|
||||
String clazzName = sb.substring(0, index);
|
||||
String methodName = sb.substring(index + 1, sb.length());
|
||||
Class<?> clazz = ClassUtil.loadClass(clazzName);
|
||||
List<Method> methods = Arrays.stream(ClassUtil.getDeclaredMethods(clazz))
|
||||
.filter(method -> method.getName().equals(methodName)).collect(Collectors.toList());
|
||||
DataPermission dataPermission;
|
||||
// 获取方法注解
|
||||
for (Method method : methods) {
|
||||
dataPermission = dataPermissionCacheMap.get(method.getName());
|
||||
if (ObjectUtil.isNotNull(dataPermission)) {
|
||||
return dataPermission.value();
|
||||
}
|
||||
if (AnnotationUtil.hasAnnotation(method, DataPermission.class)) {
|
||||
dataPermission = AnnotationUtil.getAnnotation(method, DataPermission.class);
|
||||
dataPermissionCacheMap.put(method.getName(), dataPermission);
|
||||
return dataPermission.value();
|
||||
}
|
||||
}
|
||||
dataPermission = dataPermissionCacheMap.get(clazz.getName());
|
||||
if (ObjectUtil.isNotNull(dataPermission)) {
|
||||
return dataPermission.value();
|
||||
}
|
||||
// 获取类注解
|
||||
if (AnnotationUtil.hasAnnotation(clazz, DataPermission.class)) {
|
||||
dataPermission = AnnotationUtil.getAnnotation(clazz, DataPermission.class);
|
||||
dataPermissionCacheMap.put(clazz.getName(), dataPermission);
|
||||
return dataPermission.value();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为无效方法 无数据权限
|
||||
*/
|
||||
public boolean isInvalid(String mappedStatementId) {
|
||||
return inavlidCacheSet.contains(mappedStatementId);
|
||||
}
|
||||
}
|
@ -0,0 +1,108 @@
|
||||
package com.ruoyi.framework.interceptor;
|
||||
|
||||
import com.baomidou.mybatisplus.core.plugins.InterceptorIgnoreHelper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
|
||||
import com.baomidou.mybatisplus.extension.parser.JsqlParserSupport;
|
||||
import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
|
||||
import com.ruoyi.framework.handler.PlusDataPermissionHandler;
|
||||
import net.sf.jsqlparser.expression.Expression;
|
||||
import net.sf.jsqlparser.statement.delete.Delete;
|
||||
import net.sf.jsqlparser.statement.select.PlainSelect;
|
||||
import net.sf.jsqlparser.statement.select.Select;
|
||||
import net.sf.jsqlparser.statement.select.SelectBody;
|
||||
import net.sf.jsqlparser.statement.select.SetOperationList;
|
||||
import net.sf.jsqlparser.statement.update.Update;
|
||||
import org.apache.ibatis.executor.Executor;
|
||||
import org.apache.ibatis.executor.statement.StatementHandler;
|
||||
import org.apache.ibatis.mapping.BoundSql;
|
||||
import org.apache.ibatis.mapping.MappedStatement;
|
||||
import org.apache.ibatis.mapping.SqlCommandType;
|
||||
import org.apache.ibatis.session.ResultHandler;
|
||||
import org.apache.ibatis.session.RowBounds;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 数据权限拦截器
|
||||
*
|
||||
* @author Lion Li
|
||||
* @version 3.5.0
|
||||
*/
|
||||
public class PlusDataPermissionInterceptor extends JsqlParserSupport implements InnerInterceptor {
|
||||
|
||||
private final PlusDataPermissionHandler dataPermissionHandler = new PlusDataPermissionHandler();
|
||||
|
||||
@Override
|
||||
public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
|
||||
// 检查忽略注解
|
||||
if (InterceptorIgnoreHelper.willIgnoreDataPermission(ms.getId())) {
|
||||
return;
|
||||
}
|
||||
// 检查是否无效 无数据权限注解
|
||||
if (dataPermissionHandler.isInvalid(ms.getId())) {
|
||||
return;
|
||||
}
|
||||
// 解析 sql 分配对应方法
|
||||
PluginUtils.MPBoundSql mpBs = PluginUtils.mpBoundSql(boundSql);
|
||||
mpBs.sql(parserSingle(mpBs.sql(), ms.getId()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforePrepare(StatementHandler sh, Connection connection, Integer transactionTimeout) {
|
||||
PluginUtils.MPStatementHandler mpSh = PluginUtils.mpStatementHandler(sh);
|
||||
MappedStatement ms = mpSh.mappedStatement();
|
||||
SqlCommandType sct = ms.getSqlCommandType();
|
||||
if (sct == SqlCommandType.UPDATE || sct == SqlCommandType.DELETE) {
|
||||
if (InterceptorIgnoreHelper.willIgnoreDataPermission(ms.getId())) {
|
||||
return;
|
||||
}
|
||||
PluginUtils.MPBoundSql mpBs = mpSh.mPBoundSql();
|
||||
mpBs.sql(parserMulti(mpBs.sql(), ms.getId()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processSelect(Select select, int index, String sql, Object obj) {
|
||||
SelectBody selectBody = select.getSelectBody();
|
||||
if (selectBody instanceof PlainSelect) {
|
||||
this.setWhere((PlainSelect) selectBody, (String) obj);
|
||||
} else if (selectBody instanceof SetOperationList) {
|
||||
SetOperationList setOperationList = (SetOperationList) selectBody;
|
||||
List<SelectBody> selectBodyList = setOperationList.getSelects();
|
||||
selectBodyList.forEach(s -> this.setWhere((PlainSelect) s, (String) obj));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processUpdate(Update update, int index, String sql, Object obj) {
|
||||
Expression sqlSegment = dataPermissionHandler.getSqlSegment(update.getWhere(), (String) obj, false);
|
||||
if (null != sqlSegment) {
|
||||
update.setWhere(sqlSegment);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processDelete(Delete delete, int index, String sql, Object obj) {
|
||||
Expression sqlSegment = dataPermissionHandler.getSqlSegment(delete.getWhere(), (String) obj, false);
|
||||
if (null != sqlSegment) {
|
||||
delete.setWhere(sqlSegment);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置 where 条件
|
||||
*
|
||||
* @param plainSelect 查询对象
|
||||
* @param mappedStatementId 执行方法id
|
||||
*/
|
||||
protected void setWhere(PlainSelect plainSelect, String mappedStatementId) {
|
||||
Expression sqlSegment = dataPermissionHandler.getSqlSegment(plainSelect.getWhere(), mappedStatementId, true);
|
||||
if (null != sqlSegment) {
|
||||
plainSelect.setWhere(sqlSegment);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,48 +1,55 @@
|
||||
package com.ruoyi.framework.Interceptor;
|
||||
package com.ruoyi.framework.interceptor;
|
||||
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import com.alibaba.ttl.TransmittableThreadLocal;
|
||||
import com.ruoyi.common.filter.RepeatedlyRequestWrapper;
|
||||
import com.ruoyi.common.utils.JsonUtils;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.yomahub.tlog.context.TLogContext;
|
||||
import com.yomahub.tlog.web.interceptor.AbsTLogWebHandlerMethodInterceptor;
|
||||
import com.yomahub.tlog.web.wrapper.RequestWrapper;
|
||||
import com.ruoyi.common.utils.spring.SpringUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.time.StopWatch;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.BufferedReader;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 重写Tlog web的调用时间统计拦截器
|
||||
* web的调用时间统计拦截器
|
||||
* dev环境有效
|
||||
*
|
||||
* @author Lion Li
|
||||
* @since 3.3.0
|
||||
*/
|
||||
@Slf4j
|
||||
public class PlusWebInvokeTimeInterceptor extends AbsTLogWebHandlerMethodInterceptor {
|
||||
public class PlusWebInvokeTimeInterceptor implements HandlerInterceptor {
|
||||
|
||||
private final TransmittableThreadLocal<StopWatch> invokeTimeTL = new TransmittableThreadLocal<>();
|
||||
|
||||
@Override
|
||||
public boolean preHandleByHandlerMethod(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||
if (TLogContext.enableInvokeTimePrint()) {
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||
if (!"prod".equals(SpringUtils.getActiveProfile())) {
|
||||
String url = request.getMethod() + " " + request.getRequestURI();
|
||||
|
||||
// 打印请求参数
|
||||
if (isJsonRequest(request)) {
|
||||
String jsonParam = new RequestWrapper(request).getBodyString();
|
||||
log.info("[PLUS]开始请求 => URL[{}],参数类型[json],参数:[{}]", url, jsonParam);
|
||||
String jsonParam = "";
|
||||
if (request instanceof RepeatedlyRequestWrapper) {
|
||||
BufferedReader reader = request.getReader();
|
||||
jsonParam = IoUtil.read(reader);
|
||||
}
|
||||
log.debug("[PLUS]开始请求 => URL[{}],参数类型[json],参数:[{}]", url, jsonParam);
|
||||
} else {
|
||||
Map<String, String[]> parameterMap = request.getParameterMap();
|
||||
if (MapUtil.isNotEmpty(parameterMap)) {
|
||||
String parameters = JsonUtils.toJsonString(parameterMap);
|
||||
log.info("[PLUS]开始请求 => URL[{}],参数类型[param],参数:[{}]", url, parameters);
|
||||
log.debug("[PLUS]开始请求 => URL[{}],参数类型[param],参数:[{}]", url, parameters);
|
||||
} else {
|
||||
log.info("[PLUS]开始请求 => URL[{}],无参数", url);
|
||||
log.debug("[PLUS]开始请求 => URL[{}],无参数", url);
|
||||
}
|
||||
}
|
||||
|
||||
@ -54,16 +61,16 @@ public class PlusWebInvokeTimeInterceptor extends AbsTLogWebHandlerMethodInterce
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postHandleByHandlerMethod(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
|
||||
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterCompletionByHandlerMethod(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
|
||||
if (TLogContext.enableInvokeTimePrint()) {
|
||||
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
|
||||
if (!"prod".equals(SpringUtils.getActiveProfile())) {
|
||||
StopWatch stopWatch = invokeTimeTL.get();
|
||||
stopWatch.stop();
|
||||
log.info("[PLUS]结束请求 => URL[{}],耗时:[{}]毫秒", request.getMethod() + " " + request.getRequestURI(), stopWatch.getTime());
|
||||
log.debug("[PLUS]结束请求 => URL[{}],耗时:[{}]毫秒", request.getMethod() + " " + request.getRequestURI(), stopWatch.getTime());
|
||||
invokeTimeTL.remove();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user