Merge branch 'master' into deploy

# Conflicts:
#	eladmin-system/src/main/java/me/zhengjie/modules/maint/rest/DeployController.java
#	eladmin-system/src/main/resources/config/application-prod.yml
pull/875/head
Jie Zheng 2025-01-16 13:41:36 +08:00
commit 3997a67cc6
297 changed files with 2678 additions and 1982 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -28,7 +28,7 @@ import java.lang.annotation.Target;
* @DataPermission(joinName = "dept", fieldName = "id")
* </p>
* @author Zheng Jie
* @website https://eladmin.vip
* @website <a href="https://eladmin.vip">...</a>
* @date 2020-05-07
**/
@Target(ElementType.TYPE)

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -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

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,5 +1,7 @@
package me.zhengjie.base;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.lang3.builder.ToStringBuilder;
@ -15,14 +17,21 @@ import java.sql.Timestamp;
@Setter
public class BaseDTO implements Serializable {
@ApiModelProperty(value = "创建人")
private String createBy;
@ApiModelProperty(value = "修改人")
private String updateBy;
@ApiModelProperty(value = "创建时间: yyyy-MM-dd HH:mm:ss", hidden = true)
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
private Timestamp createTime;
@ApiModelProperty(value = "更新时间: yyyy-MM-dd HH:mm:ss", hidden = true)
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
private Timestamp updateTime;
@Override
public String toString() {
ToStringBuilder builder = new ToStringBuilder(this);

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -15,6 +15,7 @@
*/
package me.zhengjie.base;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
@ -54,12 +55,14 @@ public class BaseEntity implements Serializable {
@CreationTimestamp
@Column(name = "create_time", updatable = false)
@ApiModelProperty(value = "创建时间", hidden = true)
@ApiModelProperty(value = "创建时间: yyyy-MM-dd HH:mm:ss", hidden = true)
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
private Timestamp createTime;
@UpdateTimestamp
@Column(name = "update_time")
@ApiModelProperty(value = "更新时间", hidden = true)
@ApiModelProperty(value = "更新时间: yyyy-MM-dd HH:mm:ss", hidden = true)
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
private Timestamp updateTime;
/* 分组校验 */

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -0,0 +1,96 @@
/*
* Copyright 2019-2025 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.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 线
* @author Zheng Jie
* @description
* @date 2023-06-08
**/
@EnableAsync
@Configuration
public class AsyncExecutor implements AsyncConfigurer {
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
*/
@Override
public Executor getAsyncExecutor() {
// 自定义工厂
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());
}
/**
* 线使
* private ThreadPoolTaskExecutor taskExecutor;
* @return ThreadPoolTaskExecutor
*/
@Bean("taskAsync")
public ThreadPoolTaskExecutor taskAsync() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(2);
executor.setMaxPoolSize(4);
executor.setQueueCapacity(20);
executor.setKeepAliveSeconds(60);
executor.setThreadNamePrefix("el-task-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
return executor;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -0,0 +1,62 @@
/*
* Copyright 2019-2025 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 cn.hutool.core.util.StrUtil;
import com.p6spy.engine.spy.appender.MessageFormattingStrategy;
import lombok.extern.slf4j.Slf4j;
/**
* @author Zheng Jie
* @description p6spy sql
* @date 2024-12-26
**/
@Slf4j
public class CustomP6SpyLogger implements MessageFormattingStrategy {
// 重置颜色
private static final String RESET = "\u001B[0m";
// 红色
private static final String RED = "\u001B[31m";
// 绿色
private static final String GREEN = "\u001B[32m";
/**
* sql
* @param connectionId id
* @param now
* @param elapsed
* @param category sql
* @param prepared sql
* @param sql sql
* @param url url
* @return sql
*/
@Override
public String formatMessage(int connectionId, String now, long elapsed, String category, String prepared, String sql, String url) {
// 去掉换行和多余空格
if(StrUtil.isNotBlank(sql)){
sql = sql.replaceAll("\\s+", " ").trim();
}
// 格式化并加上颜色
return String.format(
"%s[Time: %dms]%s - %s%s%s;",
GREEN, elapsed, RESET, RED, sql, RESET
);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -15,47 +15,39 @@
*/
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 +62,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<>();
//序列化
@ -92,6 +82,8 @@ public class RedisConfig extends CachingConfigurerSupport {
ParserConfig.getGlobalInstance().addAccept("me.zhengjie.modules.quartz.service.dto");
ParserConfig.getGlobalInstance().addAccept("me.zhengjie.modules.security.service.dto");
ParserConfig.getGlobalInstance().addAccept("me.zhengjie.modules.system.service.dto");
// 分页返回数据
ParserConfig.getGlobalInstance().addAccept("me.zhengjie.utils.PageResult");
// key的序列化采用StringRedisSerializer
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
@ -100,10 +92,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
* 使SimpleKeyGeneratorkey
* CachingConfigurerSupport PR
*/
@Bean
@Override
public KeyGenerator keyGenerator() {
return (target, method, params) -> {
Map<String,Object> container = new HashMap<>(8);
@ -126,100 +132,63 @@ public class RedisConfig extends CachingConfigurerSupport {
}
@Bean
@Override
@SuppressWarnings({"all"})
@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
*
* @author /
* @param <T>
*/
class FastJsonRedisSerializer<T> implements RedisSerializer<T> {
/**
* Value
*
* @param <T>
* @author /
*/
static 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,68 @@
/*
* Copyright 2019-2025 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 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

@ -0,0 +1,78 @@
package me.zhengjie.config;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure;
import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties;
import com.alibaba.druid.util.Utils;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author Zheng Jie
* @description
* @date 2025-01-11
**/
@Configuration
@SuppressWarnings("all")
@ConditionalOnWebApplication
@AutoConfigureAfter(DruidDataSourceAutoConfigure.class)
@ConditionalOnProperty(name = "spring.datasource.druid.stat-view-servlet.enabled",
havingValue = "true", matchIfMissing = true)
public class RemoveDruidAdConfig {
/**
* : removeDruidAdFilterRegistrationBean
* 广
* @param properties com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties
* @return org.springframework.boot.web.servlet.FilterRegistrationBean
*/
@Bean
public FilterRegistrationBean removeDruidAdFilterRegistrationBean(DruidStatProperties properties) {
// 获取web监控页面的参数
DruidStatProperties.StatViewServlet config = properties.getStatViewServlet();
// 提取common.js的配置路径
String pattern = config.getUrlPattern() != null ? config.getUrlPattern() : "/druid/*";
String commonJsPattern = pattern.replaceAll("\\*", "js/common.js");
final String filePath = "support/http/resources/js/common.js";
//创建filter进行过滤
Filter filter = new Filter() {
@Override
public void init(FilterConfig filterConfig) throws ServletException {}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
if (httpRequest.getRequestURI().endsWith("js/common.js")) {
// 获取common.js
String text = Utils.readFromResource(filePath);
// 正则替换banner, 除去底部的广告信息
text = text.replaceAll("<a.*?druid_banner\"></a><br/>", "");
text = text.replaceAll("powered by.*?shrek.wang</a>", "");
httpResponse.setContentType("application/javascript");
httpResponse.setCharacterEncoding("UTF-8");
httpResponse.getWriter().write(text);
} else {
chain.doFilter(request, response);
}
}
@Override
public void destroy() {}
};
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
registrationBean.setFilter(filter);
registrationBean.addUrlPatterns(commonJsPattern);
return registrationBean;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -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

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -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

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,11 +13,12 @@
* 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;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -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.boot.web.servlet.MultipartConfigFactory;
import org.springframework.context.annotation.Bean;
@ -23,7 +23,7 @@ import java.io.File;
/**
* @date 2018-12-28
* @author https://blog.csdn.net/llibin1024530411/article/details/79474953
* @author <a href="https://blog.csdn.net/llibin1024530411/article/details/79474953">...</a>
*/
@Configuration
public class MultipartConfig {

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.apache.catalina.connector.Connector;
import org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer;
@ -23,7 +23,7 @@ import org.springframework.context.annotation.Configuration;
* @author bearBoy80
*/
@Configuration(proxyBeanMethods = false)
public class RelaxedQueryCharsConnectorCustomizer implements TomcatConnectorCustomizer {
public class QueryCustomizer implements TomcatConnectorCustomizer {
@Override
public void customize(Connector connector) {
connector.setProperty("relaxedQueryChars", "[]{}");

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,22 +13,20 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.zhengjie.config;
package me.zhengjie.config.webConfig;
import cn.hutool.core.collection.CollUtil;
import com.fasterxml.classmate.TypeResolver;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import me.zhengjie.utils.AnonTagUtils;
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.core.Ordered;
import org.springframework.data.domain.Pageable;
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.schema.AlternateTypeRule;
import springfox.documentation.schema.AlternateTypeRuleConvention;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.ApiKey;
import springfox.documentation.service.AuthorizationScope;
@ -37,11 +35,15 @@ 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 static springfox.documentation.schema.AlternateTypeRules.newRule;
import java.util.Set;
import java.util.stream.Collectors;
/**
* api /doc.html
@ -50,6 +52,7 @@ import static springfox.documentation.schema.AlternateTypeRules.newRule;
*/
@Configuration
@EnableSwagger2
@RequiredArgsConstructor
public class SwaggerConfig {
@Value("${jwt.header}")
@ -58,6 +61,11 @@ public class SwaggerConfig {
@Value("${swagger.enabled}")
private Boolean enabled;
@Value("${server.servlet.context-path:}")
private String apiPath;
private final ApplicationContext applicationContext;
@Bean
@SuppressWarnings("all")
public Docket createRestApi() {
@ -98,10 +106,14 @@ public class SwaggerConfig {
}
private SecurityContext getContextByPath() {
Set<String> urls = AnonTagUtils.getAllAnonymousUrl(applicationContext);
urls = urls.stream().filter(url -> !url.equals("/")).collect(Collectors.toSet());
String regExp = "^(?!" + apiPath + String.join("|" + apiPath, urls) + ").*$";
return SecurityContext.builder()
.securityReferences(defaultAuth())
// 表示 /auth/code、/auth/login 接口不需要使用securitySchemes即不需要带token
.operationSelector(o->o.requestMappingPattern().matches("^(?!/auth/code|/auth/login).*$"))
.operationSelector(o->o.requestMappingPattern()
// 排除不需要认证的接口
.matches(regExp))
.build();
}
@ -113,39 +125,45 @@ public class SwaggerConfig {
securityReferences.add(new SecurityReference(tokenHeader, authorizationScopes));
return securityReferences;
}
}
/**
* Pageableswagger
*/
@Configuration
class SwaggerDataConfig {
/**
* SpringfoxSpringBootWebMvcRequestHandlerProviderWebFluxRequestHandlerProvider
* @return /
*/
@Bean
public AlternateTypeRuleConvention pageableConvention(final TypeResolver resolver) {
return new AlternateTypeRuleConvention() {
@SuppressWarnings({"all"})
public static BeanPostProcessor springfoxHandlerProviderBeanPostProcessor() {
return new BeanPostProcessor() {
@Override
public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE;
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof WebMvcRequestHandlerProvider || bean instanceof WebFluxRequestHandlerProvider) {
customizeSpringfoxHandlerMappings(getHandlerMappings(bean));
}
return bean;
}
@Override
public List<AlternateTypeRule> rules() {
return CollUtil.newArrayList(newRule(resolver.resolve(Pageable.class), resolver.resolve(Page.class)));
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();
}
};
}
@ApiModel
@Data
private static class Page {
@ApiModelProperty("页码 (0..N)")
private Integer page;
@ApiModelProperty("每页显示的数目")
private Integer size;
@ApiModelProperty("以下列格式排序标准property[,asc | desc]。 默认排序顺序为升序。 支持多种排序条件id,asc")
private List<String> sort;
}
}

View File

@ -0,0 +1,52 @@
package me.zhengjie.config.webConfig;
import cn.hutool.core.collection.CollUtil;
import com.fasterxml.classmate.TypeResolver;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.data.domain.Pageable;
import springfox.documentation.schema.AlternateTypeRule;
import springfox.documentation.schema.AlternateTypeRuleConvention;
import java.util.List;
import static springfox.documentation.schema.AlternateTypeRules.newRule;
/**
* Pageableswagger
*/
@Configuration
public class SwaggerDataConfig {
@Bean
public AlternateTypeRuleConvention pageableConvention(final TypeResolver resolver) {
return new AlternateTypeRuleConvention() {
@Override
public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE;
}
@Override
public List<AlternateTypeRule> rules() {
return CollUtil.newArrayList(newRule(resolver.resolve(Pageable.class), resolver.resolve(Page.class)));
}
};
}
@ApiModel
@Data
private static class Page {
@ApiModelProperty("页码 (0..N)")
private Integer page;
@ApiModelProperty("每页显示的数目")
private Integer size;
@ApiModelProperty("以下列格式排序标准property[,asc | desc]。 默认排序顺序为升序。 支持多种排序条件id,asc")
private List<String> sort;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -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

@ -1,98 +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.exception;
/**
*
*
* @author: liaojinlong
* @date: 2020/6/10 18:06
*/
public class BadConfigurationException extends RuntimeException {
/**
* Constructs a new runtime exception with {@code null} as its
* detail message. The cause is not initialized, and may subsequently be
* initialized by a call to {@link #initCause}.
*/
public BadConfigurationException() {
super();
}
/**
* Constructs a new runtime exception with the specified detail message.
* The cause is not initialized, and may subsequently be initialized by a
* call to {@link #initCause}.
*
* @param message the detail message. The detail message is saved for
* later retrieval by the {@link #getMessage()} method.
*/
public BadConfigurationException(String message) {
super(message);
}
/**
* Constructs a new runtime exception with the specified detail message and
* cause. <p>Note that the detail message associated with
* {@code cause} is <i>not</i> automatically incorporated in
* this runtime exception's detail message.
*
* @param message the detail message (which is saved for later retrieval
* by the {@link #getMessage()} method).
* @param cause the cause (which is saved for later retrieval by the
* {@link #getCause()} method). (A {@code null} value is
* permitted, and indicates that the cause is nonexistent or
* unknown.)
* @since 1.4
*/
public BadConfigurationException(String message, Throwable cause) {
super(message, cause);
}
/**
* Constructs a new runtime exception with the specified cause and a
* detail message of {@code (cause==null ? null : cause.toString())}
* (which typically contains the class and detail message of
* {@code cause}). This constructor is useful for runtime exceptions
* that are little more than wrappers for other throwables.
*
* @param cause the cause (which is saved for later retrieval by the
* {@link #getCause()} method). (A {@code null} value is
* permitted, and indicates that the cause is nonexistent or
* unknown.)
* @since 1.4
*/
public BadConfigurationException(Throwable cause) {
super(cause);
}
/**
* Constructs a new runtime exception with the specified detail
* message, cause, suppression enabled or disabled, and writable
* stack trace enabled or disabled.
*
* @param message the detail message.
* @param cause the cause. (A {@code null} value is permitted,
* and indicates that the cause is nonexistent or unknown.)
* @param enableSuppression whether or not suppression is enabled
* or disabled
* @param writableStackTrace whether or not the stack trace should
* be writable
* @since 1.7
*/
protected BadConfigurationException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -22,7 +22,7 @@ import lombok.Data;
* @date 2018-11-23
*/
@Data
class ApiError {
public class ApiError {
private Integer status = 400;
private Long timestamp;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -0,0 +1,103 @@
/*
* 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 me.zhengjie.annotation.rest.AnonymousAccess;
import me.zhengjie.utils.enums.RequestMethodEnum;
import org.springframework.context.ApplicationContext;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import java.util.*;
/**
* @author Zheng Jie
* @description
* @date 2025-01-13
**/
public class AnonTagUtils {
/**
* URL
* @param applicationContext /
* @return /
*/
public static Map<String, Set<String>> getAnonymousUrl(ApplicationContext applicationContext){
RequestMappingHandlerMapping requestMappingHandlerMapping = (RequestMappingHandlerMapping) applicationContext.getBean("requestMappingHandlerMapping");
Map<RequestMappingInfo, HandlerMethod> handlerMethodMap = requestMappingHandlerMapping.getHandlerMethods();
Map<String, Set<String>> anonymousUrls = new HashMap<>(8);
// 获取匿名标记
Set<String> get = new HashSet<>();
Set<String> post = new HashSet<>();
Set<String> put = new HashSet<>();
Set<String> patch = new HashSet<>();
Set<String> delete = new HashSet<>();
Set<String> all = new HashSet<>();
for (Map.Entry<RequestMappingInfo, HandlerMethod> infoEntry : handlerMethodMap.entrySet()) {
HandlerMethod handlerMethod = infoEntry.getValue();
AnonymousAccess anonymousAccess = handlerMethod.getMethodAnnotation(AnonymousAccess.class);
if (null != anonymousAccess) {
List<RequestMethod> requestMethods = new ArrayList<>(infoEntry.getKey().getMethodsCondition().getMethods());
RequestMethodEnum request = RequestMethodEnum.find(requestMethods.isEmpty() ? RequestMethodEnum.ALL.getType() : requestMethods.get(0).name());
if (infoEntry.getKey().getPatternsCondition()!=null) {
switch (Objects.requireNonNull(request)) {
case GET:
get.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());
break;
case POST:
post.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());
break;
case PUT:
put.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());
break;
case PATCH:
patch.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());
break;
case DELETE:
delete.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());
break;
default:
all.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());
break;
}
}
}
}
anonymousUrls.put(RequestMethodEnum.GET.getType(), get);
anonymousUrls.put(RequestMethodEnum.POST.getType(), post);
anonymousUrls.put(RequestMethodEnum.PUT.getType(), put);
anonymousUrls.put(RequestMethodEnum.PATCH.getType(), patch);
anonymousUrls.put(RequestMethodEnum.DELETE.getType(), delete);
anonymousUrls.put(RequestMethodEnum.ALL.getType(), all);
return anonymousUrls;
}
/**
* URL
* @param applicationContext /
* @return /
*/
public static Set<String> getAllAnonymousUrl(ApplicationContext applicationContext){
Set<String> allUrl = new HashSet<>();
Map<String, Set<String>> anonymousUrls = getAnonymousUrl(applicationContext);
for (String key : anonymousUrls.keySet()) {
allUrl.addAll(anonymousUrls.get(key));
}
return allUrl;
}
}

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

@ -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 SpringContextHolder}
* SpringContextHolder <br>
* <br>
* SpringContextHolder 使
*/
public interface CallBack {
/**
*
*/
void executor();
/**
*
* @return /
*/
default String getCallBackName() {
return Thread.currentThread().getId() + ":" + this.getClass().getName();
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -19,16 +19,17 @@ import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.poi.excel.BigExcelWriter;
import cn.hutool.poi.excel.ExcelUtil;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.exception.BadRequestException;
import org.apache.poi.util.IOUtils;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.file.Files;
import java.security.MessageDigest;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
@ -44,10 +45,9 @@ import java.util.stream.Collectors;
* @author Zheng Jie
* @date 2018-12-27
*/
@Slf4j
public class FileUtil extends cn.hutool.core.io.FileUtil {
private static final Logger log = LoggerFactory.getLogger(FileUtil.class);
/**
*
* <br>
@ -110,7 +110,7 @@ public class FileUtil extends cn.hutool.core.io.FileUtil {
* .
*/
public static String getExtensionName(String filename) {
if ((filename != null) && (filename.length() > 0)) {
if ((filename != null) && (!filename.isEmpty())) {
int dot = filename.lastIndexOf('.');
if ((dot > -1) && (dot < (filename.length() - 1))) {
return filename.substring(dot + 1);
@ -123,9 +123,9 @@ public class FileUtil extends cn.hutool.core.io.FileUtil {
* Java
*/
public static String getFileNameNoEx(String filename) {
if ((filename != null) && (filename.length() > 0)) {
if ((filename != null) && (!filename.isEmpty())) {
int dot = filename.lastIndexOf('.');
if ((dot > -1) && (dot < (filename.length()))) {
if (dot > -1) {
return filename.substring(0, dot);
}
}
@ -162,7 +162,7 @@ public class FileUtil extends cn.hutool.core.io.FileUtil {
}
OutputStream os = null;
try {
os = new FileOutputStream(file);
os = Files.newOutputStream(file.toPath());
int bytesRead;
int len = 8192;
byte[] buffer = new byte[len];
@ -170,7 +170,7 @@ public class FileUtil extends cn.hutool.core.io.FileUtil {
os.write(buffer, 0, bytesRead);
}
} catch (Exception e) {
e.printStackTrace();
log.error(e.getMessage(), e);
} finally {
CloseUtil.close(os);
CloseUtil.close(ins);
@ -301,7 +301,7 @@ public class FileUtil extends cn.hutool.core.io.FileUtil {
byte[] b = new byte[(int) file.length()];
InputStream in = null;
try {
in = new FileInputStream(file);
in = Files.newInputStream(file.toPath());
try {
System.out.println(in.read(b));
} catch (IOException e) {
@ -407,7 +407,6 @@ public class FileUtil extends cn.hutool.core.io.FileUtil {
return fileName;
}
public static String getMd5(File file) {
return getMd5(getByte(file));
}

View File

@ -1,16 +1,24 @@
package me.zhengjie.utils;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.List;
@Getter
@RequiredArgsConstructor(access = AccessLevel.PACKAGE)
public class PageResult<T> {
/**
*
* @author Zheng Jie
* @date 2018-11-23
* @param <T>
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class PageResult<T> implements Serializable {
private final List<T> content;
private List<T> content;
private final long totalElements;
private long totalElements;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -15,6 +15,7 @@
*/
package me.zhengjie.utils;
import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.slf4j.Logger;
@ -24,14 +25,16 @@ import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.*;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Component;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
* @author /
*/
@Component
@SuppressWarnings({"unchecked", "all"})
@SuppressWarnings({"all"})
public class RedisUtils {
private static final Logger log = LoggerFactory.getLogger(RedisUtils.class);
@ -39,9 +42,8 @@ public class RedisUtils {
public RedisUtils(RedisTemplate<Object, Object> redisTemplate) {
this.redisTemplate = redisTemplate;
this.redisTemplate.setHashKeySerializer(new StringRedisSerializer());
this.redisTemplate.setKeySerializer(new StringRedisSerializer());
this.redisTemplate.setStringSerializer(new StringRedisSerializer());
this.redisTemplate.setHashKeySerializer(new StringRedisSerializer());
}
/**
@ -221,6 +223,65 @@ public class RedisUtils {
return key == null ? null : redisTemplate.opsForValue().get(key);
}
/**
*
*
* @param key
* @return
*/
public <T> T get(String key, Class<T> clazz) {
Object value = key == null ? null : redisTemplate.opsForValue().get(key);
if (value == null) {
return null;
}
if (clazz.isInstance(value)) {
return clazz.cast(value);
} else {
return null;
}
}
/**
*
*
* @param key
* @param clazz
* @return
*/
public <T> List<T> getList(String key, Class<T> clazz) {
Object value = key == null ? null : redisTemplate.opsForValue().get(key);
if (value == null) {
return null;
}
if (value instanceof List<?>) {
List<?> list = (List<?>) value;
// 检查每个元素是否为指定类型
if (list.stream().allMatch(clazz::isInstance)) {
return list.stream().map(clazz::cast).collect(Collectors.toList());
}
}
return null;
}
/**
*
*
* @param key
* @return
*/
public String getStr(String key) {
if(StrUtil.isBlank(key)){
return null;
}
Object value = redisTemplate.opsForValue().get(key);
if (value == null) {
return null;
} else {
return String.valueOf(value);
}
}
/**
*
*
@ -242,13 +303,17 @@ public class RedisUtils {
* @return true false
*/
public boolean set(String key, Object value) {
try {
redisTemplate.opsForValue().set(key, value);
return true;
} catch (Exception e) {
log.error(e.getMessage(), e);
return false;
int attempt = 0;
while (attempt < 3) {
try {
redisTemplate.opsForValue().set(key, value);
return true;
} catch (Exception e) {
attempt++;
log.error("Attempt {} failed: {}", attempt, e.getMessage(), e);
}
}
return false;
}
/**
@ -716,10 +781,25 @@ public class RedisUtils {
keys.addAll(redisTemplate.keys(new StringBuffer(prefix).append(id).toString()));
}
long count = redisTemplate.delete(keys);
// 此处提示可自行删除
log.debug("--------------------------------------------");
log.debug("成功删除缓存:" + keys.toString());
log.debug("缓存删除数量:" + count + "个");
log.debug("--------------------------------------------");
}
// ============================incr=============================
/**
*
* @param key
* @return
*/
public Long increment(String key) {
return redisTemplate.opsForValue().increment(key);
}
/**
*
* @param key
* @return
*/
public Long decrement(String key) {
return redisTemplate.opsForValue().decrement(key);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -15,18 +15,24 @@
*/
package me.zhengjie.utils;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.exception.BadRequestException;
import me.zhengjie.utils.enums.DataScopeEnum;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Objects;
/**
*
@ -34,45 +40,32 @@ import java.util.List;
* @date 2019-01-17
*/
@Slf4j
@Component
public class SecurityUtils {
public static String header;
public static String tokenStartWith;
@Value("${jwt.header}")
public void setHeader(String header) {
SecurityUtils.header = header;
}
@Value("${jwt.token-start-with}")
public void setTokenStartWith(String tokenStartWith) {
SecurityUtils.tokenStartWith = tokenStartWith;
}
/**
*
* @return UserDetails
*/
public static UserDetails getCurrentUser() {
UserDetailsService userDetailsService = SpringContextHolder.getBean(UserDetailsService.class);
UserDetailsService userDetailsService = SpringBeanHolder.getBean(UserDetailsService.class);
return userDetailsService.loadUserByUsername(getCurrentUsername());
}
/**
*
*
* @return
*/
public static String getCurrentUsername() {
final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null) {
throw new BadRequestException(HttpStatus.UNAUTHORIZED, "当前登录状态过期");
}
if (authentication.getPrincipal() instanceof UserDetails) {
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
return userDetails.getUsername();
}
throw new BadRequestException(HttpStatus.UNAUTHORIZED, "找不到当前登录的信息");
}
/**
* ID
* @return ID
*/
public static Long getCurrentUserId() {
UserDetails userDetails = getCurrentUser();
// 将 Java 对象转换为 JSONObject 对象
JSONObject jsonObject = (JSONObject) JSON.toJSON(userDetails);
return jsonObject.getJSONObject("user").getLong("id");
}
/**
*
* @return /
@ -91,9 +84,62 @@ public class SecurityUtils {
*/
public static String getDataScopeType() {
List<Long> dataScopes = getCurrentUserDataScope();
if(dataScopes.size() != 0){
if(CollUtil.isEmpty(dataScopes)){
return "";
}
return DataScopeEnum.ALL.getValue();
}
/**
* ID
* @return ID
*/
public static Long getCurrentUserId() {
return getCurrentUserId(getToken());
}
/**
* ID
* @return ID
*/
public static Long getCurrentUserId(String token) {
JWT jwt = JWTUtil.parseToken(token);
return Long.valueOf(jwt.getPayload("userId").toString());
}
/**
*
*
* @return
*/
public static String getCurrentUsername() {
return getCurrentUsername(getToken());
}
/**
*
*
* @return
*/
public static String getCurrentUsername(String token) {
JWT jwt = JWTUtil.parseToken(token);
return jwt.getPayload("sub").toString();
}
/**
* Token
* @return /
*/
public static String getToken() {
HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder
.getRequestAttributes())).getRequest();
String bearerToken = request.getHeader(header);
if (bearerToken != null && bearerToken.startsWith(tokenStartWith)) {
// 去掉令牌前缀
return bearerToken.replace(tokenStartWith, "");
} else {
log.debug("非法Token{}", bearerToken);
}
return null;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -31,10 +31,11 @@ import java.util.List;
* @date 2019-01-07
*/
@Slf4j
public class SpringContextHolder implements ApplicationContextAware, DisposableBean {
@SuppressWarnings("all")
public class SpringBeanHolder implements ApplicationContextAware, DisposableBean {
private static ApplicationContext applicationContext = null;
private static final List<CallBack> CALL_BACKS = new ArrayList<>();
private static final List<SpringBeanHolder.CallBack> CALL_BACKS = new ArrayList<>();
private static boolean addCallback = true;
/**
@ -43,9 +44,9 @@ public class SpringContextHolder implements ApplicationContextAware, DisposableB
*
* @param callBack
*/
public synchronized static void addCallBacks(CallBack callBack) {
public synchronized static void addCallBacks(SpringBeanHolder.CallBack callBack) {
if (addCallback) {
SpringContextHolder.CALL_BACKS.add(callBack);
SpringBeanHolder.CALL_BACKS.add(callBack);
} else {
log.warn("CallBack{} 已无法添加!立即执行", callBack.getCallBackName());
callBack.executor();
@ -55,7 +56,6 @@ public class SpringContextHolder implements ApplicationContextAware, DisposableB
/**
* applicationContextBean, .
*/
@SuppressWarnings("unchecked")
public static <T> T getBean(String name) {
assertContextInjected();
return (T) applicationContext.getBean(name);
@ -127,22 +127,22 @@ public class SpringContextHolder implements ApplicationContextAware, DisposableB
@Override
public void destroy() {
SpringContextHolder.clearHolder();
SpringBeanHolder.clearHolder();
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if (SpringContextHolder.applicationContext != null) {
log.warn("SpringContextHolder中的ApplicationContext被覆盖, 原有ApplicationContext为:" + SpringContextHolder.applicationContext);
if (SpringBeanHolder.applicationContext != null) {
log.warn("SpringContextHolder中的ApplicationContext被覆盖, 原有ApplicationContext为:" + SpringBeanHolder.applicationContext);
}
SpringContextHolder.applicationContext = applicationContext;
SpringBeanHolder.applicationContext = applicationContext;
if (addCallback) {
for (CallBack callBack : SpringContextHolder.CALL_BACKS) {
for (SpringBeanHolder.CallBack callBack : SpringBeanHolder.CALL_BACKS) {
callBack.executor();
}
CALL_BACKS.clear();
}
SpringContextHolder.addCallback = false;
SpringBeanHolder.addCallback = false;
}
/**
@ -153,4 +153,20 @@ public class SpringContextHolder implements ApplicationContextAware, DisposableB
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

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -41,7 +41,7 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils {
/**
* bean
*/
private final static Ip2regionSearcher IP_SEARCHER = SpringContextHolder.getBean(Ip2regionSearcher.class);
private final static Ip2regionSearcher IP_SEARCHER = SpringBeanHolder.getBean(Ip2regionSearcher.class);
/**
*

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -32,7 +32,7 @@ import java.io.Serializable;
@Setter
@Entity
@NoArgsConstructor
@Table(name = "code_column_config")
@Table(name = "code_column")
public class ColumnInfo implements Serializable {
@Id

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -32,7 +32,7 @@ import java.io.Serializable;
@Setter
@Entity
@NoArgsConstructor
@Table(name = "code_gen_config")
@Table(name = "code_config")
public class GenConfig implements Serializable {
public GenConfig(String tableName) {

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -15,6 +15,8 @@
*/
package me.zhengjie.domain.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@ -29,20 +31,19 @@ import lombok.NoArgsConstructor;
@NoArgsConstructor
public class TableInfo {
/** 表名称 */
@ApiModelProperty(value = "表名称")
private Object tableName;
/** 创建日期 */
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty(value = "创建日期yyyy-MM-dd HH:mm:ss")
private Object createTime;
/** 数据库引擎 */
@ApiModelProperty(value = "数据库引擎")
private Object engine;
/** 编码集 */
@ApiModelProperty(value = "编码集")
private Object coding;
/** 备注 */
@ApiModelProperty(value = "备注")
private Object remark;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -20,7 +20,6 @@ import me.zhengjie.domain.ColumnInfo;
import me.zhengjie.domain.vo.TableInfo;
import me.zhengjie.utils.PageResult;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Async;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -19,7 +19,6 @@ import lombok.RequiredArgsConstructor;
import me.zhengjie.domain.GenConfig;
import me.zhengjie.repository.GenConfigRepository;
import me.zhengjie.service.GenConfigService;
import me.zhengjie.utils.StringUtils;
import org.springframework.stereotype.Service;
import java.io.File;
@ -29,6 +28,7 @@ import java.io.File;
*/
@Service
@RequiredArgsConstructor
@SuppressWarnings({"unchecked","all"})
public class GenConfigServiceImpl implements GenConfigService {
private final GenConfigRepository genConfigRepository;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -50,6 +50,7 @@ import java.util.stream.Collectors;
*/
@Service
@RequiredArgsConstructor
@SuppressWarnings({"unchecked","all"})
public class GeneratorServiceImpl implements GeneratorService {
private static final Logger log = LoggerFactory.getLogger(GeneratorServiceImpl.class);
@PersistenceContext

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -45,7 +45,7 @@ public class ColUtil {
*/
public static PropertiesConfiguration getConfig() {
try {
return new PropertiesConfiguration("generator.properties");
return new PropertiesConfiguration("gen.properties");
} catch (ConfigurationException e) {
log.error(e.getMessage(), e);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -39,13 +39,12 @@ import ${package}.service.dto.${className}Dto;
**/
@RestController
@RequiredArgsConstructor
@Api(tags = "${apiAlias}管理")
@Api(tags = "${apiAlias}")
@RequestMapping("/api/${changeClassName}")
public class ${className}Controller {
private final ${className}Service ${changeClassName}Service;
@Log("导出数据")
@ApiOperation("导出数据")
@GetMapping(value = "/download")
@PreAuthorize("@el.check('${changeClassName}:list')")
@ -54,7 +53,6 @@ public class ${className}Controller {
}
@GetMapping
@Log("查询${apiAlias}")
@ApiOperation("查询${apiAlias}")
@PreAuthorize("@el.check('${changeClassName}:list')")
public ResponseEntity<PageResult<${className}Dto>> query${className}(${className}QueryCriteria criteria, Pageable pageable){
@ -83,7 +81,7 @@ public class ${className}Controller {
@Log("删除${apiAlias}")
@ApiOperation("删除${apiAlias}")
@PreAuthorize("@el.check('${changeClassName}:del')")
public ResponseEntity<Object> delete${className}(@RequestBody ${pkColumnType}[] ids) {
public ResponseEntity<Object> delete${className}(@ApiParam(value = "传ID数组[]") @RequestBody ${pkColumnType}[] ids) {
${changeClassName}Service.deleteAll(ids);
return new ResponseEntity<>(HttpStatus.OK);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -27,6 +27,7 @@ import java.io.Serializable;
import com.alibaba.fastjson.annotation.JSONField;
import com.alibaba.fastjson.serializer.ToStringSerializer;
</#if>
import io.swagger.annotations.ApiModelProperty;
/**
* @website https://eladmin.vip
@ -40,7 +41,9 @@ public class ${className}Dto implements Serializable {
<#list columns as column>
<#if column.remark != ''>
/** ${column.remark} */
@ApiModelProperty(value = "${column.remark}")
<#else>
@ApiModelProperty(value = "${column.changeColumnName}")
</#if>
<#if column.columnKey = 'PRI'>
<#if !auto && pkColumnType = 'Long'>

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -34,6 +34,25 @@ import java.sql.Timestamp;
<#if hasBigDecimal>
import java.math.BigDecimal;
</#if>
<#assign notBlankUsed = false>
<#assign notNullUsed = false>
<#if columns??>
<#list columns as column>
<#if column.istNotNull && column.columnKey != 'PRI'>
<#if column.columnType = 'String'>
<#assign notBlankUsed = true>
<#else>
<#assign notNullUsed = true>
</#if>
</#if>
</#list>
</#if>
<#if notBlankUsed>
import javax.validation.constraints.NotBlank;
</#if>
<#if notNullUsed>
import javax.validation.constraints.NotNull;
</#if>
import java.io.Serializable;
/**

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -28,6 +28,7 @@ import java.util.List;
<#if queryColumns??>
import me.zhengjie.annotation.Query;
</#if>
import io.swagger.annotations.ApiModelProperty;
/**
* @website https://eladmin.vip
@ -42,31 +43,61 @@ public class ${className}QueryCriteria{
<#if column.queryType = '='>
/** 精确 */
@Query
<#if column.remark != ''>
@ApiModelProperty(value = "${column.remark}")
<#else>
@ApiModelProperty(value = "${column.changeColumnName}")
</#if>
private ${column.columnType} ${column.changeColumnName};
</#if>
<#if column.queryType = 'Like'>
/** 模糊 */
@Query(type = Query.Type.INNER_LIKE)
<#if column.remark != ''>
@ApiModelProperty(value = "${column.remark}")
<#else>
@ApiModelProperty(value = "${column.changeColumnName}")
</#if>
private ${column.columnType} ${column.changeColumnName};
</#if>
<#if column.queryType = '!='>
/** 不等于 */
@Query(type = Query.Type.NOT_EQUAL)
<#if column.remark != ''>
@ApiModelProperty(value = "${column.remark}")
<#else>
@ApiModelProperty(value = "${column.changeColumnName}")
</#if>
private ${column.columnType} ${column.changeColumnName};
</#if>
<#if column.queryType = 'NotNull'>
/** 不为空 */
@Query(type = Query.Type.NOT_NULL)
<#if column.remark != ''>
@ApiModelProperty(value = "${column.remark}")
<#else>
@ApiModelProperty(value = "${column.changeColumnName}")
</#if>
private ${column.columnType} ${column.changeColumnName};
</#if>
<#if column.queryType = '>='>
/** 大于等于 */
@Query(type = Query.Type.GREATER_THAN)
<#if column.remark != ''>
@ApiModelProperty(value = "${column.remark}")
<#else>
@ApiModelProperty(value = "${column.changeColumnName}")
</#if>
private ${column.columnType} ${column.changeColumnName};
</#if>
<#if column.queryType = '<='>
/** 小于等于 */
@Query(type = Query.Type.LESS_THAN)
<#if column.remark != ''>
@ApiModelProperty(value = "${column.remark}")
<#else>
@ApiModelProperty(value = "${column.changeColumnName}")
</#if>
private ${column.columnType} ${column.changeColumnName};
</#if>
</#list>

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -15,6 +15,8 @@
*/
package me.zhengjie.domain;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@ -36,41 +38,44 @@ public class SysLog implements Serializable {
@Id
@Column(name = "log_id")
@ApiModelProperty(value = "ID")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
/** 操作用户 */
@ApiModelProperty(value = "操作用户")
private String username;
/** 描述 */
@ApiModelProperty(value = "描述")
private String description;
/** 方法名 */
@ApiModelProperty(value = "方法名")
private String method;
/** 参数 */
@ApiModelProperty(value = "参数")
private String params;
/** 日志类型 */
@ApiModelProperty(value = "日志类型")
private String logType;
/** 请求ip */
@ApiModelProperty(value = "请求ip")
private String requestIp;
/** 地址 */
@ApiModelProperty(value = "地址")
private String address;
/** 浏览器 */
@ApiModelProperty(value = "浏览器")
private String browser;
/** 请求耗时 */
@ApiModelProperty(value = "请求耗时")
private Long time;
/** 异常详细 */
@ApiModelProperty(value = "异常详细")
private byte[] exceptionDetail;
/** 创建日期 */
@CreationTimestamp
@ApiModelProperty(value = "创建日期yyyy-MM-dd HH:mm:ss")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
private Timestamp createTime;
public SysLog(String logType, Long time) {

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -15,6 +15,7 @@
*/
package me.zhengjie.service.dto;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.sql.Timestamp;
@ -26,21 +27,30 @@ import java.sql.Timestamp;
@Data
public class SysLogErrorDto implements Serializable {
@ApiModelProperty(value = "ID")
private Long id;
@ApiModelProperty(value = "用户名")
private String username;
@ApiModelProperty(value = "描述")
private String description;
@ApiModelProperty(value = "方法")
private String method;
@ApiModelProperty(value = "参数")
private String params;
@ApiModelProperty(value = "浏览器")
private String browser;
@ApiModelProperty(value = "请求ip")
private String requestIp;
@ApiModelProperty(value = "地址")
private String address;
@ApiModelProperty(value = "创建时间")
private Timestamp createTime;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -15,6 +15,7 @@
*/
package me.zhengjie.service.dto;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import me.zhengjie.annotation.Query;
import java.sql.Timestamp;
@ -28,15 +29,19 @@ import java.util.List;
@Data
public class SysLogQueryCriteria {
@ApiModelProperty(value = "模糊查询")
@Query(blurry = "username,description,address,requestIp,method,params")
private String blurry;
@Query
@ApiModelProperty(value = "用户名")
private String username;
@Query
@ApiModelProperty(value = "日志类型")
private String logType;
@ApiModelProperty(value = "创建时间")
@Query(type = Query.Type.BETWEEN)
private List<Timestamp> createTime;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -15,6 +15,7 @@
*/
package me.zhengjie.service.dto;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.sql.Timestamp;
@ -26,15 +27,21 @@ import java.sql.Timestamp;
@Data
public class SysLogSmallDto implements Serializable {
@ApiModelProperty(value = "描述")
private String description;
@ApiModelProperty(value = "请求IP")
private String requestIp;
@ApiModelProperty(value = "耗时")
private Long time;
@ApiModelProperty(value = "地址")
private String address;
@ApiModelProperty(value = "浏览器")
private String browser;
@ApiModelProperty(value = "创建时间")
private Timestamp createTime;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -39,12 +39,6 @@
<version>2.7</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,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,8 +16,9 @@
package me.zhengjie;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.annotation.rest.AnonymousGetMapping;
import me.zhengjie.utils.SpringContextHolder;
import me.zhengjie.utils.SpringBeanHolder;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.ApplicationPidFileWriter;
@ -35,6 +36,7 @@ import org.springframework.web.bind.annotation.RestController;
* @author Zheng Jie
* @date 2018/11/15 9:20:19
*/
@Slf4j
@EnableAsync
@RestController
@Api(hidden = true)
@ -49,11 +51,15 @@ public class AppRun {
// 或者在 application.yml 添加文件路径,方便 killkill `cat /home/eladmin/app.pid`
springApplication.addListeners(new ApplicationPidFileWriter());
springApplication.run(args);
log.info("---------------------------------------------");
log.info("Local: {}", "http://localhost:8000");
log.info("Swagger: {}", "http://localhost:8000/doc.html");
log.info("---------------------------------------------");
}
@Bean
public SpringContextHolder springContextHolder() {
return new SpringContextHolder();
public SpringBeanHolder springContextHolder() {
return new SpringBeanHolder();
}
/**

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 2019103114: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

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.zhengjie.modules.mnt.domain;
package me.zhengjie.modules.maint.domain;
import io.swagger.annotations.ApiModelProperty;
import cn.hutool.core.bean.BeanUtil;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.zhengjie.modules.mnt.domain;
package me.zhengjie.modules.maint.domain;
import io.swagger.annotations.ApiModelProperty;
import cn.hutool.core.bean.BeanUtil;
@ -36,19 +36,19 @@ public class Database extends BaseEntity implements Serializable {
@Id
@Column(name = "db_id")
@ApiModelProperty(value = "ID", hidden = true)
@ApiModelProperty(value = "ID", hidden = true)
private String id;
@ApiModelProperty(value = "数据库名称")
@ApiModelProperty(value = "数据库名称")
private String name;
@ApiModelProperty(value = "数据库连接地址")
@ApiModelProperty(value = "数据库连接地址")
private String jdbcUrl;
@ApiModelProperty(value = "数据库密码")
@ApiModelProperty(value = "数据库密码")
private String pwd;
@ApiModelProperty(value = "用户名")
@ApiModelProperty(value = "用户名")
private String userName;
public void copy(Database source){

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.zhengjie.modules.mnt.domain;
package me.zhengjie.modules.maint.domain;
import io.swagger.annotations.ApiModelProperty;
import cn.hutool.core.bean.BeanUtil;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.zhengjie.modules.mnt.domain;
package me.zhengjie.modules.maint.domain;
import io.swagger.annotations.ApiModelProperty;
import cn.hutool.core.bean.BeanUtil;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Zheng Jie
* Copyright 2019-2025 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.zhengjie.modules.mnt.domain;
package me.zhengjie.modules.maint.domain;
import io.swagger.annotations.ApiModelProperty;
import cn.hutool.core.bean.BeanUtil;

View File

@ -17,7 +17,7 @@
*
*/
package me.zhengjie.modules.mnt.util;
package me.zhengjie.modules.maint.domain.enums;
import lombok.extern.slf4j.Slf4j;
/**

Some files were not shown because too many files have changed in this diff Show More