1. springboot版本升级3.x

2. mybatis plus版本升级3.x
3. dynamic mybatis plus版本升级3.x
4. redis版本升级3.x
5. reids实现配置优化
6. 替换swagger依赖(支持3.x)
7. 新增请求头工具类
8. 参数校验异常捕获优化
9. 拦截器注册为spring容器管理
10. 新增本地日志配置文件
This commit is contained in:
xiongf
2024-10-12 17:32:56 +08:00
parent cf4c78766b
commit 247e6f456a
16 changed files with 361 additions and 174 deletions

44
pom.xml
View File

@@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.6</version>
<version>3.3.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>cn.xf</groupId>
@@ -25,9 +25,9 @@
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.1.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
@@ -40,24 +40,32 @@
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-spring-boot3-starter -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.2</version>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
<version>3.5.8</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.baomidou/dynamic-datasource-spring-boot-starter -->
<!-- https://mvnrepository.com/artifact/com.baomidou/dynamic-datasource-spring-boot3-starter -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>3.6.1</version>
<artifactId>dynamic-datasource-spring-boot3-starter</artifactId>
<version>4.3.1</version>
</dependency>
<!-- <dependency>-->
<!-- <groupId>com.github.xiaoymin</groupId>-->
<!-- <artifactId>knife4j-spring-boot-starter</artifactId>-->
<!-- &lt;!&ndash;在引用时请在maven中央仓库搜索3.X最新版本号&ndash;&gt;-->
<!-- <version>3.0.2</version>-->
<!-- </dependency>-->
<!-- https://mvnrepository.com/artifact/org.springdoc/springdoc-openapi-starter-webmvc-ui -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<!--在引用时请在maven中央仓库搜索3.X最新版本号-->
<version>3.0.2</version>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.6.0</version>
</dependency>
<dependency>
@@ -75,7 +83,7 @@
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>2.7.0</version>
<version>3.3.3</version>
</dependency>
<!--redis连接池需要依赖-->
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-pool2 -->
@@ -130,6 +138,14 @@
<version>3.0.1</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version> <!-- 根据需要选择合适的版本 -->
<scope>provided</scope> <!-- 在Web服务器环境中由服务器提供 -->
</dependency>
</dependencies>
<build>

View File

@@ -1,14 +1,21 @@
package cn.xf.basedemo.common.exception;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.HttpStatusCode;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;
/**
* @Author: xiongfeng
@@ -58,4 +65,22 @@ public class GlobalExceptionHandler extends ResponseEntityExceptionHandler{
return new GenericResponse(exception.getCode(),null,exception.getMessage());
}
/**
* 重写handleMethodArgumentNotValid 方法自定义处理参数校验错误信息
*
* @param ex
* @param headers
* @param status
* @param request
* @return
*/
@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) {
Map<String, String> errors = new HashMap<>();
ex.getBindingResult().getFieldErrors().forEach(error -> {
errors.put(error.getField(), error.getDefaultMessage());
});
return new ResponseEntity<>(errors, HttpStatus.BAD_REQUEST);
}
}

View File

@@ -2,6 +2,7 @@ package cn.xf.basedemo.common.utils;
import org.apache.tomcat.util.codec.binary.Base64;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.security.*;
@@ -34,14 +35,15 @@ public class RSAUtils {
/**
* 创建rsa密匙对
*
* @return
*/
private static Map<String, String> createEncryptKey(){
private static Map<String, String> createEncryptKey() {
KeyPairGenerator kpg;
try {
kpg = KeyPairGenerator.getInstance(RSA);
}catch (Exception e){
} catch (Exception e) {
throw new IllegalArgumentException();
}
kpg.initialize(ENCRYPT_SIZE);
@@ -52,7 +54,7 @@ public class RSAUtils {
PrivateKey aPrivate = keyPair.getPrivate();
String privateKey = Base64.encodeBase64URLSafeString(aPrivate.getEncoded());
Map<String, String> map =new HashMap<>();
Map<String, String> map = new HashMap<>();
map.put("publicKey", publicKey);
map.put("privateKey", privateKey);
@@ -62,6 +64,7 @@ public class RSAUtils {
/**
* 获取ras公匙
*
* @param publicKeyStr 公匙加密字符串
* @return
* @throws NoSuchAlgorithmException
@@ -77,6 +80,7 @@ public class RSAUtils {
/**
* 获取ras私匙
*
* @param privateKeyStr 私匙加密字符串
* @return
* @throws NoSuchAlgorithmException
@@ -91,12 +95,13 @@ public class RSAUtils {
}
/**
* 公匙加密
* @param data 字符串
* 公匙加密
*
* @param data 字符串
* @param publicKey
* @return
*/
public static String publicEncrypt(String data, RSAPublicKey publicKey){
public static String publicEncrypt(String data, RSAPublicKey publicKey) {
try {
@@ -106,19 +111,19 @@ public class RSAUtils {
byte[] bytes = cipher.doFinal(data.getBytes());
return Base64.encodeBase64URLSafeString(bytes);
// return Base64.encodeBase64URLSafeString(rsaSplitCodec(cipher, Cipher.ENCRYPT_MODE, data.getBytes(CHARSET), publicKey.getModulus().bitLength()));
}catch (Exception e){
} catch (Exception e) {
throw new RuntimeException();
}
}
public static String privateDecryption(String data, RSAPrivateKey privateKey){
public static String privateDecryption(String data, RSAPrivateKey privateKey) {
try {
Cipher cipher = Cipher.getInstance(RSA);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
// byte[] bytes = cipher.doFinal(Base64.decodeBase64(data.getBytes(CHARSET)));
// return new String(bytes);
return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, Base64.decodeBase64(data.getBytes(CHARSET)), privateKey.getModulus().bitLength()), CHARSET);
return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, Base64.decodeBase64(data.getBytes(CHARSET), 0, data.getBytes(CHARSET).length), privateKey.getModulus().bitLength()), CHARSET);
} catch (Exception e) {
throw new RuntimeException("解密字符串[" + data + "]时遇到异常", e);
}
@@ -178,7 +183,7 @@ public class RSAUtils {
// String s1 = privateDecryption(ss, getPrivateKey(privateKey1));
// System.out.println("解密后明文:" + s1);
}catch (Exception e){
} catch (Exception e) {
throw new IllegalArgumentException();
}
@@ -186,5 +191,4 @@ public class RSAUtils {
}
}

View File

@@ -0,0 +1,67 @@
package cn.xf.basedemo.common.utils;
import cn.xf.basedemo.common.exception.LoginException;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.util.StringUtils;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
/**
* packageName com.wenliao.customer.common.utils
*
* @author remaindertime
* @className RequestHeaderUtil
* @date 2024/10/10
* @description
*/
public class RequestHeaderUtil {
/**
* 获取所有请求头
* @param request HttpServletRequest 对象
* @return 请求头的键值对 Map
*/
public static Map<String, String> getHeaders(HttpServletRequest request) {
Map<String, String> headersMap = new HashMap<>();
Enumeration<String> headerNames = request.getHeaderNames();
if (headerNames != null) {
while (headerNames.hasMoreElements()) {
String headerName = headerNames.nextElement();
String headerValue = request.getHeader(headerName);
headersMap.put(headerName, headerValue);
}
}
return headersMap;
}
/**
* 获取特定的请求头
* @param request HttpServletRequest 对象
* @param headerName 请求头名称
* @return 请求头值,如果没有则返回 null
*/
public static String getHeader(HttpServletRequest request, String headerName) {
return request.getHeader(headerName);
}
/**
* 获取token
*/
public static String getToken(HttpServletRequest request) {
//登录处理
String token = request.getHeader("Authorization");
if (StringUtils.isEmpty(token))
token = request.getParameter("token");
if (StringUtils.isEmpty(token)) {
throw new LoginException("请先登录");
}
// 如果 Authorization 头部中存在且以 "Bearer " 开头,则提取 token
if (token.startsWith("Bearer ")) {
token = token.substring(7); // 去除 "Bearer " 部分,获取真正的 token
}
return token;
}
}

View File

@@ -0,0 +1,43 @@
package cn.xf.basedemo.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import jakarta.annotation.Resource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
public class RedisConfig {
@Resource
private RedisConnectionFactory factory;
@Bean
public Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer(){
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
return jackson2JsonRedisSerializer;
}
@Bean
public RedisTemplate<String, Object> redisTemplate() {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer());
redisTemplate.setConnectionFactory(factory);
return redisTemplate;
}
}

View File

@@ -1,70 +0,0 @@
package cn.xf.basedemo.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.service.Parameter;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.util.ArrayList;
import java.util.List;
/**
* @program: spring-boot-base-demo
* @ClassName SpringFoxSwaggerConfig
* @description:
* @author: xiongfeng
* @create: 2022-06-16 16:44
**/
@Configuration
@EnableSwagger2
public class SpringFoxSwaggerConfig {
@Bean
public Docket docket(Environment environment) {
// 添加接口请求头参数配置 没有的话 可以忽略
ParameterBuilder tokenPar = new ParameterBuilder();
List<Parameter> pars = new ArrayList<>();
tokenPar.name("token")
.description("令牌")
.defaultValue("")
.modelRef(new ModelRef("string"))
.parameterType("header").required(false).build();
pars.add(tokenPar.build());
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
//是否启动swagger 默认启动
.enable(true)
//所在分组
.groupName("base")
.select()
//指定扫描的包路径
.apis(RequestHandlerSelectors.basePackage("cn.xf.basedemo.controller.business"))
.paths(PathSelectors.any())
.build()
.globalOperationParameters(pars);
}
private ApiInfo apiInfo() {
Contact author = new Contact("reamindertime", "https://blog.csdn.net/qq_39818325?type=blog", "2439534736@qq.com");
return new ApiInfo(
"开箱即用springboot基础项目文档",
"开箱即用springboot基础项目文档",
"1.0",
"",
author,
"",
"",
new ArrayList()
);
}
}

View File

@@ -5,8 +5,7 @@ import cn.xf.basedemo.common.model.RetObj;
import cn.xf.basedemo.interceptor.SessionContext;
import cn.xf.basedemo.model.res.LoginInfoRes;
import cn.xf.basedemo.service.UserService;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.*;
import io.swagger.v3.oas.annotations.Operation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@@ -20,7 +19,6 @@ import org.springframework.web.bind.annotation.RestController;
* @author: xiongfeng
* @create: 2022-06-28 09:17
**/
@Api(tags = "用户控制器")
@RestController(value = "用户控制器")
@RequestMapping("/user")
public class UserController {
@@ -28,16 +26,14 @@ public class UserController {
@Autowired
private UserService userService;
@ApiOperation(value = "用户登录", notes = "用户登录")
@ApiOperationSupport(order = 1)
@Operation(summary = "用户登录", description = "用户登录")
@PostMapping("/login")
public RetObj login(@RequestBody LoginInfoRes res){
return userService.login(res);
}
@ApiOperation(value = "用户信息", notes = "用户信息")
@ApiOperationSupport(order = 2)
@Operation(summary = "用户信息", description = "用户信息")
@PostMapping("/info")
public RetObj info(){
LoginUser loginUser = SessionContext.getInstance().get();

View File

@@ -1,5 +1,6 @@
package cn.xf.basedemo.interceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
@@ -15,16 +16,22 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Bean
public TokenInterceptor tokenInterceptor() {
return new TokenInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new TokenInterceptor()) //登录逻辑拦截类
registry.addInterceptor(tokenInterceptor()) //登录逻辑拦截类
.addPathPatterns("/**") //需要拦截的请求(设置的全部拦截)
.excludePathPatterns("/user/login","/web/**"); //忽略的请求
.excludePathPatterns("/user/login", "/web/**"); //忽略的请求
}
/**
* 放行Knife4j请求
*
* @param registry
*/
@Override

View File

@@ -5,13 +5,14 @@ import cn.xf.basedemo.common.exception.ResponseCode;
import cn.xf.basedemo.common.model.LoginUser;
import cn.xf.basedemo.common.utils.ApplicationContextUtils;
import com.alibaba.fastjson.JSONObject;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
@@ -23,37 +24,38 @@ import java.util.concurrent.TimeUnit;
* @author: xiongfeng
* @create: 2022-06-16 14:17
**/
@Component
public class TokenInterceptor implements HandlerInterceptor {
@Autowired
RedisTemplate<Object,Object> redisTemplate =
(RedisTemplate<Object,Object>) ApplicationContextUtils.getBean("redisTemplate");
private RedisTemplate redisTemplate;
//不拦截的请求列表
private static final List<String> EXCLUDE_PATH_LIST = Arrays.asList("/user/login","/web/login");
private static final List<String> EXCLUDE_PATH_LIST = Arrays.asList("/user/login", "/web/login");
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String requestURI = request.getRequestURI();
if(EXCLUDE_PATH_LIST.contains(requestURI)){
if (EXCLUDE_PATH_LIST.contains(requestURI)) {
return true;
}
//登录处理
String token = request.getHeader("Authorization");
if(StringUtils.isEmpty(token))
if (StringUtils.isEmpty(token))
token = request.getParameter("token");
if(StringUtils.isEmpty(token)){
if (StringUtils.isEmpty(token)) {
throw new LoginException("请先登录");
}
String value = (String) redisTemplate.opsForValue().get("token:" + token);
if(StringUtils.isEmpty(value)){
if (StringUtils.isEmpty(value)) {
throw new LoginException();
}
JSONObject jsonObject = JSONObject.parseObject(value);
//JSON对象转换成Java对象
LoginUser loginUserInfo = JSONObject.toJavaObject(jsonObject, LoginUser.class);
if(loginUserInfo == null || loginUserInfo.getId() <= 0){
if (loginUserInfo == null || loginUserInfo.getId() <= 0) {
throw new LoginException(ResponseCode.USER_INPUT_ERROR);
}
redisTemplate.expire(token, 86700, TimeUnit.SECONDS);

View File

@@ -1,7 +1,6 @@
package cn.xf.basedemo.model.res;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
@@ -12,12 +11,11 @@ import lombok.Data;
* @create: 2022-07-04 11:46
**/
@Data
@ApiModel(value = "登录请求对象")
public class LoginInfoRes {
/**
* 登录密文
*/
@ApiModelProperty(value = "encryptedData", name = "登录密文")
@Schema(name = "登录密文")
private String encryptedData;
}

View File

@@ -10,37 +10,38 @@
# connection-test-query: SELECT 1
# datasource:
# master: #${SERVER_ADDRESS}
# url: jdbc:mysql://172.16.0.3:3307/xf-boot-base?useUnicode=true&characterEncoding=utf-8&allowPublicKeyRetrieval=true&useSSL=false&serverTimezone=Asia/Shanghai
# url: jdbc:mysql://9.9.9.9:3307/xf-boot-base?useUnicode=true&characterEncoding=utf-8&allowPublicKeyRetrieval=true&useSSL=false&serverTimezone=Asia/Shanghai
# username:
# password:
# driver-class-name: com.mysql.cj.jdbc.Driver
# slave:
# url: jdbc:mysql://172.16.0.3:3307/xf-boot-base?useUnicode=true&characterEncoding=utf-8&allowPublicKeyRetrieval=true&useSSL=false&serverTimezone=Asia/Shanghai
# url: jdbc:mysql://9.9.9.9:3307/xf-boot-base?useUnicode=true&characterEncoding=utf-8&allowPublicKeyRetrieval=true&useSSL=false&serverTimezone=Asia/Shanghai
# username:
# password:
# driver-class-name: com.mysql.cj.jdbc.Driver
# redis:
# port: 6379 #Redis服务器连接的端口
# host: 172.16.0.3 # Redis服务器的地址
# password: # Redis服务器连接密码(默认为空)
# timeout: 5000 # 连接超时时间(毫秒
# lettuce: #参考博客 https://blog.csdn.net/weixin_43944305/article/details/124322595
# pool:
# maxActive: 5000 #最大连接数
# maxIdle: 30 #连接池最大空闲连接数.
# minIdle: 5 #连接池最空闲连接数.
# max-wait: 2000 #连接池中获取连接时的最大等待时间
# time-between-eviction-runs: 60s #空闲对象逐出器线程的运行间隔时间.空闲连接线程释放周期时间.
# cluster:
# refresh:
# adaptive: true #拓扑动态感应即客户端能够根据 redis cluster 集群的变化,动态改变客户端的节点情况,完成故障转移。
# period: 60s #刷新redis集群状态周期时间
# data:
# redis:
# port: 6379 #Redis服务器连接的端口
# host: 9.9.9.9 # Redis服务器的地址
# password: # Redis服务器连接密码默认为空
# timeout: 5000 # 连接超时时间(毫秒)
# lettuce: #参考博客 https://blog.csdn.net/weixin_43944305/article/details/124322595
# pool:
# maxActive: 5000 #最大连接数
# maxIdle: 30 #连接池最空闲连接数.
# minIdle: 5 #连接池最小空闲连接数.
# max-wait: 2000 #从连接池中获取连接时的最大等待时间
# time-between-eviction-runs: 60s #空闲对象逐出器线程的运行间隔时间.空闲连接线程释放周期时间.
# cluster:
# refresh:
# adaptive: true #拓扑动态感应即客户端能够根据 redis cluster 集群的变化,动态改变客户端的节点情况,完成故障转移。
# period: 60s #刷新redis集群状态周期时间
#
#global:
# rsaPublicKey: MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC_F5UQC1QWsu3QsESQBz9M-GDA9Atm0qVSvwIsy568lyRLi-nq3VvvnmgrlL4yTbngFzyfb2Dn35cNCHsBvIaGuCY3_PpzPqMzVpxr2QlEkhEX9atnJQ1rWexS8QeZtPjpiIwoQrChTzXjD_sYUkDrqSykFplyivf0NSO2WqCBdwIDAQAB
# rsaPrivateKey: MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAL8XlRALVBay7dCwRJAHP0z4YMD0C2bSpVK_AizLnryXJEuL6erdW--eaCuUvjJNueAXPJ9vYOfflw0IewG8hoa4Jjf8-nM-ozNWnGvZCUSSERf1q2clDWtZ7FLxB5m0-OmIjChCsKFPNeMP-xhSQOupLKQWmXKK9_Q1I7ZaoIF3AgMBAAECgYBxTUA61Ry0oL7U_86HP2TO9G4ZuhmQi9EucMaPXOPvmgYRLRIzCbDbMKc_P-BN3zwYnG57cgSZNz9OoPqeGvP_oVTnkoEpVkCSV-JP2p_DK09LdbDqszJXMrxAkPmWGUw8IRMcTJT1xJJcgzFE6T0CmTo-Vk47AnmqfJD4U6o74QJBAPRjVUJKZnrMSnSqKPDL2ThgTo8h7-KFxl_Z-g724lTOFiCmBpi6nCWAcuacFRrrYqxF-r9c4zdIyR7AvLROql8CQQDIK_kRF52dVtwShciZhyeUBLoi0nWV9F8mMGt60NTEER9zPEgPsv2aVn8h97KMWOwmd2Da4EPm25QxOuaKQC_pAkBczcfXp5co9KElkmR_pHl1jiTm97U3qSM-zPDHc_tYxvXiKgoBP4QCPbfkWMsu8MoEr4Jb3vMt0EcHlZtTQTgzAkAfmNla-lhV4sUgY1_T5EK6GbjsED6hag6u74u3ukkrnexR-10ApWdkumydBwV3I_464DM4uZfeVCDjWIHVpuYpAkEA6QLPztGD4V8Q1PqTEeSF3i68CKPM8vO1_mCH2JD7qsqDQcIKkczj5rTg7hlOKwB9V6gSw4CbnOF6moTooRD-cQ
##redis
#redis
#redis:
# datasource:
# token:
@@ -65,16 +66,16 @@
# args:
# expireTime: 3600 #过期时间
# contentLengthRange: 2000 #大小限制
##oss:
## name: alioss
## endpoint: ll-oss-pre.lianlianlvyou.com
## accessKey:
## secretKey:
## bucketName:
## args:
## expireTime: 3600 #过期时间
## contentLengthRange: 2000 #大小限制
## redis分布式锁
#oss:
# name: alioss
# endpoint: ll-oss-pre.lianlianlvyou.com
# accessKey:
# secretKey:
# bucketName:
# args:
# expireTime: 3600 #过期时间
# contentLengthRange: 2000 #大小限制
# redis分布式锁
#redisson:
# enabled: true
# address: 'redis://192.168.10.113:6379'
@@ -120,8 +121,8 @@
# subscribeList:
# - queue: 'app-business'
# messageListener: commonChangeMessageListener
#
##应用可以默认使用的配置文件
#应用可以默认使用的配置文件
#global:
# testCofnig: "aaa"
# tokenSecret: '12435twefdsfsdt4tsdcqw43tregdsgd'

View File

@@ -19,22 +19,23 @@ spring:
username: ${MYSQL_NAME}
password: ${MYSQL_PWD}
driver-class-name: com.mysql.cj.jdbc.Driver
redis:
port: 6379 #Redis服务器连接的端口
host: ${SERVER_ADDRESS} # Redis服务器的地址
password: ${REDIS_PWD} # Redis服务器连接密码(默认为空)
timeout: 5000 # 连接超时时间(毫秒
lettuce: #参考博客 https://blog.csdn.net/weixin_43944305/article/details/124322595
pool:
maxActive: 5000 #最大连接数
maxIdle: 30 #连接池最大空闲连接数.
minIdle: 5 #连接池最空闲连接数.
max-wait: 2000 #连接池中获取连接时的最大等待时间
time-between-eviction-runs: 60s #空闲对象逐出器线程的运行间隔时间.空闲连接线程释放周期时间.
cluster:
refresh:
adaptive: true #拓扑动态感应即客户端能够根据 redis cluster 集群的变化,动态改变客户端的节点情况,完成故障转移。
period: 60s #刷新redis集群状态周期时间
data:
redis:
port: 6379 #Redis服务器连接的端口
host: ${SERVER_ADDRESS} # Redis服务器的地址
password: ${REDIS_PWD} # Redis服务器连接密码默认为空
timeout: 5000 # 连接超时时间(毫秒)
lettuce: #参考博客 https://blog.csdn.net/weixin_43944305/article/details/124322595
pool:
maxActive: 5000 #最大连接数
maxIdle: 30 #连接池最空闲连接数.
minIdle: 5 #连接池最小空闲连接数.
max-wait: 2000 #从连接池中获取连接时的最大等待时间
time-between-eviction-runs: 60s #空闲对象逐出器线程的运行间隔时间.空闲连接线程释放周期时间.
cluster:
refresh:
adaptive: true #拓扑动态感应即客户端能够根据 redis cluster 集群的变化,动态改变客户端的节点情况,完成故障转移。
period: 60s #刷新redis集群状态周期时间
global:
rsaPublicKey: MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC_F5UQC1QWsu3QsESQBz9M-GDA9Atm0qVSvwIsy568lyRLi-nq3VvvnmgrlL4yTbngFzyfb2Dn35cNCHsBvIaGuCY3_PpzPqMzVpxr2QlEkhEX9atnJQ1rWexS8QeZtPjpiIwoQrChTzXjD_sYUkDrqSykFplyivf0NSO2WqCBdwIDAQAB

View File

@@ -18,7 +18,16 @@ spring:
WRITE_DATES_AS_TIMESTAMPS: false
FAIL_ON_EMPTY_BEANS: false
springdoc:
api-docs:
path: /v3/api-docs # 自定义 API 文档路径
swagger-ui:
path: /swagger-ui.html # 自定义 Swagger UI 路径
enabled: true
info:
title: 文撩 API 文档
description: 这是文撩平台的 API 文档
version: v1.0
mybatis-plus:
configuration:

View File

@@ -5,14 +5,14 @@ spring:
cloud:
nacos:
config:
server-addr: 172.16.0.3:8848
server-addr: 9.9.9.9:8848
file-extension: yml
namespace: 7e913a24-bf7a-4628-9dcf-96ac79800c9f
namespace: 34f368d5-a6c6-4f57-a80a-5402de295695
group: DEFAULT_GROUP
username: nacos
password: nacos
username:
password:
discovery:
server-addr: 172.16.0.3:8848
namespace: 7e913a24-bf7a-4628-9dcf-96ac79800c9f
username: nacos
password: nacos
server-addr: 9.9.9.9:9
namespace: 34f368d5-a6c6-4f57-a80a-5402de295695
username:
password:

View File

@@ -0,0 +1,88 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="false">
<contextName>logback</contextName>
<property name="log_home" value="logs"/>
<property name="log_pattern" value="[%date{yyyy-MM-dd HH:mm:ss.SSS}] %-5level %logger{96} - %msg%n"/>
<!--输出到控制台-->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>info</level>
</filter>
<encoder>
<Pattern>${log_pattern}</Pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<!--输出到本地-->
<appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<FileNamePattern>./${log_home}/base-%d{yyyy-MM-dd}-info.%i.log</FileNamePattern>
<!-- 日志文件最大尺寸 -->
<maxFileSize>200MB</maxFileSize>
<!--日志文件保留天数-->
<MaxHistory>3</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期%thread表示线程名%-5level级别从左显示5个字符宽度%msg日志消息%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>info</level>
</filter>
</appender>
<!--输出到本地-->
<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<FileNamePattern>./${log_home}/base-%d{yyyy-MM-dd}-error.%i.log</FileNamePattern>
<!-- 日志文件最大尺寸 -->
<maxFileSize>200MB</maxFileSize>
<!--日志文件保留天数-->
<MaxHistory>3</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期%thread表示线程名%-5level级别从左显示5个字符宽度%msg日志消息%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>error</level>
</filter>
</appender>
<springProperty scope="logstash" name="logIps" source="logstash.ips"/>
<springProperty scope="logstash" name="appName" source="logstash.appName"/>
<appender name="logstash" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
<!-- logstash tcp 服务器地址,可以配置多个地址 -->
<destination>${logIps}</destination>
<!-- 保持连接 -->
<keepAliveDuration>5 minutes</keepAliveDuration>
<!-- 连接超时等待时间 -->
<connectionTimeout>5 seconds</connectionTimeout>
<!-- 重连延迟,默认 30s -->
<reconnectionDelay>30 second</reconnectionDelay>
<!-- 等待策略需要测试和监控CPU找到最佳配置 -->
<!-- 文档: https://github.com/logfellow/logstash-logback-encoder#wait-strategy -->
<waitStrategyType>sleeping</waitStrategyType>
<encoder class="net.logstash.logback.encoder.LogstashEncoder">
<customFields>{"host":"${HOSTNAME}", "app_name":"${appName}","plantVersion":"1"}</customFields>
</encoder>
</appender>
<springProfile name="dev">
<root level="info">
<appender-ref ref="INFO_FILE"/>
<appender-ref ref="ERROR_FILE"/>
<!-- <appender-ref ref="logstash"/>-->
</root>
</springProfile>
<springProfile name="pre">
<root level="info">
<appender-ref ref="INFO_FILE"/>
<appender-ref ref="ERROR_FILE"/>
<!-- <appender-ref ref="logstash"/>-->
</root>
</springProfile>
</configuration>