初始化项目

This commit is contained in:
2026-08-06 15:19:45 +08:00
commit 63c8d8b757
229 changed files with 12653 additions and 0 deletions
@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.xujun</groupId>
<artifactId>xtools-boot-web</artifactId>
<version>5.1.0</version>
</parent>
<artifactId>xtools-boot-web-base</artifactId>
<!-- 依赖 -->
<dependencies>
<!-- xtools begin -->
<!-- xtools-web 模块 -->
<dependency>
<groupId>org.xujun</groupId>
<artifactId>xtools-web</artifactId>
</dependency>
<!-- xtools end -->
<!-- xtools-boot begin -->
<!-- xtools-boot-core -->
<dependency>
<groupId>org.xujun</groupId>
<artifactId>xtools-boot-core</artifactId>
</dependency>
<!-- xtools-boot-log -->
<dependency>
<groupId>org.xujun</groupId>
<artifactId>xtools-boot-log</artifactId>
</dependency>
<!-- xtools-boot-web-filter -->
<dependency>
<groupId>org.xujun</groupId>
<artifactId>xtools-boot-web-filter</artifactId>
</dependency>
<!-- xtools-boot end -->
<!-- SpringBoot begin -->
<!-- SpringBoot-Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- SpringBoot-Validation -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!-- SpringBoot end -->
<!-- fastjson2 -->
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,28 @@
package xtools.boot.web.base;
import org.springframework.context.annotation.Import;
import xtools.boot.core.utils.ModuleLoadUtils;
import xtools.boot.web.base.selector.BootWebBaseImportSelector;
/**
* <p>Title : BootWebBaseConfiguration</p>
* <p>Description : BootWebBaseConfiguration</p>
* <p>DevelopTools : Idea_x64_v2026.1</p>
* <p>DevelopSystem : macOS Sequoia 15.7.5</p>
* <p>Company : org.xujun</p>
*
* @author : XuJun
* @version : 5.0.0
* @date : 2026/01/01 09:30
*/
@Import(BootWebBaseImportSelector.class)
public class BootWebBaseConfiguration {
/**
* 构造方法
*/
public BootWebBaseConfiguration() {
ModuleLoadUtils.loadSuccess(BootWebBaseConfiguration.class);
}
}
@@ -0,0 +1,135 @@
package xtools.boot.web.base.config;
import com.fasterxml.jackson.annotation.JsonInclude;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import tools.jackson.core.JacksonException;
import tools.jackson.core.JsonGenerator;
import tools.jackson.core.JsonParser;
import tools.jackson.databind.BeanProperty;
import tools.jackson.databind.DeserializationContext;
import tools.jackson.databind.SerializationContext;
import tools.jackson.databind.ValueDeserializer;
import tools.jackson.databind.ValueSerializer;
import tools.jackson.databind.json.JsonMapper;
import tools.jackson.databind.module.SimpleModule;
import xtools.boot.api.anntation.IgnoreXss;
import xtools.boot.core.utils.TimeUtils;
import xtools.core.time.InstantUtils;
import xtools.web.xss.XssUtils;
import java.time.Instant;
import java.util.Objects;
/**
* <p>Title : JacksonConfig</p>
* <p>Description : JacksonConfig</p>
* <p>DevelopTools : Idea_x64_v2026.1</p>
* <p>DevelopSystem : macOS Sequoia 15.7.5</p>
* <p>Company : org.xujun</p>
*
* @author : XuJun
* @version : 5.0.0
* @date : 2026/1/6 12:15
*/
@Configuration
public class JacksonConfig {
/**
* 忽略 null 值
*/
public static final JsonMapper NON_NULL;
// 初始化
static {
NON_NULL = JsonMapper.builder().changeDefaultPropertyInclusion(handler -> handler.withValueInclusion(JsonInclude.Include.NON_NULL)).build();
}
/**
* 创建 SimpleModule
*
* @return SimpleModule
*/
@Bean
public SimpleModule simpleModule() {
SimpleModule module = new SimpleModule();
// 序列化
module.addSerializer(Long.class, new ValueSerializer<>() {
@Override
public void serialize(Long value, JsonGenerator gen, SerializationContext context) throws JacksonException {
if (value == null) {
gen.writeNull();
} else {
gen.writeString(value.toString());
}
}
});
module.addSerializer(Instant.class, new ValueSerializer<>() {
@Override
public void serialize(Instant value, JsonGenerator gen, SerializationContext context) throws JacksonException {
if (value == null) {
gen.writeNull();
} else {
gen.writeString(InstantUtils.format(value));
}
}
});
// 反序列化
module.addDeserializer(Instant.class, new ValueDeserializer<>() {
@Override
public Instant deserialize(JsonParser p, DeserializationContext context) throws JacksonException {
return TimeUtils.toInstant(p.getString());
}
});
// xss处理
module.addDeserializer(String.class, new XssStringDeserializer());
return module;
}
/**
* XSS 字符串反序列化器
*/
static class XssStringDeserializer extends ValueDeserializer<String> {
/**
* 是否忽略 XSS 过滤
*/
private final boolean ignore;
/**
* 创建 XSS 忽略字符串反序列化器
*/
XssStringDeserializer() {
this(false);
}
/**
* 创建 XSS 忽略字符串反序列化器
*
* @param ignore 是否忽略 XSS 过滤
*/
XssStringDeserializer(boolean ignore) {
this.ignore = ignore;
}
@Override
public String deserialize(JsonParser parser, DeserializationContext context) throws JacksonException {
String value = parser.getString();
if (ignore) {
return value;
}
return XssUtils.filterParam(value);
}
@Override
public ValueDeserializer<String> createContextual(DeserializationContext context, BeanProperty property) throws JacksonException {
if (Objects.nonNull(property) && Objects.nonNull(property.getAnnotation(IgnoreXss.class))) {
return new XssStringDeserializer(true);
}
return new XssStringDeserializer(false);
}
}
}
@@ -0,0 +1,30 @@
package xtools.boot.web.base.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
/**
* <p>Title : LogTrackConfig</p>
* <p>Description : LogTrackConfig</p>
* <p>DevelopTools : Idea_x64_v2026.1</p>
* <p>DevelopSystem : macOS Sequoia 15.7.5</p>
* <p>Company : org.xujun</p>
*
* @author : XuJun
* @version : 5.0.0
* @date : 2026/2/3 15:07
*/
@Data
@Component
@ConfigurationProperties(prefix = "sys.log.track")
public class LogTrackConfig {
/**
* 日志追踪忽略路径
*/
private List<String> ignorePath = new ArrayList<>();
}
@@ -0,0 +1,42 @@
package xtools.boot.web.base.config;
import org.jspecify.annotations.NonNull;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.format.FormatterRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import xtools.boot.core.utils.TimeUtils;
import java.time.Instant;
/**
* <p>Title : MvcConverterConfig</p>
* <p>Description : MvcConverterConfig</p>
* <p>DevelopTools : Idea_x64_v2026.1</p>
* <p>DevelopSystem : macOS Sequoia 15.7.5</p>
* <p>Company : org.xujun</p>
*
* @author : XuJun
* @version : 5.0.0
* @date : 2026/1/6 14:44
*/
@Configuration
public class MvcConverterConfig implements WebMvcConfigurer {
/**
* 添加转换器
*
* @param registry registry
*/
@Override
public void addFormatters(FormatterRegistry registry) {
// 添加时间转换器
registry.addConverter(new Converter<String, Instant>() {
@Override
public Instant convert(@NonNull String source) {
return TimeUtils.toInstant(source);
}
});
}
}
@@ -0,0 +1,332 @@
package xtools.boot.web.base.exception;
import com.alibaba.fastjson2.JSONObject;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.connector.ClientAbortException;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.HandlerMethodValidationException;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.servlet.resource.NoResourceFoundException;
import xtools.boot.api.enums.ResultType;
import xtools.boot.api.exection.BizError;
import xtools.boot.api.exection.BizPublicKeyError;
import xtools.boot.api.exection.BizWarning;
import xtools.boot.api.exection.UnauthorizedError;
import xtools.boot.api.model.dto.Result;
import xtools.boot.api.model.dto.log.LogTrack;
import xtools.boot.log.LogBus;
import xtools.boot.log.enums.LogBusBaseType;
import xtools.boot.log.holder.LogTrackHolder;
import xtools.boot.log.interfaces.LogBusType;
import xtools.core.StringUtils;
import xtools.core.enums.LogLevel;
import xtools.core.extend.TemplateUtils;
import java.util.List;
import java.util.Objects;
import java.util.StringJoiner;
import static xtools.base.config.Constants.CP_COLON;
import static xtools.base.config.Constants.CP_COMMA;
/**
* <p>Title : GlobalExceptionHandler</p>
* <p>Description : GlobalExceptionHandler</p>
* <p>DevelopTools : Idea_x64_v2026.1</p>
* <p>DevelopSystem : macOS Sequoia 15.7.5</p>
* <p>Company : org.xujun</p>
*
* @author : XuJun
* @version : 5.0.0
* @date : 2026/1/5 15:21
*/
@Slf4j
@RestControllerAdvice
public class GlobalControllerExceptionHandler {
/**
* 参数类型不匹配异常模板
*/
private static final String ARGUMENT_TYPE_MISMATCH_TEMPLATE = "参数[{}]类型不匹配";
/**
* 参数类型不匹配
*
* @param e 参数类型不匹配异常
* @param request 请求
* @return 错误结果
*/
@ExceptionHandler(MethodArgumentTypeMismatchException.class)
public Result<Object> handleMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e, HttpServletRequest request) {
String errMsg = TemplateUtils.format(ARGUMENT_TYPE_MISMATCH_TEMPLATE, e.getPropertyName());
debugLog("参数类型不匹配", errMsg, request, e);
return Result.badRequest(errMsg);
}
/**
* 参数校验异常
*
* @param e 参数校验异常
* @param request 请求
* @return 错误结果
*/
@ExceptionHandler(HandlerMethodValidationException.class)
public Result<Object> handleHandlerMethodValidationException(HandlerMethodValidationException e, HttpServletRequest request) {
// 错误结果
StringJoiner msg = new StringJoiner(CP_COMMA);
// 处理参数验证结果
e.getParameterValidationResults().forEach(validation -> {
// 获取参数名称
String paramName = validation.getMethodParameter().getParameterName();
// 获取字段约束违规
validation.getResolvableErrors().forEach(item -> msg.add(paramName + CP_COLON + item.getDefaultMessage()));
});
String errMsg = msg.toString();
debugLog("参数校验异常", errMsg, request, e);
return Result.badRequest(errMsg);
}
/**
* 参数校验异常
*
* @param e 参数校验异常
* @param request 请求
* @return 错误结果
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
public Result<Object> handleMethodArgumentNotValidException(MethodArgumentNotValidException e, HttpServletRequest request) {
// 错误结果
StringJoiner msg = new StringJoiner(CP_COMMA);
// 处理参数验证结果
e.getBindingResult().getFieldErrors().forEach(fieldError -> {
String fieldName = fieldError.getField();
String errorMessage = fieldError.getDefaultMessage();
msg.add(fieldName + CP_COLON + errorMessage);
});
String errMsg = msg.toString();
debugLog("参数校验异常", errMsg, request, e);
return Result.badRequest(errMsg);
}
/**
* 消息不可读异常
*
* @param e 消息不可读异常
* @param request 请求
* @return 错误结果
*/
@ExceptionHandler(HttpMessageNotReadableException.class)
public Result<Object> handleHttpMessageNotReadableException(HttpMessageNotReadableException e, HttpServletRequest request) {
String errMsg = "请求参数格式错误";
debugLog(errMsg, e.getMessage(), request, e);
return Result.badRequest(errMsg);
}
/**
* 公钥错误
*
* @param e 公钥错误
* @param request 请求
* @return 错误结果
*/
@ExceptionHandler(BizPublicKeyError.class)
public Result<Object> handleBizPublicKeyErrorException(BizPublicKeyError e, HttpServletRequest request) {
debugLog("公钥错误", e.getMessage(), request, e);
return new Result<>(true, e.getCode(), e.getMessage(), null);
}
/**
* 业务异常
*
* @param e 业务异常
* @param request 请求
* @return 错误结果
*/
@ExceptionHandler(BizError.class)
public Result<Object> handleBizErrorException(BizError e, HttpServletRequest request) {
debugLog("业务异常", e.getMessage(), request, e);
return new Result<>(true, e.getCode(), e.getMessage(), null);
}
/**
* 业务警告
*
* @param e 业务异常
* @param request 请求
* @return 警告结果
*/
@ExceptionHandler(BizWarning.class)
public Result<Object> handleBizWarningException(BizWarning e, HttpServletRequest request) {
debugLog("业务警告", e.getMessage(), request, e);
return new Result<>(true, e.getCode(), e.getMessage(), null);
}
/**
* 认证异常
*
* @param e 认证异常
* @return 错误结果
*/
@ExceptionHandler(UnauthorizedError.class)
public Result<Object> handleUnauthorizedErrorException(UnauthorizedError e) {
errorLog(LogLevel.ERROR, LogBusBaseType.CONTROLLER, "认证异常", e);
return new Result<>(ResultType.UNAUTHORIZED, null);
}
/**
* 请求方法不支持
*
* @param e 请求方法不支持异常
* @return 错误结果
*/
@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
public Result<Object> handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
errorLog(LogLevel.WARN, LogBusBaseType.CONTROLLER, "请求方法不支持", e, false);
return new Result<>(ResultType.METHOD_NOT_ALLOWED, null);
}
/**
* 资源未找到
*
* @param e 资源未找到异常
* @return 错误结果
*/
@ExceptionHandler(NoResourceFoundException.class)
public ResponseEntity<?> handleNoResourceFoundException(NoResourceFoundException e, HttpServletRequest request) {
errorLog(LogLevel.WARN, LogBusBaseType.CONTROLLER, "资源未找到", e, false);
if (checkTextResponse(request)) {
String body = JSONObject.toJSONString(new Result<>(ResultType.NOT_FOUND, null));
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(body);
} else {
return ResponseEntity.notFound().build();
}
}
/**
* 检查是否为文本响应
*
* @param request 请求
* @return 是否为文本响应
*/
private boolean checkTextResponse(HttpServletRequest request) {
String acceptHeader = request.getHeader(HttpHeaders.ACCEPT);
if (StringUtils.isBlank(acceptHeader)) {
return true;
}
List<MediaType> acceptedTypes = MediaType.parseMediaTypes(acceptHeader);
for (MediaType item : acceptedTypes) {
// 通配符 */* 表示可接受任意类型,包括文本
if (item.equals(MediaType.ALL)) {
return true;
}
String type = item.getType();
switch (type) {
case "text" -> {
return true;
}
case "image", "multipart" -> {
return false;
}
default -> {
}
}
if (
item.isCompatibleWith(MediaType.APPLICATION_ATOM_XML) ||
item.isCompatibleWith(MediaType.APPLICATION_FORM_URLENCODED) ||
item.isCompatibleWith(MediaType.APPLICATION_GRAPHQL_RESPONSE) ||
item.isCompatibleWith(MediaType.APPLICATION_JSON) ||
item.isCompatibleWith(MediaType.APPLICATION_NDJSON) ||
item.isCompatibleWith(MediaType.APPLICATION_PROBLEM_JSON) ||
item.isCompatibleWith(MediaType.APPLICATION_PROBLEM_XML) ||
item.isCompatibleWith(MediaType.APPLICATION_RSS_XML) ||
item.isCompatibleWith(MediaType.APPLICATION_XHTML_XML) ||
item.isCompatibleWith(MediaType.APPLICATION_XML) ||
item.isCompatibleWith(MediaType.APPLICATION_YAML)
) {
return true;
}
}
return false;
}
/**
* 客户端提前断开连接
*
* @param e 客户端提前断开连接异常
*/
@ExceptionHandler(ClientAbortException.class)
public void handleClientAbortException(ClientAbortException e) {
errorLog(LogLevel.WARN, LogBusBaseType.CONTROLLER, "客户端提前断开连接", e, false);
}
/**
* 默认全局异常处理
*
* @param e 异常
* @return 错误结果
*/
@ExceptionHandler(Exception.class)
public Result<Object> handleException(Exception e) {
errorLog(LogLevel.ERROR, LogBusBaseType.CONTROLLER, "默认全局异常处理", e);
return new Result<>(ResultType.INTERNAL_SERVER_ERROR, null);
}
/**
* 错误日志
*
* @param level 日志级别
* @param type 异常类型
* @param title 标题
* @param e 异常
*/
private void errorLog(LogLevel level, LogBusType type, String title, Exception e) {
errorLog(level, type, title, e, null);
}
/**
* 错误日志
*
* @param level 日志级别
* @param type 异常类型
* @param title 标题
* @param e 异常
* @param print 是否打印
*/
private void errorLog(LogLevel level, LogBusType type, String title, Exception e, Boolean print) {
LogTrack logTrack = LogTrackHolder.getDefNull();
if (Objects.isNull(logTrack)) {
logTrack = LogTrackHolder.getNewMain();
}
LogBus logBus = LogBus.init(level, type, logTrack).title(title).error(e);
if (Objects.nonNull(print)) {
logBus.print(print);
}
logBus.save();
}
/**
* 调试日志
*
* @param type 异常类型
* @param msg 错误消息
* @param request 请求
* @param e 异常
*/
private void debugLog(String type, String msg, HttpServletRequest request, Exception e) {
if (StringUtils.isBlank(msg)) {
log.debug("请求[{}]异常,类型[{}]", request.getRequestURI(), type, e);
} else {
log.debug("请求[{}]异常,类型[{}],错误消息[{}]", request.getRequestURI(), type, msg);
}
}
}
@@ -0,0 +1,54 @@
package xtools.boot.web.base.filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.jspecify.annotations.NonNull;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import xtools.boot.core.holder.CommonHolder;
import xtools.boot.web.filter.base.BaseFilter;
import java.io.IOException;
import static xtools.base.config.Constants.CP_NUM1;
import static xtools.base.config.Constants.CP_NUM100;
/**
* <p>Title : CommonFilter</p>
* <p>Description : CommonFilter</p>
* <p>DevelopTools : Idea_x64_v2026.1</p>
* <p>DevelopSystem : macOS Sequoia 15.7.5</p>
* <p>Company : org.xujun</p>
*
* @author : XuJun
* @version : 5.0.0
* @date : 2026/1/6 16:37
*/
@Slf4j
@Component
public class CommonFilter extends BaseFilter implements Ordered {
@Override
public int getOrder() {
return CP_NUM100 + CP_NUM1;
}
@Override
protected void doFilterInternal(
@NonNull HttpServletRequest request,
@NonNull HttpServletResponse response,
@NonNull FilterChain filterChain
) {
ScopedValue.where(CommonHolder.getScoped(), CommonHolder.create()).run(() -> {
try {
filterChain.doFilter(request, response);
} catch (IOException | ServletException e) {
printLog(e, "添加通用ScopedValue异常");
}
});
}
}
@@ -0,0 +1,75 @@
package xtools.boot.web.base.filter;
import jakarta.annotation.Resource;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.jspecify.annotations.NonNull;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import xtools.boot.api.constant.BootCommonConstant;
import xtools.boot.api.model.dto.log.HolderLogTrack;
import xtools.boot.core.utils.PathPatternUtils;
import xtools.boot.log.holder.LogTrackHolder;
import xtools.boot.web.base.config.LogTrackConfig;
import xtools.boot.web.filter.base.BaseFilter;
import xtools.core.StringUtils;
import xtools.web.HeaderUtils;
import java.io.IOException;
import static xtools.base.config.Constants.CP_NUM100;
/**
* <p>Title : LogTrackFilter</p>
* <p>Description : LogTrackFilter</p>
* <p>DevelopTools : Idea_x64_v2026.1</p>
* <p>DevelopSystem : macOS Sequoia 15.7.5</p>
* <p>Company : org.xujun</p>
*
* @author : XuJun
* @version : 5.0.0
* @date : 2026/1/6 16:37
*/
@Slf4j
@Component
public class LogTrackFilter extends BaseFilter implements Ordered {
@Resource
private LogTrackConfig logTrackConfig;
@Override
public int getOrder() {
return CP_NUM100;
}
@Override
protected void doFilterInternal(
@NonNull HttpServletRequest request,
@NonNull HttpServletResponse response,
@NonNull FilterChain filterChain
) {
String uri = HeaderUtils.getUri(request);
String headerLogTrack = HeaderUtils.getHeader(request, BootCommonConstant.LOG_TRACK);
HolderLogTrack logTrack;
if (StringUtils.isBlank(headerLogTrack)) {
logTrack = LogTrackHolder.newMain();
} else {
logTrack = LogTrackHolder.newByBase64(headerLogTrack);
}
ScopedValue.where(LogTrackHolder.getScoped(), logTrack).run(() -> {
// 判断该uri是否忽略记录日志
if (PathPatternUtils.match(logTrackConfig.getIgnorePath(), uri)) {
LogTrackHolder.saveLog(false);
}
try {
filterChain.doFilter(request, response);
} catch (IOException | ServletException e) {
printLog(e, "添加日志追踪ScopedValue异常");
}
});
}
}
@@ -0,0 +1,36 @@
package xtools.boot.web.base.selector;
import org.jspecify.annotations.NonNull;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
/**
* <p>Title : BootWebBaseImportSelector</p>
* <p>Description : BootWebBaseImportSelector</p>
* <p>DevelopTools : Idea_x64_v2026.1</p>
* <p>DevelopSystem : macOS Sequoia 15.7.5</p>
* <p>Company : org.xujun</p>
*
* @author : XuJun
* @version : 5.0.0
* @date : 2026/01/01 09:30
*/
public class BootWebBaseImportSelector implements ImportBeanDefinitionRegistrar {
/**
* 根据给定的注释元数据,根据需要注册bean
*
* @param importingClassMetadata AnnotationMetadata
* @param registry BeanDefinitionRegistry
*/
@Override
public void registerBeanDefinitions(@NonNull AnnotationMetadata importingClassMetadata, @NonNull BeanDefinitionRegistry registry) {
// 构建扫描对象
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(registry, true);
// 扫描包下路径
scanner.scan("xtools.boot.web.base");
}
}