feat: 优化配置和代码结构

1、优化项目结构、优化部分配置
2、优化Redis配置类,缓存需手动指定key生成器
3、新增AnonTagUtils,用于获取匿名接口
4、优化Swagger,排除不需要认证的接口
5、新增BigDecimalUtils,用于BigDecimal类型,+-*/计算,元与分的转换
This commit is contained in:
Jie Zheng 2025-01-13 14:32:27 +08:00
parent fc5fbe0c85
commit eb17ffdfc7
53 changed files with 612 additions and 498 deletions

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.zhengjie.annotation;
package me.zhengjie.annotation.rest;
import java.lang.annotation.*;

View File

@ -22,7 +22,6 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import me.zhengjie.annotation.AnonymousAccess;
import org.springframework.core.annotation.AliasFor;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

View File

@ -22,7 +22,6 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import me.zhengjie.annotation.AnonymousAccess;
import org.springframework.core.annotation.AliasFor;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

View File

@ -22,7 +22,6 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import me.zhengjie.annotation.AnonymousAccess;
import org.springframework.core.annotation.AliasFor;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

View File

@ -22,7 +22,6 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import me.zhengjie.annotation.AnonymousAccess;
import org.springframework.core.annotation.AliasFor;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

View File

@ -22,7 +22,6 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import me.zhengjie.annotation.AnonymousAccess;
import org.springframework.core.annotation.AliasFor;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

View File

@ -0,0 +1,75 @@
package me.zhengjie.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 创建自定义的线程池
* @author Zheng Jie
* @description
* @date 2023-06-08
**/
@Configuration
public class AsyncExecutor {
public static int corePoolSize;
public static int maxPoolSize;
public static int keepAliveSeconds;
public static int queueCapacity;
@Value("${task.pool.core-pool-size}")
public void setCorePoolSize(int corePoolSize) {
AsyncExecutor.corePoolSize = corePoolSize;
}
@Value("${task.pool.max-pool-size}")
public void setMaxPoolSize(int maxPoolSize) {
AsyncExecutor.maxPoolSize = maxPoolSize;
}
@Value("${task.pool.keep-alive-seconds}")
public void setKeepAliveSeconds(int keepAliveSeconds) {
AsyncExecutor.keepAliveSeconds = keepAliveSeconds;
}
@Value("${task.pool.queue-capacity}")
public void setQueueCapacity(int queueCapacity) {
AsyncExecutor.queueCapacity = queueCapacity;
}
/**
* 自定义线程池用法 @Async
* @return Executor
*/
@Bean
@Primary
public Executor elAsync() {
// 自定义工厂
ThreadFactory factory = r -> new Thread(r, "el-async-" + new AtomicInteger(1).getAndIncrement());
// 自定义线程池
return new ThreadPoolExecutor(corePoolSize, maxPoolSize, keepAliveSeconds,
TimeUnit.SECONDS, new ArrayBlockingQueue<>(queueCapacity), factory,
new ThreadPoolExecutor.CallerRunsPolicy());
}
/**
* 自定义线程池用法 @Async("otherAsync")
* @return Executor
*/
@Bean
public Executor otherAsync() {
// 自定义工厂
ThreadFactory factory = r -> new Thread(r, "tpl-other-" + new AtomicInteger(1).getAndIncrement());
// 自定义线程池
return new ThreadPoolExecutor(2, 4, keepAliveSeconds,
TimeUnit.SECONDS, new ArrayBlockingQueue<>(20), factory,
new ThreadPoolExecutor.CallerRunsPolicy());
}
}

View File

@ -15,47 +15,38 @@
*/
package me.zhengjie.config;
import cn.hutool.core.lang.Assert;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.serializer.SerializerFeature;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cache.Cache;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.CacheErrorHandler;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.cache.interceptor.SimpleCacheErrorHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import reactor.util.annotation.Nullable;
import java.nio.charset.Charset;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
/**
* @author Zheng Jie
* @date 2018-11-24
* @date 2025-01-13
*/
@Slf4j
@Configuration
@EnableCaching
@ConditionalOnClass(RedisOperations.class)
@EnableConfigurationProperties(RedisProperties.class)
public class RedisConfig extends CachingConfigurerSupport {
public class RedisConfiguration {
/**
* 设置 redis 数据默认过期时间默认2小时
@ -70,9 +61,7 @@ public class RedisConfig extends CachingConfigurerSupport {
return configuration;
}
@SuppressWarnings("all")
@Bean(name = "redisTemplate")
@ConditionalOnMissingBean(name = "redisTemplate")
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
//序列化
@ -96,10 +85,24 @@ public class RedisConfig extends CachingConfigurerSupport {
}
/**
* 自定义缓存key生成策略默认将使用该策略
* 缓存管理器
* @param redisConnectionFactory /
* @return 缓存管理器
*/
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
RedisCacheConfiguration config = redisCacheConfiguration();
return RedisCacheManager.builder(redisConnectionFactory)
.cacheDefaults(config)
.build();
}
/**
* 自定义缓存key生成策略需要在缓存注解中使用keyGenerator才会生效
* 默认是使用SimpleKeyGenerator生成的key
* 继承 CachingConfigurerSupport 才会默认生效这个生成器暂时没找到其他方式默认生效如果有请PR谢谢
*/
@Bean
@Override
public KeyGenerator keyGenerator() {
return (target, method, params) -> {
Map<String,Object> container = new HashMap<>(8);
@ -122,101 +125,63 @@ public class RedisConfig extends CachingConfigurerSupport {
}
@Bean
@Override
@SuppressWarnings("all")
public CacheErrorHandler errorHandler() {
// 异常处理当Redis发生异常时打印日志但是程序正常走
log.info("初始化 -> [{}]", "Redis CacheErrorHandler");
return new CacheErrorHandler() {
return new SimpleCacheErrorHandler() {
@Override
public void handleCacheGetError(RuntimeException e, Cache cache, Object key) {
log.error("Redis occur handleCacheGetErrorkey -> [{}]", key, e);
public void handleCacheGetError(RuntimeException exception, Cache cache, Object key) {
// 处理缓存读取错误
log.error("Cache Get Error: {}",exception.getMessage());
}
@Override
public void handleCachePutError(RuntimeException e, Cache cache, Object key, Object value) {
log.error("Redis occur handleCachePutErrorkey -> [{}]value -> [{}]", key, value, e);
public void handleCachePutError(RuntimeException exception, Cache cache, Object key, Object value) {
// 处理缓存写入错误
log.error("Cache Put Error: {}",exception.getMessage());
}
@Override
public void handleCacheEvictError(RuntimeException e, Cache cache, Object key) {
log.error("Redis occur handleCacheEvictErrorkey -> [{}]", key, e);
public void handleCacheEvictError(RuntimeException exception, Cache cache, Object key) {
// 处理缓存删除错误
log.error("Cache Evict Error: {}",exception.getMessage());
}
@Override
public void handleCacheClearError(RuntimeException e, Cache cache) {
log.error("Redis occur handleCacheClearError", e);
public void handleCacheClearError(RuntimeException exception, Cache cache) {
// 处理缓存清除错误
log.error("Cache Clear Error: {}",exception.getMessage());
}
};
}
}
/**
* Value 序列化
*
* @param <T>
* @author /
*/
static class FastJsonRedisSerializer<T> implements RedisSerializer<T> {
/**
* Value 序列化
*
* @author /
* @param <T>
*/
class FastJsonRedisSerializer<T> implements RedisSerializer<T> {
private final Class<T> clazz;
private final Class<T> clazz;
FastJsonRedisSerializer(Class<T> clazz) {
super();
this.clazz = clazz;
}
@Override
public byte[] serialize(T t) {
if (t == null) {
return new byte[0];
FastJsonRedisSerializer(Class<T> clazz) {
super();
this.clazz = clazz;
}
return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(StandardCharsets.UTF_8);
}
@Override
public T deserialize(byte[] bytes) {
if (bytes == null || bytes.length == 0) {
return null;
@Override
public byte[] serialize(T t) {
if (t == null) {
return new byte[0];
}
return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(StandardCharsets.UTF_8);
}
String str = new String(bytes, StandardCharsets.UTF_8);
return JSON.parseObject(str, clazz);
@Override
public T deserialize(byte[] bytes) {
if (bytes == null || bytes.length == 0) {
return null;
}
String str = new String(bytes, StandardCharsets.UTF_8);
return JSON.parseObject(str, clazz);
}
}
}
/**
* 重写序列化器
*
* @author /
*/
class StringRedisSerializer implements RedisSerializer<Object> {
private final Charset charset;
StringRedisSerializer() {
this(StandardCharsets.UTF_8);
}
private StringRedisSerializer(Charset charset) {
Assert.notNull(charset, "Charset must not be null!");
this.charset = charset;
}
@Override
public String deserialize(byte[] bytes) {
return (bytes == null ? null : new String(bytes, charset));
}
@Override
public @Nullable byte[] serialize(Object object) {
String string = JSON.toJSONString(object);
if (org.apache.commons.lang3.StringUtils.isBlank(string)) {
return null;
}
string = string.replace("\"", "");
return string.getBytes(charset);
}
}
}

View File

@ -0,0 +1,53 @@
package me.zhengjie.config;
import cn.hutool.core.util.StrUtil;
import lombok.Data;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Data
@Configuration
public class RedissonConfiguration {
@Value("${spring.redis.host}")
private String redisHost;
@Value("${spring.redis.port}")
private int redisPort;
@Value("${spring.redis.database}")
private int redisDatabase;
@Value("${spring.redis.password:}")
private String redisPassword;
@Value("${spring.redis.timeout:5000}")
private int timeout;
@Value("${spring.redis.lettuce.pool.max-active:64}")
private int connectionPoolSize;
@Value("${spring.redis.lettuce.pool.min-idle:16}")
private int connectionMinimumIdleSize;
@Bean
public RedissonClient redissonClient() {
Config config = new Config();
config.useSingleServer()
.setAddress("redis://" + redisHost + ":" + redisPort)
.setDatabase(redisDatabase)
.setTimeout(timeout)
.setConnectionPoolSize(connectionPoolSize)
.setConnectionMinimumIdleSize(connectionMinimumIdleSize);
if(StrUtil.isNotBlank(redisPassword)){
config.useSingleServer().setPassword(redisPassword);
}
return Redisson.create(config);
}
}

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.zhengjie.config;
package me.zhengjie.config.properties;
import lombok.Data;
import me.zhengjie.utils.ElConstant;

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.zhengjie.config;
package me.zhengjie.config.properties;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;

View File

@ -13,15 +13,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.zhengjie.config;
package me.zhengjie.config.webConfig;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import me.zhengjie.config.properties.FileProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
@ -73,16 +75,22 @@ public class ConfigurerAdapter implements WebMvcConfigurer {
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
// 使用 fastjson 序列化会导致 @JsonIgnore 失效可以使用 @JSONField(serialize = false) 替换
FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
// 添加默认的 StringHttpMessageConverter
converters.add(new StringHttpMessageConverter(StandardCharsets.UTF_8));
// 配置 FastJsonHttpMessageConverter
FastJsonHttpMessageConverter fastJsonConverter = new FastJsonHttpMessageConverter();
List<MediaType> supportMediaTypeList = new ArrayList<>();
supportMediaTypeList.add(MediaType.APPLICATION_JSON);
FastJsonConfig config = new FastJsonConfig();
config.setDateFormat("yyyy-MM-dd HH:mm:ss");
config.setSerializerFeatures(SerializerFeature.DisableCircularReferenceDetect);
converter.setFastJsonConfig(config);
converter.setSupportedMediaTypes(supportMediaTypeList);
converter.setDefaultCharset(StandardCharsets.UTF_8);
converters.add(converter);
config.setSerializerFeatures(
SerializerFeature.WriteEnumUsingToString,
SerializerFeature.DisableCircularReferenceDetect
);
fastJsonConverter.setFastJsonConfig(config);
fastJsonConverter.setSupportedMediaTypes(supportMediaTypeList);
fastJsonConverter.setDefaultCharset(StandardCharsets.UTF_8);
// FastJsonHttpMessageConverter 添加到列表末尾
converters.add(fastJsonConverter);
}
}

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.zhengjie.config.webmvc;
package me.zhengjie.config.webConfig;
import org.springframework.boot.web.servlet.MultipartConfigFactory;
import org.springframework.context.annotation.Bean;

View File

@ -13,15 +13,18 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.zhengjie.config.webmvc;
package me.zhengjie.config.webConfig;
import lombok.RequiredArgsConstructor;
import me.zhengjie.utils.AnonTagUtils;
import me.zhengjie.utils.StringUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.service.ApiInfo;
@ -32,11 +35,14 @@ import springfox.documentation.service.SecurityScheme;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.spring.web.plugins.WebFluxRequestHandlerProvider;
import springfox.documentation.spring.web.plugins.WebMvcRequestHandlerProvider;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
/**
@ -61,7 +67,6 @@ public class SwaggerConfig {
private final ApplicationContext applicationContext;
@Bean
@SuppressWarnings("all")
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.enable(enabled)
@ -119,4 +124,44 @@ public class SwaggerConfig {
securityReferences.add(new SecurityReference(tokenHeader, authorizationScopes));
return securityReferences;
}
/**
* 解决Springfox与SpringBoot集成后WebMvcRequestHandlerProvider和WebFluxRequestHandlerProvider冲突问题
* @return /
*/
@Bean
@SuppressWarnings({"all"})
public static BeanPostProcessor springfoxHandlerProviderBeanPostProcessor() {
return new BeanPostProcessor() {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof WebMvcRequestHandlerProvider || bean instanceof WebFluxRequestHandlerProvider) {
customizeSpringfoxHandlerMappings(getHandlerMappings(bean));
}
return bean;
}
private <T extends RequestMappingInfoHandlerMapping> void customizeSpringfoxHandlerMappings(List<T> mappings) {
List<T> filteredMappings = mappings.stream()
.filter(mapping -> mapping.getPatternParser() == null)
.collect(Collectors.toList());
mappings.clear();
mappings.addAll(filteredMappings);
}
private List<RequestMappingInfoHandlerMapping> getHandlerMappings(Object bean) {
Field field = ReflectionUtils.findField(bean.getClass(), "handlerMappings");
if (field != null) {
field.setAccessible(true);
try {
return (List<RequestMappingInfoHandlerMapping>) field.get(bean);
} catch (IllegalAccessException e) {
throw new IllegalStateException("Failed to access handlerMappings field", e);
}
}
return Collections.emptyList();
}
};
}
}

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.zhengjie.config;
package me.zhengjie.config.webConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

View File

@ -15,7 +15,7 @@
*/
package me.zhengjie.utils;
import me.zhengjie.annotation.AnonymousAccess;
import me.zhengjie.annotation.rest.AnonymousAccess;
import me.zhengjie.utils.enums.RequestMethodEnum;
import org.springframework.context.ApplicationContext;
import org.springframework.web.bind.annotation.RequestMethod;

View File

@ -0,0 +1,143 @@
/*
* Copyright 2019-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.zhengjie.utils;
import java.math.BigDecimal;
import java.math.RoundingMode;
/**
* @author Zheng Jie
* @description 计算类
* @date 2024-12-27
**/
public class BigDecimalUtils {
/**
* 将对象转换为 BigDecimal
* @param obj 输入对象
* @return 转换后的 BigDecimal
*/
private static BigDecimal toBigDecimal(Object obj) {
if (obj instanceof BigDecimal) {
return (BigDecimal) obj;
} else if (obj instanceof Long) {
return BigDecimal.valueOf((Long) obj);
} else if (obj instanceof Integer) {
return BigDecimal.valueOf((Integer) obj);
} else if (obj instanceof Double) {
return new BigDecimal(String.valueOf(obj));
} else {
throw new IllegalArgumentException("Unsupported type");
}
}
/**
* 加法
* @param a 加数
* @param b 加数
* @return 两个加数的和保留两位小数
*/
public static BigDecimal add(Object a, Object b) {
BigDecimal bdA = toBigDecimal(a);
BigDecimal bdB = toBigDecimal(b);
return bdA.add(bdB).setScale(2, RoundingMode.HALF_UP);
}
/**
* 减法
* @param a 被减数
* @param b 减数
* @return 两数的差保留两位小数
*/
public static BigDecimal subtract(Object a, Object b) {
BigDecimal bdA = toBigDecimal(a);
BigDecimal bdB = toBigDecimal(b);
return bdA.subtract(bdB).setScale(2, RoundingMode.HALF_UP);
}
/**
* 乘法
* @param a 乘数
* @param b 乘数
* @return 两个乘数的积保留两位小数
*/
public static BigDecimal multiply(Object a, Object b) {
BigDecimal bdA = toBigDecimal(a);
BigDecimal bdB = toBigDecimal(b);
return bdA.multiply(bdB).setScale(2, RoundingMode.HALF_UP);
}
/**
* 除法
* @param a 被除数
* @param b 除数
* @return 两数的商保留两位小数
*/
public static BigDecimal divide(Object a, Object b) {
BigDecimal bdA = toBigDecimal(a);
BigDecimal bdB = toBigDecimal(b);
return bdA.divide(bdB, 2, RoundingMode.HALF_UP);
}
/**
* 除法
* @param a 被除数
* @param b 除数
* @param scale 保留小数位数
* @return 两数的商保留两位小数
*/
public static BigDecimal divide(Object a, Object b, int scale) {
BigDecimal bdA = toBigDecimal(a);
BigDecimal bdB = toBigDecimal(b);
return bdA.divide(bdB, scale, RoundingMode.HALF_UP);
}
/**
* 分转元
* @param obj 分的金额
* @return 转换后的元保留两位小数
*/
public static BigDecimal centsToYuan(Object obj) {
BigDecimal cents = toBigDecimal(obj);
return cents.divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP);
}
/**
* 元转分
* @param obj 元的金额
* @return 转换后的分
*/
public static Long yuanToCents(Object obj) {
BigDecimal yuan = toBigDecimal(obj);
return yuan.multiply(BigDecimal.valueOf(100)).setScale(0, RoundingMode.HALF_UP).longValue();
}
public static void main(String[] args) {
BigDecimal num1 = new BigDecimal("10.123");
BigDecimal num2 = new BigDecimal("2.456");
System.out.println("加法结果: " + add(num1, num2));
System.out.println("减法结果: " + subtract(num1, num2));
System.out.println("乘法结果: " + multiply(num1, num2));
System.out.println("除法结果: " + divide(num1, num2));
Long cents = 12345L;
System.out.println("分转元结果: " + centsToYuan(cents));
BigDecimal yuan = new BigDecimal("123.45");
System.out.println("元转分结果: " + yuanToCents(yuan));
}
}

View File

@ -16,9 +16,9 @@
package me.zhengjie.utils;
/**
* @author: liaojinlong
* @date: 2020/6/11 15:49
* @apiNote: 关于缓存的Key集合
* @author liaojinlong
* @date 2020/6/11 15:49
* @description 关于缓存的Key集合
*/
public interface CacheKey {

View File

@ -1,43 +0,0 @@
/*
* Copyright 2019-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.zhengjie.utils;
/**
* @author: liaojinlong
* @date: 2020/6/9 17:02
* @since: 1.0
* @see {@link SpringBeanHolder}
* 针对某些初始化方法在SpringContextHolder 初始化前时<br>
* 可提交一个 提交回调任务<br>
* 在SpringContextHolder 初始化后进行回调使用
*/
public interface CallBack {
/**
* 回调执行方法
*/
void executor();
/**
* 本回调任务名称
* @return /
*/
default String getCallBackName() {
return Thread.currentThread().getId() + ":" + this.getClass().getName();
}
}

View File

@ -19,7 +19,6 @@ import java.io.Closeable;
/**
* @author Zheng Jie
* @website https://eladmin.vip
* @description 用于关闭各种连接缺啥补啥
* @date 2021-03-05
**/

View File

@ -22,9 +22,9 @@ import java.time.format.DateTimeFormatter;
import java.util.Date;
/**
* @author: liaojinlong
* @date: 2020/6/11 16:28
* @apiNote: JDK 8 新日期类 格式化与字符串转换 工具类
* @author liaojinlong
* @date 2020/6/11 16:28
* @description JDK 8 新日期类 格式化与字符串转换 工具类
*/
public class DateUtil {

View File

@ -37,7 +37,7 @@ public class EncryptUtils {
private static final IvParameterSpec IV = new IvParameterSpec(STR_PARAM.getBytes(StandardCharsets.UTF_8));
private static DESKeySpec getDesKeySpec(String source) throws Exception {
if (source == null || source.length() == 0){
if (source == null || source.isEmpty()){
return null;
}
cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");

View File

@ -4,6 +4,12 @@ import lombok.*;
import java.io.Serializable;
import java.util.List;
/**
* 分页结果封装类
* @author Zheng Jie
* @date 2018-11-23
* @param <T>
*/
@Data
@NoArgsConstructor
@AllArgsConstructor

View File

@ -33,7 +33,7 @@ import java.util.stream.Collectors;
* @author /
*/
@Component
@SuppressWarnings({"unchecked", "all"})
@SuppressWarnings({"all"})
public class RedisUtils {
private static final Logger log = LoggerFactory.getLogger(RedisUtils.class);

View File

@ -10,7 +10,7 @@ import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
/**
* @author https://www.cnblogs.com/nihaorz/p/10690643.html
* @author <a href="https://www.cnblogs.com/nihaorz/p/10690643.html">...</a>
* @description Rsa 工具类公钥私钥生成加解密
* @date 2020-05-18
**/

View File

@ -31,6 +31,7 @@ import java.util.List;
* @date 2019-01-07
*/
@Slf4j
@SuppressWarnings("all")
public class SpringBeanHolder implements ApplicationContextAware, DisposableBean {
private static ApplicationContext applicationContext = null;
@ -55,7 +56,6 @@ public class SpringBeanHolder implements ApplicationContextAware, DisposableBean
/**
* 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
*/
@SuppressWarnings("unchecked")
public static <T> T getBean(String name) {
assertContextInjected();
return (T) applicationContext.getBean(name);
@ -153,4 +153,20 @@ public class SpringBeanHolder implements ApplicationContextAware, DisposableBean
return new ArrayList<>(Arrays.asList(applicationContext
.getBeanNamesForAnnotation(Service.class)));
}
interface CallBack {
/**
* 回调执行方法
*/
void executor();
/**
* 本回调任务名称
* @return /
*/
default String getCallBackName() {
return Thread.currentThread().getId() + ":" + this.getClass().getName();
}
}
}

View File

@ -32,7 +32,7 @@ import java.util.*;
* 字符串工具类, 继承org.apache.commons.lang3.StringUtils类
*/
@Slf4j
@SuppressWarnings({"unchecked","all"})
@SuppressWarnings({"all"})
public class StringUtils extends org.apache.commons.lang3.StringUtils {
private static final char SEPARATOR = '_';

View File

@ -39,12 +39,6 @@
<version>1.1</version>
</dependency>
<!-- Spring boot websocket -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<!-- quartz -->
<dependency>
<groupId>org.springframework.boot</groupId>

View File

@ -1,31 +0,0 @@
/*
* Copyright 2019-2023 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.zhengjie.config;
import org.apache.catalina.connector.Connector;
import org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer;
import org.springframework.context.annotation.Configuration;
/**
* @author bearBoy80
*/
@Configuration(proxyBeanMethods = false)
public class RelaxedQueryCharsConnectorCustomizer implements TomcatConnectorCustomizer {
@Override
public void customize(Connector connector) {
connector.setProperty("relaxedQueryChars", "[]{}");
}
}

View File

@ -1,59 +0,0 @@
/*
* Copyright 2019-2020 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.zhengjie.config.thread;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 线程池配置属性类
* @author https://juejin.im/entry/5abb8f6951882555677e9da2
* @date 2019年10月31日14:58:18
*/
@Data
@Component
public class AsyncTaskProperties {
public static int corePoolSize;
public static int maxPoolSize;
public static int keepAliveSeconds;
public static int queueCapacity;
@Value("${task.pool.core-pool-size}")
public void setCorePoolSize(int corePoolSize) {
AsyncTaskProperties.corePoolSize = corePoolSize;
}
@Value("${task.pool.max-pool-size}")
public void setMaxPoolSize(int maxPoolSize) {
AsyncTaskProperties.maxPoolSize = maxPoolSize;
}
@Value("${task.pool.keep-alive-seconds}")
public void setKeepAliveSeconds(int keepAliveSeconds) {
AsyncTaskProperties.keepAliveSeconds = keepAliveSeconds;
}
@Value("${task.pool.queue-capacity}")
public void setQueueCapacity(int queueCapacity) {
AsyncTaskProperties.queueCapacity = queueCapacity;
}
}

View File

@ -1,52 +0,0 @@
package me.zhengjie.config.thread;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
/**
* 创建自定义的线程池
* @author Zheng Jie
* @description
* @date 2023-06-08
**/
@Configuration
public class CustomExecutorConfig {
/**
* 自定义线程池用法 @Async
* @return Executor
*/
@Bean
@Primary
public Executor elAsync() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(AsyncTaskProperties.corePoolSize);
executor.setMaxPoolSize(AsyncTaskProperties.maxPoolSize);
executor.setQueueCapacity(AsyncTaskProperties.queueCapacity);
executor.setThreadNamePrefix("el-async-");
executor.setKeepAliveSeconds(AsyncTaskProperties.keepAliveSeconds);
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}
/**
* 自定义线程池用法 @Async("otherAsync")
* @return Executor
*/
@Bean
public Executor otherAsync() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(15);
executor.setQueueCapacity(50);
executor.setKeepAliveSeconds(AsyncTaskProperties.keepAliveSeconds);
executor.setThreadNamePrefix("el-task-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}
}

View File

@ -0,0 +1,134 @@
/*
* Copyright 2019-2020 the original author or authors.
*
* Licensed under the Apache License, Version loginCode.length.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-loginCode.length.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.zhengjie.modules.security.config.bean;
import com.wf.captcha.*;
import com.wf.captcha.base.Captcha;
import lombok.Data;
import lombok.Getter;
import me.zhengjie.exception.BadRequestException;
import me.zhengjie.utils.StringUtils;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import java.awt.*;
/**
* 登录验证码配置信息
* @author liaojinlong
* @date 2025-01-13
*/
@Data
@Configuration
@ConfigurationProperties(prefix = "login.code")
public class CodeProperties {
/**
* 验证码配置
*/
@Getter
private LoginCodeEnum codeType;
/**
* 验证码有效期 分钟
*/
private Long expiration = 5L;
/**
* 验证码内容长度
*/
private int length = 4;
/**
* 验证码宽度
*/
private int width = 111;
/**
* 验证码高度
*/
private int height = 36;
/**
* 验证码字体
*/
private String fontName;
/**
* 字体大小
*/
private int fontSize = 25;
/**
* 依据配置信息生产验证码
* @return /
*/
public Captcha getCaptcha() {
Captcha captcha;
switch (codeType) {
case ARITHMETIC:
// 算术类型 https://gitee.com/whvse/EasyCaptcha
captcha = new FixedArithmeticCaptcha(width, height);
// 几位数运算默认是两位
captcha.setLen(length);
break;
case CHINESE:
captcha = new ChineseCaptcha(width, height);
captcha.setLen(length);
break;
case CHINESE_GIF:
captcha = new ChineseGifCaptcha(width, height);
captcha.setLen(length);
break;
case GIF:
captcha = new GifCaptcha(width, height);
captcha.setLen(length);
break;
case SPEC:
captcha = new SpecCaptcha(width, height);
captcha.setLen(length);
break;
default:
throw new BadRequestException("验证码配置信息错误!正确配置查看 LoginCodeEnum ");
}
if(StringUtils.isNotBlank(fontName)){
captcha.setFont(new Font(fontName, Font.PLAIN, fontSize));
}
return captcha;
}
static class FixedArithmeticCaptcha extends ArithmeticCaptcha {
public FixedArithmeticCaptcha(int width, int height) {
super(width, height);
}
@Override
protected char[] alphas() {
// 生成随机数字和运算符
int n1 = num(1, 10), n2 = num(1, 10);
int opt = num(3);
// 计算结果
int res = new int[]{n1 + n2, n1 - n2, n1 * n2}[opt];
// 转换为字符运算符
char optChar = "+-x".charAt(opt);
this.setArithmeticString(String.format("%s%c%s=?", n1, optChar, n2));
this.chars = String.valueOf(res);
return chars.toCharArray();
}
}
}

View File

@ -1,61 +0,0 @@
/*
* Copyright 2019-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.zhengjie.modules.security.config.bean;
import lombok.Data;
/**
* 登录验证码配置信息
*
* @author liaojinlong
* @date 2020/6/10 18:53
*/
@Data
public class LoginCode {
/**
* 验证码配置
*/
private LoginCodeEnum codeType;
/**
* 验证码有效期 分钟
*/
private Long expiration = 2L;
/**
* 验证码内容长度
*/
private int length = 2;
/**
* 验证码宽度
*/
private int width = 111;
/**
* 验证码高度
*/
private int height = 36;
/**
* 验证码字体
*/
private String fontName;
/**
* 字体大小
*/
private int fontSize = 25;
public LoginCodeEnum getCodeType() {
return codeType;
}
}

View File

@ -15,14 +15,7 @@
*/
package me.zhengjie.modules.security.config.bean;
import com.wf.captcha.*;
import com.wf.captcha.base.Captcha;
import lombok.Data;
import lombok.Getter;
import me.zhengjie.exception.BadRequestException;
import me.zhengjie.utils.StringUtils;
import java.awt.*;
import java.util.Objects;
/**
* 配置文件读取
@ -36,88 +29,7 @@ public class LoginProperties {
/**
* 账号单用户 登录
*/
@Getter
private boolean singleLogin = false;
private LoginCode loginCode;
public static final String cacheKey = "user-login-cache:";
/**
* 获取验证码生产类
*
* @return /
*/
public Captcha getCaptcha() {
if (Objects.isNull(loginCode)) {
loginCode = new LoginCode();
if (Objects.isNull(loginCode.getCodeType())) {
loginCode.setCodeType(LoginCodeEnum.ARITHMETIC);
}
}
return switchCaptcha(loginCode);
}
/**
* 依据配置信息生产验证码
*
* @param loginCode 验证码配置信息
* @return /
*/
private Captcha switchCaptcha(LoginCode loginCode) {
Captcha captcha;
switch (loginCode.getCodeType()) {
case ARITHMETIC:
// 算术类型 https://gitee.com/whvse/EasyCaptcha
captcha = new FixedArithmeticCaptcha(loginCode.getWidth(), loginCode.getHeight());
// 几位数运算默认是两位
captcha.setLen(loginCode.getLength());
break;
case CHINESE:
captcha = new ChineseCaptcha(loginCode.getWidth(), loginCode.getHeight());
captcha.setLen(loginCode.getLength());
break;
case CHINESE_GIF:
captcha = new ChineseGifCaptcha(loginCode.getWidth(), loginCode.getHeight());
captcha.setLen(loginCode.getLength());
break;
case GIF:
captcha = new GifCaptcha(loginCode.getWidth(), loginCode.getHeight());
captcha.setLen(loginCode.getLength());
break;
case SPEC:
captcha = new SpecCaptcha(loginCode.getWidth(), loginCode.getHeight());
captcha.setLen(loginCode.getLength());
break;
default:
throw new BadRequestException("验证码配置信息错误!正确配置查看 LoginCodeEnum ");
}
if(StringUtils.isNotBlank(loginCode.getFontName())){
captcha.setFont(new Font(loginCode.getFontName(), Font.PLAIN, loginCode.getFontSize()));
}
return captcha;
}
static class FixedArithmeticCaptcha extends ArithmeticCaptcha {
public FixedArithmeticCaptcha(int width, int height) {
super(width, height);
}
@Override
protected char[] alphas() {
// 生成随机数字和运算符
int n1 = num(1, 10), n2 = num(1, 10);
int opt = num(3);
// 计算结果
int res = new int[]{n1 + n2, n1 - n2, n1 * n2}[opt];
// 转换为字符运算符
char optChar = "+-x".charAt(opt);
this.setArithmeticString(String.format("%s%c%s=?", n1, optChar, n2));
this.chars = String.valueOf(res);
return chars.toCharArray();
}
}
}

View File

@ -25,8 +25,9 @@ import me.zhengjie.annotation.Log;
import me.zhengjie.annotation.rest.AnonymousDeleteMapping;
import me.zhengjie.annotation.rest.AnonymousGetMapping;
import me.zhengjie.annotation.rest.AnonymousPostMapping;
import me.zhengjie.config.RsaProperties;
import me.zhengjie.config.properties.RsaProperties;
import me.zhengjie.exception.BadRequestException;
import me.zhengjie.modules.security.config.bean.CodeProperties;
import me.zhengjie.modules.security.config.bean.LoginCodeEnum;
import me.zhengjie.modules.security.config.bean.LoginProperties;
import me.zhengjie.modules.security.config.bean.SecurityProperties;
@ -47,7 +48,7 @@ import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
@ -63,14 +64,14 @@ import java.util.concurrent.TimeUnit;
@RequestMapping("/auth")
@RequiredArgsConstructor
@Api(tags = "系统:系统授权接口")
public class AuthorizationController {
public class AuthController {
private final SecurityProperties properties;
private final RedisUtils redisUtils;
private final OnlineUserService onlineUserService;
private final TokenProvider tokenProvider;
private final AuthenticationManagerBuilder authenticationManagerBuilder;
@Resource
private LoginProperties loginProperties;
private final CodeProperties codeProperties;
private final LoginProperties loginProperties;
@Log("用户登录")
@ApiOperation("登录授权")
@ -123,7 +124,7 @@ public class AuthorizationController {
@AnonymousGetMapping(value = "/code")
public ResponseEntity<Object> getCode() {
// 获取运算的结果
Captcha captcha = loginProperties.getCaptcha();
Captcha captcha = codeProperties.getCaptcha();
String uuid = properties.getCodeKey() + IdUtil.simpleUUID();
//当验证码类型为 arithmetic时且长度 >= 2 captcha.text()的结果有几率为浮点型
String captchaValue = captcha.text();
@ -131,7 +132,7 @@ public class AuthorizationController {
captchaValue = captchaValue.split("\\.")[0];
}
// 保存
redisUtils.set(uuid, captchaValue, loginProperties.getLoginCode().getExpiration(), TimeUnit.MINUTES);
redisUtils.set(uuid, captchaValue, codeProperties.getExpiration(), TimeUnit.MINUTES);
// 验证码信息
Map<String, Object> imgResult = new HashMap<String, Object>(2) {{
put("img", captcha.toBase64());

View File

@ -21,7 +21,7 @@ import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import me.zhengjie.annotation.Log;
import me.zhengjie.config.RsaProperties;
import me.zhengjie.config.properties.RsaProperties;
import me.zhengjie.modules.system.domain.Dept;
import me.zhengjie.modules.system.domain.Role;
import me.zhengjie.modules.system.service.DataService;

View File

@ -35,7 +35,7 @@ import java.util.*;
**/
@Service
@RequiredArgsConstructor
@CacheConfig(cacheNames = "data")
@CacheConfig(cacheNames = "data", keyGenerator = "keyGenerator")
public class DataServiceImpl implements DataService {
private final RoleService roleService;

View File

@ -45,7 +45,7 @@ import java.util.stream.Collectors;
*/
@Service
@RequiredArgsConstructor
@CacheConfig(cacheNames = "dept")
@CacheConfig(cacheNames = "dept", keyGenerator = "keyGenerator")
public class DeptServiceImpl extends ServiceImpl<DeptMapper, Dept> implements DeptService {
private final DeptMapper deptMapper;

View File

@ -37,7 +37,7 @@ import java.util.List;
*/
@Service
@RequiredArgsConstructor
@CacheConfig(cacheNames = "dict")
@CacheConfig(cacheNames = "dict", keyGenerator = "keyGenerator")
public class DictDetailServiceImpl extends ServiceImpl<DictDetailMapper, DictDetail> implements DictDetailService {
private final DictMapper dictMapper;

View File

@ -39,7 +39,7 @@ import java.util.*;
*/
@Service
@RequiredArgsConstructor
@CacheConfig(cacheNames = "dict")
@CacheConfig(cacheNames = "dict", keyGenerator = "keyGenerator")
public class DictServiceImpl extends ServiceImpl<DictMapper, Dict> implements DictService {
private final DictMapper dictMapper;

View File

@ -41,7 +41,7 @@ import java.util.*;
*/
@Service
@RequiredArgsConstructor
@CacheConfig(cacheNames = "job")
@CacheConfig(cacheNames = "job", keyGenerator = "keyGenerator")
public class JobServiceImpl extends ServiceImpl<JobMapper, Job> implements JobService {
private final JobMapper jobMapper;
@ -49,6 +49,7 @@ public class JobServiceImpl extends ServiceImpl<JobMapper, Job> implements JobSe
private final UserMapper userMapper;
@Override
@Cacheable
public PageResult<Job> queryAll(JobQueryCriteria criteria, Page<Object> page) {
return PageUtil.toPage(jobMapper.findAll(criteria, page));
}

View File

@ -48,7 +48,7 @@ import java.util.stream.Collectors;
*/
@Service
@RequiredArgsConstructor
@CacheConfig(cacheNames = "menu")
@CacheConfig(cacheNames = "menu", keyGenerator = "keyGenerator")
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements MenuService {
private final MenuMapper menuMapper;

View File

@ -49,7 +49,7 @@ import java.util.stream.Collectors;
*/
@Service
@RequiredArgsConstructor
@CacheConfig(cacheNames = "role")
@CacheConfig(cacheNames = "role", keyGenerator = "keyGenerator")
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements RoleService {
private final RoleMapper roleMapper;
@ -154,7 +154,7 @@ public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements Ro
@Override
public Integer findByRoles(Set<Role> roles) {
if (roles.size() == 0) {
if (CollUtil.isEmpty(roles)) {
return Integer.MAX_VALUE;
}
Set<Role> roleSet = new HashSet<>();

View File

@ -18,7 +18,7 @@ package me.zhengjie.modules.system.service.impl;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import me.zhengjie.config.FileProperties;
import me.zhengjie.config.properties.FileProperties;
import me.zhengjie.exception.BadRequestException;
import me.zhengjie.modules.security.service.OnlineUserService;
import me.zhengjie.modules.security.service.UserCacheManager;
@ -51,7 +51,7 @@ import java.util.stream.Collectors;
*/
@Service
@RequiredArgsConstructor
@CacheConfig(cacheNames = "user")
@CacheConfig(cacheNames = "user", keyGenerator = "keyGenerator")
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
private final UserMapper userMapper;

View File

@ -58,7 +58,7 @@ login:
# 存活时间/秒
idle-time: 21600
# 验证码
login-code:
code:
# 验证码类型配置 查看 LoginProperties 类
code-type: arithmetic
# 登录图形验证码有效时间/分钟

View File

@ -60,7 +60,7 @@ login:
# 存活时间/秒
idle-time: 21600
# 验证码
login-code:
code:
# 验证码类型配置 查看 LoginProperties 类
code-type: arithmetic
# 登录图形验证码有效时间/分钟

View File

@ -19,7 +19,7 @@ import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.annotation.AnonymousAccess;
import me.zhengjie.annotation.rest.AnonymousAccess;
import me.zhengjie.annotation.Log;
import me.zhengjie.annotation.rest.AnonymousGetMapping;
import me.zhengjie.domain.vo.TradeVo;

View File

@ -38,7 +38,7 @@ import org.springframework.transaction.annotation.Transactional;
*/
@Service
@RequiredArgsConstructor
@CacheConfig(cacheNames = "aliPay")
@CacheConfig(cacheNames = "aliPay", keyGenerator = "keyGenerator")
public class AliPayServiceImpl extends ServiceImpl<AliPayConfigMapper, AlipayConfig> implements AliPayService {
@Override

View File

@ -37,7 +37,7 @@ import org.springframework.transaction.annotation.Transactional;
*/
@Service
@RequiredArgsConstructor
@CacheConfig(cacheNames = "email")
@CacheConfig(cacheNames = "email", keyGenerator = "keyGenerator")
public class EmailServiceImpl extends ServiceImpl<EmailConfigMapper, EmailConfig> implements EmailService {
@Override

View File

@ -19,7 +19,7 @@ import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import me.zhengjie.config.FileProperties;
import me.zhengjie.config.properties.FileProperties;
import me.zhengjie.domain.LocalStorage;
import me.zhengjie.domain.vo.LocalStorageQueryCriteria;
import me.zhengjie.exception.BadRequestException;

View File

@ -33,7 +33,7 @@ import org.springframework.transaction.annotation.Transactional;
*/
@Service
@RequiredArgsConstructor
@CacheConfig(cacheNames = "qiNiu")
@CacheConfig(cacheNames = "qiNiu", keyGenerator = "keyGenerator")
public class QiNiuConfigServiceImpl extends ServiceImpl<QiniuConfigMapper, QiniuConfig> implements QiNiuConfigService {
@Override

View File

@ -52,7 +52,7 @@ import java.util.*;
*/
@Service
@RequiredArgsConstructor
@CacheConfig(cacheNames = "qiNiu")
@CacheConfig(cacheNames = "qiNiu", keyGenerator = "keyGenerator")
public class QiniuContentServiceImpl extends ServiceImpl<QiniuContentMapper, QiniuContent> implements QiniuContentService {
private final QiniuContentMapper qiniuContentMapper;

View File

@ -76,6 +76,19 @@
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--Spring boot redisson-->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.17.1</version>
</dependency>
<!-- Spring boot websocket -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<!-- mybatis -->
<dependency>
<groupId>com.baomidou</groupId>