feat: 升级springboot3
This commit is contained in:
@@ -19,7 +19,7 @@ package cn.odboy.base;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* 通用参数
|
||||
|
||||
@@ -21,8 +21,8 @@ import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.validation.constraints.Min;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Min;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
|
||||
+1
-2
@@ -17,10 +17,9 @@
|
||||
|
||||
package cn.odboy.framework.context;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
|
||||
+14
-120
@@ -16,139 +16,33 @@
|
||||
|
||||
package cn.odboy.framework.doc;
|
||||
|
||||
import cn.odboy.constant.SystemConst;
|
||||
import cn.odboy.framework.properties.AppProperties;
|
||||
import cn.odboy.util.CsAnonTagUtil;
|
||||
import org.springframework.beans.BeansException;
|
||||
import io.swagger.v3.oas.models.Components;
|
||||
import io.swagger.v3.oas.models.OpenAPI;
|
||||
import io.swagger.v3.oas.models.info.Info;
|
||||
import io.swagger.v3.oas.models.security.SecurityRequirement;
|
||||
import io.swagger.v3.oas.models.security.SecurityScheme;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping;
|
||||
import springfox.documentation.builders.ApiInfoBuilder;
|
||||
import springfox.documentation.builders.PathSelectors;
|
||||
import springfox.documentation.service.*;
|
||||
import springfox.documentation.spi.DocumentationType;
|
||||
import springfox.documentation.spi.service.contexts.SecurityContext;
|
||||
import springfox.documentation.spring.web.plugins.Docket;
|
||||
import springfox.documentation.spring.web.plugins.WebFluxRequestHandlerProvider;
|
||||
import springfox.documentation.spring.web.plugins.WebMvcRequestHandlerProvider;
|
||||
import springfox.documentation.swagger2.annotations.EnableSwagger2;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* api页面 /doc.html
|
||||
*/
|
||||
@Configuration
|
||||
@EnableSwagger2
|
||||
public class SwaggerConfig {
|
||||
@Value("${server.servlet.context-path:}")
|
||||
private String apiPath;
|
||||
@Autowired
|
||||
private AppProperties properties;
|
||||
@Autowired
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
@Bean
|
||||
public Docket createRestApi() {
|
||||
return new Docket(DocumentationType.SWAGGER_2).enable(properties.getSwagger().getEnabled())
|
||||
.pathMapping("/")
|
||||
.apiInfo(apiInfo())
|
||||
.select()
|
||||
.paths(PathSelectors.regex("^(?!/error).*"))
|
||||
.paths(PathSelectors.any())
|
||||
.build()
|
||||
//添加登陆认证
|
||||
.securitySchemes(securitySchemes())
|
||||
.securityContexts(securityContexts());
|
||||
}
|
||||
|
||||
private ApiInfo apiInfo() {
|
||||
return new ApiInfoBuilder().description("一个简单且易上手的自动化运维平台")
|
||||
.title("CuteJava 接口文档")
|
||||
.version("1.4.1")
|
||||
.build();
|
||||
}
|
||||
|
||||
private List<SecurityScheme> securitySchemes() {
|
||||
//设置请求头信息
|
||||
List<SecurityScheme> securitySchemes = new ArrayList<>();
|
||||
ApiKey apiKey = new ApiKey(SystemConst.HEADER_NAME, SystemConst.HEADER_NAME, "header");
|
||||
securitySchemes.add(apiKey);
|
||||
return securitySchemes;
|
||||
}
|
||||
|
||||
private List<SecurityContext> securityContexts() {
|
||||
//设置需要登录认证的路径
|
||||
List<SecurityContext> securityContexts = new ArrayList<>();
|
||||
securityContexts.add(getContextByPath());
|
||||
return securityContexts;
|
||||
}
|
||||
|
||||
private SecurityContext getContextByPath() {
|
||||
Set<String> urls = CsAnonTagUtil.getAllAnonymousUrl(applicationContext);
|
||||
urls = urls.stream().filter(url -> !"/".equals(url)).collect(Collectors.toSet());
|
||||
String regExp = "^(?!" + apiPath + String.join("|" + apiPath, urls) + ").*$";
|
||||
return SecurityContext.builder().securityReferences(defaultAuth()).operationSelector(o -> o.requestMappingPattern()
|
||||
// 排除不需要认证的接口
|
||||
.matches(regExp)).build();
|
||||
}
|
||||
|
||||
private List<SecurityReference> defaultAuth() {
|
||||
List<SecurityReference> securityReferences = new ArrayList<>();
|
||||
AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
|
||||
AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
|
||||
authorizationScopes[0] = authorizationScope;
|
||||
securityReferences.add(new SecurityReference(SystemConst.HEADER_NAME, authorizationScopes));
|
||||
return securityReferences;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解决Springfox与SpringBoot集成后, WebMvcRequestHandlerProvider和WebFluxRequestHandlerProvider冲突问题
|
||||
*
|
||||
* @return /
|
||||
*/
|
||||
@Bean
|
||||
@SuppressWarnings({"unchecked", "all"})
|
||||
public static BeanPostProcessor springfoxHandlerProviderBeanPostProcessor() {
|
||||
return new BeanPostProcessor() {
|
||||
|
||||
@Override
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
|
||||
if (bean instanceof WebMvcRequestHandlerProvider || bean instanceof WebFluxRequestHandlerProvider) {
|
||||
customizeSpringfoxHandlerMappings(getHandlerMappings(bean));
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
|
||||
private <T extends RequestMappingInfoHandlerMapping> void customizeSpringfoxHandlerMappings(List<T> mappings) {
|
||||
List<T> filteredMappings =
|
||||
mappings.stream().filter(mapping -> mapping.getPatternParser() == null).collect(Collectors.toList());
|
||||
mappings.clear();
|
||||
mappings.addAll(filteredMappings);
|
||||
}
|
||||
|
||||
private List<RequestMappingInfoHandlerMapping> getHandlerMappings(Object bean) {
|
||||
Field field = ReflectionUtils.findField(bean.getClass(), "handlerMappings");
|
||||
if (field != null) {
|
||||
field.setAccessible(true);
|
||||
try {
|
||||
return (List<RequestMappingInfoHandlerMapping>) field.get(bean);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new IllegalStateException("Failed to access handlerMappings field", e);
|
||||
}
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
};
|
||||
public OpenAPI customOpenAPI() {
|
||||
// 添加开关控制
|
||||
if (!properties.getSwagger().getEnabled()) {
|
||||
return new OpenAPI();
|
||||
}
|
||||
return new OpenAPI().components(new Components().addSecuritySchemes("Authorization",
|
||||
new SecurityScheme().name("Authorization").type(SecurityScheme.Type.APIKEY).in(SecurityScheme.In.HEADER)))
|
||||
.info(new Info().title("CuteJava 接口文档").version("1.4.1").description("一个简单且易上手的自动化运维平台"))
|
||||
.addSecurityItem(new SecurityRequirement().addList("Authorization"));
|
||||
}
|
||||
}
|
||||
|
||||
+5
-5
@@ -16,8 +16,8 @@
|
||||
|
||||
package cn.odboy.framework.mybatisplus.config;
|
||||
|
||||
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure;
|
||||
import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties;
|
||||
import com.alibaba.druid.spring.boot3.autoconfigure.DruidDataSourceAutoConfigure;
|
||||
import com.alibaba.druid.spring.boot3.autoconfigure.properties.DruidStatProperties;
|
||||
import com.alibaba.druid.util.Utils;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
@@ -26,9 +26,9 @@ 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 jakarta.servlet.*;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
@Configuration
|
||||
|
||||
+2
-3
@@ -27,10 +27,9 @@ import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
+4
-5
@@ -21,10 +21,10 @@ import com.alibaba.fastjson2.JSONFactory;
|
||||
import com.alibaba.fastjson2.JSONWriter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.codec.digest.MurmurHash3;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
|
||||
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
|
||||
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;
|
||||
@@ -49,7 +49,7 @@ import java.util.Map;
|
||||
@Configuration
|
||||
@EnableCaching
|
||||
@AutoConfigureBefore(RedisAutoConfiguration.class)
|
||||
public class RedisConfiguration extends CachingConfigurerSupport {
|
||||
public class RedisConfiguration {
|
||||
/**
|
||||
* 自动识别json对象白名单配置(仅允许解析的包名, 范围越小越安全)<br/> 未配置可能导致, 登录失败, 反复登录等问题
|
||||
*/
|
||||
@@ -69,7 +69,8 @@ public class RedisConfiguration extends CachingConfigurerSupport {
|
||||
public RedisCacheConfiguration redisCacheConfiguration() {
|
||||
FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);
|
||||
RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig();
|
||||
configuration = configuration.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(fastJsonRedisSerializer)).entryTtl(Duration.ofHours(2));
|
||||
configuration = configuration.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(fastJsonRedisSerializer))
|
||||
.entryTtl(Duration.ofHours(2));
|
||||
return configuration;
|
||||
}
|
||||
|
||||
@@ -109,7 +110,6 @@ public class RedisConfiguration extends CachingConfigurerSupport {
|
||||
*/
|
||||
|
||||
@Bean
|
||||
@Override
|
||||
public KeyGenerator keyGenerator() {
|
||||
return (target, method, params) -> {
|
||||
Map<String, Object> container = new HashMap<>(8);
|
||||
@@ -132,7 +132,6 @@ public class RedisConfiguration extends CachingConfigurerSupport {
|
||||
}
|
||||
|
||||
@Bean
|
||||
@SuppressWarnings({"unchecked", "all"})
|
||||
public CacheErrorHandler errorHandler() {
|
||||
return new SimpleCacheErrorHandler() {
|
||||
@Override
|
||||
|
||||
-43
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright 2021-2025 Odboy
|
||||
*
|
||||
* 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 cn.odboy.framework.websocket.config;
|
||||
|
||||
import io.undertow.server.DefaultByteBufferPool;
|
||||
import io.undertow.websockets.jsr.WebSocketDeploymentInfo;
|
||||
import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory;
|
||||
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 解决启动io.undertow.websockets.jsr UT026010: Buffer pool was not set on WebSocketDeploymentInfo, the default pool will be used的警告
|
||||
*
|
||||
* @date 2024-06-07
|
||||
*/
|
||||
@Component
|
||||
public class WsFactory implements WebServerFactoryCustomizer<UndertowServletWebServerFactory> {
|
||||
|
||||
@Override
|
||||
public void customize(UndertowServletWebServerFactory factory) {
|
||||
factory.addDeploymentInfoCustomizers(deploymentInfo -> {
|
||||
WebSocketDeploymentInfo webSocketDeploymentInfo = new WebSocketDeploymentInfo();
|
||||
webSocketDeploymentInfo.setBuffers(new DefaultByteBufferPool(false, 1024));
|
||||
deploymentInfo.addServletContextAttribute(
|
||||
"io.undertow.websockets.jsr.WebSocketDeploymentInfo",
|
||||
webSocketDeploymentInfo);
|
||||
});
|
||||
}
|
||||
}
|
||||
+3
-4
@@ -17,13 +17,12 @@
|
||||
package cn.odboy.framework.websocket.context;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import jakarta.websocket.server.ServerEndpoint;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.websocket.*;
|
||||
import javax.websocket.server.PathParam;
|
||||
import javax.websocket.server.ServerEndpoint;
|
||||
import jakarta.websocket.*;
|
||||
import jakarta.websocket.server.PathParam;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
+11
-14
@@ -23,7 +23,7 @@ import lombok.experimental.UtilityClass;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition;
|
||||
import org.springframework.web.servlet.mvc.condition.PathPatternsRequestCondition;
|
||||
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
|
||||
|
||||
@@ -42,8 +42,7 @@ public class CsAnonTagUtil {
|
||||
* @return /
|
||||
*/
|
||||
public static Map<String, Set<String>> getAnonymousUrl(final ApplicationContext applicationContext) {
|
||||
RequestMappingHandlerMapping requestMappingHandlerMapping =
|
||||
(RequestMappingHandlerMapping) applicationContext.getBean("requestMappingHandlerMapping");
|
||||
RequestMappingHandlerMapping requestMappingHandlerMapping = applicationContext.getBean(RequestMappingHandlerMapping.class);
|
||||
Map<RequestMappingInfo, HandlerMethod> handlerMethodMap = requestMappingHandlerMapping.getHandlerMethods();
|
||||
Map<String, java.util.Set<String>> anonymousUrls = new HashMap<>(8);
|
||||
// 获取匿名标记
|
||||
@@ -58,29 +57,27 @@ public class CsAnonTagUtil {
|
||||
AnonymousAccess anonymousAccess = handlerMethod.getMethodAnnotation(AnonymousAccess.class);
|
||||
if (null != anonymousAccess && infoEntry.getKey() != null) {
|
||||
List<RequestMethod> requestMethods = new ArrayList<>(infoEntry.getKey().getMethodsCondition().getMethods());
|
||||
RequestMethodEnum request = RequestMethodEnum.find(requestMethods.isEmpty() ?
|
||||
RequestMethodEnum.ALL.getType() :
|
||||
requestMethods.get(0).name());
|
||||
PatternsRequestCondition patternsCondition = infoEntry.getKey().getPatternsCondition();
|
||||
if (patternsCondition != null) {
|
||||
RequestMethodEnum request = RequestMethodEnum.find(requestMethods.isEmpty() ? RequestMethodEnum.ALL.getType() : requestMethods.get(0).name());
|
||||
PathPatternsRequestCondition pathPatternsCondition = infoEntry.getKey().getPathPatternsCondition();
|
||||
if (pathPatternsCondition != null) {
|
||||
switch (Objects.requireNonNull(request)) {
|
||||
case GET:
|
||||
get.addAll(patternsCondition.getPatterns());
|
||||
get.addAll(pathPatternsCondition.getPatternValues());
|
||||
break;
|
||||
case POST:
|
||||
post.addAll(patternsCondition.getPatterns());
|
||||
post.addAll(pathPatternsCondition.getPatternValues());
|
||||
break;
|
||||
case PUT:
|
||||
put.addAll(patternsCondition.getPatterns());
|
||||
put.addAll(pathPatternsCondition.getPatternValues());
|
||||
break;
|
||||
case PATCH:
|
||||
patch.addAll(patternsCondition.getPatterns());
|
||||
patch.addAll(pathPatternsCondition.getPatternValues());
|
||||
break;
|
||||
case DELETE:
|
||||
delete.addAll(patternsCondition.getPatterns());
|
||||
delete.addAll(pathPatternsCondition.getPatternValues());
|
||||
break;
|
||||
default:
|
||||
all.addAll(patternsCondition.getPatterns());
|
||||
all.addAll(pathPatternsCondition.getPatternValues());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ import cn.hutool.http.useragent.UserAgentUtil;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
|
||||
@@ -29,9 +29,9 @@ import org.apache.poi.util.IOUtils;
|
||||
import org.apache.poi.xssf.streaming.SXSSFSheet;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.ServletOutputStream;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.*;
|
||||
import java.nio.file.Files;
|
||||
import java.security.MessageDigest;
|
||||
|
||||
+5
-5
@@ -19,11 +19,11 @@ package cn.odboy.util;
|
||||
import cn.odboy.framework.exception.BadRequestException;
|
||||
import lombok.experimental.UtilityClass;
|
||||
|
||||
import javax.validation.ConstraintViolation;
|
||||
import javax.validation.Validation;
|
||||
import javax.validation.Validator;
|
||||
import javax.validation.ValidatorFactory;
|
||||
import javax.validation.groups.Default;
|
||||
import jakarta.validation.ConstraintViolation;
|
||||
import jakarta.validation.Validation;
|
||||
import jakarta.validation.Validator;
|
||||
import jakarta.validation.ValidatorFactory;
|
||||
import jakarta.validation.groups.Default;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user