跳转到正文

快速开始

本例完成“经应用上传文本文件 → MinIO 保存对象 → MySQL 保存记录 → 管理端查询 → 核对对象内容”的同步流程。

前提是已有 EFC Web 应用,采用当前 Java 25、Spring Boot 4.1.0 基线,相关 4.1.0-SNAPSHOT 依赖在项目 Maven 仓库或本地可用。应用需具备 MySQL 驱动、数据源、框架基础 MapperUtil Bean 和管理端认证环境。

另外准备一个可连接的 MinIO 服务、测试 bucket 及具备该 bucket 查询和写入权限的凭证。示例使用非敏感文件;用 MinIO 控制台核对文件即可,若要浏览器直接访问,还需自行提供可读取该对象的访问策略或文件服务。

1. 添加依赖

在应用 POM 中导入 Business BOM,已有配置不重复导入。

xml
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.own</groupId>
            <artifactId>springboot-business-dependencies</artifactId>
            <version>4.1.0-SNAPSHOT</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
        <groupId>com.own.business</groupId>
        <artifactId>springboot-business-resource-module-minio</artifactId>
    </dependency>
    <dependency>
        <groupId>com.own.business</groupId>
        <artifactId>springboot-business-resource-controller-admin</artifactId>
    </dependency>
    <dependency>
        <groupId>com.own.component</groupId>
        <artifactId>springboot-component-store-starter-local</artifactId>
    </dependency>
</dependencies>

MinIO 适配器已传递依赖 App Controller、Business、Core 和 Common,无需再次声明 App Controller。管理端依赖用于本例的记录查询。

ResourceTemporaryAccessUtil 无条件注入名为 storeTemplateStoreTemplate<String>,即使只使用公有文件上传也要满足该 Bean 的装配。示例用本地 Store 提供它;已有 Store 实现时沿用原配置,不重复引入另一后端。模板装配与 Redis 接入见 Component 的Store 后端与配置

2. 准备数据库和存储配置

在应用数据库中执行 资源文件首次建表 SQL,创建 own_system_file_recordidx_md5idx_md5_position

脚本保留当前业务源码的表结构和索引,移除了 DROP TABLE,只用于尚未创建该表的数据库,不是增量迁移;应用不会自动执行它。

在应用 application.yml 中添加或合并:

yaml
spring:
  datasource:
    url: ${RESOURCE_JDBC_URL}
    username: ${RESOURCE_DB_USERNAME}
    password: ${RESOURCE_DB_PASSWORD}
    driver-class-name: com.mysql.cj.jdbc.Driver
  servlet:
    multipart:
      max-file-size: 10MB
      max-request-size: 20MB

own:
  resource:
    primary: default
    unique: REPEAT
    source:
      type: MINIO
      end-point: ${RESOURCE_MINIO_ENDPOINT}
      key: ${RESOURCE_MINIO_ACCESS_KEY}
      secret: ${RESOURCE_MINIO_SECRET_KEY}
      bucket: ${RESOURCE_MINIO_BUCKET}
      position: ${RESOURCE_MINIO_POSITION}
      private-read: false
环境变量填写方式
RESOURCE_JDBC_URL应用的 MySQL JDBC 地址
RESOURCE_DB_USERNAMERESOURCE_DB_PASSWORD应用数据库凭证
RESOURCE_MINIO_ENDPOINTMinIO S3 API 地址,包含协议,如 http://127.0.0.1:9000;不是管理控制台地址
RESOURCE_MINIO_ACCESS_KEYRESOURCE_MINIO_SECRET_KEY具备测试 bucket 访问权限的凭证
RESOURCE_MINIO_BUCKET已准备的 bucket,如 resource-demo
RESOURCE_MINIO_POSITION对外访问前缀,包含 bucket 且不以 / 结尾,如 http://127.0.0.1:9000/resource-demo

必须显式填写 position:上传服务在调用 MinIO 之前就将其写入上传模型,适配器上传后再补默认值无法保证当前记录地址正确。private-read: false 仅声明模块访问属性,不会修改 bucket 权限。

unique: REPEAT 跳过有缺陷的单记录 MD5 复用查询,但仍计算并保存 MD5。当前默认 NEXT + UNIQUE 在首次 MD5 未命中时会抛出 business_not_found,详见上传与直传签名。上传体积限制是本例的应用配置,不是资源模块默认值。

3. 补充 Mapper 扫描

UseBusinessResource 已通过自动配置导入文件注册,会扫描 com.own.business.resource 下的 Spring 组件;但其 Mapper 扫描常量为 com.own.business.resource.mapper,实际 Mapper 位于 com.own.business.resource.business.mapper,且接口没有单独的 @Mapper 注解。

在应用启动类能够扫描的包中加入以下配置,或将该包并入应用已有的 @MapperScan

java
package com.example.config;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = false)
@MapperScan("com.own.business.resource.business.mapper")
public class ResourceMapperConfiguration {
}

保留其他业务所需的扫描范围。启动后应能注入 ResourceServiceFileRecordServiceFileRecordMapperMapperUtilstoreTemplate,并完成 PageHelper 分页装配。

4. 上传文件

创建一个本地 resource-demo.txt,内容为 resource demo。启动应用,然后在该文件所在目录执行:

bash
curl --request POST 'http://localhost:8080/api/app/resource/upload?method=default' \
  --form 'file=@resource-demo.txt;type=text/plain'

替换应用域名、端口及实际 context path。file 是 multipart 字段名,不要用 JSON 发送文件。本模块的 App Controller 标记 @LoginIgnore,若应用网关还有额外认证规则,则按现有协议携带认证信息。

成功响应为 ResultModel<FileRecordVo>,业务码 code=00000。记录 data.id,并核对:

  • oldNameresource-demo.txtname 为保留扩展名的随机文件名。
  • path 为日期目录和对象名组成的相对路径,如 /2026/09/09/<随机名>.txt;日期取应用运行时本地日期。
  • position 为配置的对外访问前缀,size 为原文件字节数,md5 为文件摘要。

5. 查询记录并核对文件

使用已通过管理端认证的 API 客户端调用 GET /api/admin/file/record/{fileId},将 {fileId} 换成上传返回的 data.id。也可以调用 POST /api/admin/file/record/page,请求体为:

json
{
  "page": 1,
  "rows": 10
}

单条结果在 data,分页列表在 data.list。当前分页不支持按文件名或 MD5 筛选,也没有默认排序,因此精确核对本次上传应使用记录 ID,详见文件记录管理

在 MinIO 控制台查看相应 bucket,使用 path 去掉开头 / 后的对象键定位文件,下载后核对内容与原文件字节数。若已配置可读取对象的访问规则,Linux/macOS 应用通常可用 position + path 打开文件;private-read=false 本身不会开放读权限。

再次上传同一文件,本例 REPEAT 配置应生成新的随机对象名与记录 ID。资源上传和文件记录写入是同步顺序执行的,不是一个覆盖对象存储和数据库的事务。

下一步