mirror of
https://github.com/RemainderTime/spring-boot-base-demo.git
synced 2026-02-06 15:10:56 +08:00
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:
44
pom.xml
44
pom.xml
@@ -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>-->
|
||||
<!-- <!–在引用时请在maven中央仓库搜索3.X最新版本号–>-->
|
||||
<!-- <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>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
43
src/main/java/cn/xf/basedemo/config/RedisConfig.java
Normal file
43
src/main/java/cn/xf/basedemo/config/RedisConfig.java
Normal 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;
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
88
src/main/resources/logback-spring-local.xml
Normal file
88
src/main/resources/logback-spring-local.xml
Normal 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>
|
||||
Reference in New Issue
Block a user