From af1430eaee7a642a91bc775c900d7fd1acdcf86b Mon Sep 17 00:00:00 2001 From: "weicw1996@qq.com" Date: Sun, 20 Sep 2026 19:31:58 +0800 Subject: [PATCH] =?UTF-8?q?:bug:=20=E4=BF=AE=E5=A4=8D=E6=9C=AA=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=20MinIO=20=E6=97=B6=20transport=20=E6=9C=8D=E5=8A=A1?= =?UTF-8?q?=E6=97=A0=E6=B3=95=E5=90=AF=E5=8A=A8=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 凭证图片 MinIO 客户端此前为无条件装配,缺少 file.storage.minio.endpoint 配置时会在启动阶段直接抛 IllegalArgumentException,导致整个 blade-transport 服务起不来,并在关闭失败上下文时连带抛出 nacosGracefulShutdownDelegate 的 BeanCreationNotAllowedException, 掩盖了真正的失败原因。 - VoucherMinioConfig 增加 @ConditionalOnProperty,未配置 endpoint 时不注册客户端 - ProcessConfigController、VoucherManageServiceImpl 改用 ObjectProvider 可选注入,避免构造器注入因 bean 缺失而启动失败 - 新增 minioClient() 访问器,在真正调用时给出"未配置"的明确提示, 与已有 validateMinioConfig() 的提示风格保持一致 未配置 MinIO 时服务可正常启动,凭证相关接口仅在使用时提示配置缺失; 已配置 MinIO 时行为不变。 --- .../transport/config/VoucherMinioConfig.java | 6 ++++ .../controller/ProcessConfigController.java | 25 ++++++++++--- .../impl/VoucherManageServiceImpl.java | 35 +++++++++++++------ 3 files changed, 51 insertions(+), 15 deletions(-) diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/config/VoucherMinioConfig.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/config/VoucherMinioConfig.java index 5c0545b..08ed5e3 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/config/VoucherMinioConfig.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/config/VoucherMinioConfig.java @@ -6,14 +6,20 @@ package org.springblade.transport.config; import io.minio.MinioClient; import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * 凭证图片 MinIO 客户端配置。 + *

* 连接参数由 Nacos 的 file.storage.minio 配置提供。 + * 未配置 {@code file.storage.minio.endpoint} 时不注册该客户端, + * 以免凭证上传功能缺失配置导致整个 blade-transport 服务无法启动; + * 此时凭证相关接口会在调用时给出明确提示,而非启动即失败。 */ @Configuration +@ConditionalOnProperty(prefix = "file.storage.minio", name = "endpoint") public class VoucherMinioConfig { @Bean diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/ProcessConfigController.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/ProcessConfigController.java index 8df54de..c0cb3d3 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/ProcessConfigController.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/ProcessConfigController.java @@ -52,6 +52,7 @@ import org.springblade.transport.pojo.entity.Waybill; import org.springblade.transport.pojo.vo.BusinessRemoveResultVO; import org.springblade.transport.pojo.vo.ProcessConfigVO; import org.springblade.transport.service.IProcessConfigService; +import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; @@ -83,20 +84,34 @@ public class ProcessConfigController extends BladeController { private final VoucherFileMapper voucherFileMapper; private final VoucherImageMapper voucherImageMapper; private final VoucherManageMapper voucherManageMapper; - private final MinioClient minioClient; + private final ObjectProvider minioClientProvider; @Value("${file.storage.minio.bucket-name:${minio.bucket-name:}}") private String minioBucketName; public ProcessConfigController(IProcessConfigService processConfigService, WaybillMapper waybillMapper, VoucherFileMapper voucherFileMapper, VoucherImageMapper voucherImageMapper, VoucherManageMapper voucherManageMapper, - MinioClient minioClient) { + ObjectProvider minioClientProvider) { this.processConfigService = processConfigService; this.waybillMapper = waybillMapper; this.voucherFileMapper = voucherFileMapper; this.voucherImageMapper = voucherImageMapper; this.voucherManageMapper = voucherManageMapper; - this.minioClient = minioClient; + this.minioClientProvider = minioClientProvider; + } + + /** + * 获取 MinIO 客户端。 + *

+ * 未配置 file.storage.minio.endpoint 时该客户端不会被注册, + * 此时凭证预览地址无法生成,抛出明确提示而非启动即失败。 + */ + private MinioClient minioClient() { + MinioClient minioClient = minioClientProvider.getIfAvailable(); + if (minioClient == null) { + throw new IllegalStateException("Nacos 未配置 file.storage.minio.endpoint,凭证文件功能不可用"); + } + return minioClient; } @GetMapping("/detail") @@ -147,7 +162,7 @@ public class ProcessConfigController extends BladeController { result.put("waybillNo", image.getWaybillNo()); result.put("objectKey", image.getObjectKey()); try { - result.put("url", minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder() + result.put("url", minioClient().getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder() .method(Method.GET).bucket(minioBucketName).object(image.getObjectKey()) .expiry(1, TimeUnit.HOURS).build())); } catch (Exception e) { @@ -270,7 +285,7 @@ public class ProcessConfigController extends BladeController { result.put("objectKey", image.objectKey()); result.put("matched", image.matched()); try { - result.put("url", minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder() + result.put("url", minioClient().getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder() .method(Method.GET).bucket(minioBucketName).object(image.objectKey()) .expiry(1, TimeUnit.HOURS).build())); } catch (Exception exception) { diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/VoucherManageServiceImpl.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/VoucherManageServiceImpl.java index 3b4d519..6eb2e8b 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/VoucherManageServiceImpl.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/VoucherManageServiceImpl.java @@ -42,6 +42,7 @@ import io.minio.PutObjectArgs; import io.minio.RemoveObjectArgs; import io.minio.http.Method; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.annotation.Value; import java.time.format.DateTimeFormatter; @@ -79,14 +80,14 @@ public class VoucherManageServiceImpl extends BaseServiceImpl minioClientProvider; private final String minioBucketName; private final String minioRootDirectory; public VoucherManageServiceImpl(VoucherWaybillBatchMapper voucherWaybillBatchMapper, IProjectApplyService projectApplyService, IWaybillService waybillService, VoucherImageMapper voucherImageMapper, VoucherFileMapper voucherFileMapper, - ApplicationEventPublisher eventPublisher, MinioClient minioClient, + ApplicationEventPublisher eventPublisher, ObjectProvider minioClientProvider, @Value("${file.storage.minio.bucket-name:${minio.bucket-name:}}") String minioBucketName, @Value("${file.storage.minio.root-directory:${minio.root-directory:}}") String minioRootDirectory) { this.voucherWaybillBatchMapper = voucherWaybillBatchMapper; @@ -95,7 +96,7 @@ public class VoucherManageServiceImpl extends BaseServiceImpl candidateObjectKeys = resolvedObjectKey.equals(objectKey) ? List.of(objectKey) : List.of(resolvedObjectKey, objectKey); for (String candidateObjectKey : candidateObjectKeys) { - try (InputStream source = minioClient.getObject(GetObjectArgs.builder().bucket(minioBucketName).object(candidateObjectKey).build()); + try (InputStream source = minioClient().getObject(GetObjectArgs.builder().bucket(minioBucketName).object(candidateObjectKey).build()); OutputStream target = Files.newOutputStream(archivePath)) { source.transferTo(target); return archivePath; @@ -427,7 +428,7 @@ public class VoucherManageServiceImpl extends BaseServiceImpl + * 未配置 file.storage.minio.endpoint 时该客户端不会被注册, + * 此处给出与 {@link #validateMinioConfig()} 一致的明确提示。 + */ + private MinioClient minioClient() { + MinioClient minioClient = minioClientProvider.getIfAvailable(); + if (minioClient == null) { + throw new ServiceException("Nacos 未配置 file.storage.minio.endpoint,凭证文件功能不可用"); + } + return minioClient; + } + private String buildObjectKey(Long voucherId, String waybillNo, String plateNo, String entryName) { String objectKey = voucherId + "/" + waybillNo + "/" + safePathPart(plateNo) + "/" + safeArchivePath(entryName); if (Func.isEmpty(minioRootDirectory)) { @@ -1127,7 +1142,7 @@ public class VoucherManageServiceImpl extends BaseServiceImpl