玉溪市网站建设_网站建设公司_企业官网_seo优化
2026/1/5 19:39:57 网站建设 项目流程

模块描述回顾

功能

该模块具备文档存储、元数据管理以及加密存取的功能。想象一下,它就像是一个超级文件仓库,不仅能存放各种文件,还能记录文件的详细信息,并且保证文件的安全存储,就如同给文件加上了一把密码锁。

需求

它需要具备多种存取模式,并且要脱离具体业务,专注于存储本身。这就好比一个通用的文件保管箱,不管你是做什么业务的,都能按照不同的方式把文件存进去、取出来。

设计

采用基于DDD(领域驱动设计)架构的微服务设计。提供FileClient SDK和REST API双重接口,就像给用户提供了两把不同的钥匙来访问这个文件仓库。同时支持URL和UUID两种文件访问模式,用户可以根据自己的习惯或需求选择合适的方式。还可以自定义密钥进行加密存取,或者借助MinIO来使用相关能力,为文件存储的安全性和灵活性提供了更多选择。

架构组成

file - storage - service

这是核心存储服务,就像仓库的核心管理系统,它会注册到Nacos,方便其他服务找到它并与之交互。

file - api

作为客户端SDK,它提供了FileClient接口,供其他服务调用,就像是仓库的外部操作控制台,其他服务通过它来对仓库里的文件进行各种操作。

开发过程

首先要做的是划分DDD结构。至于其他具体接口业务流程,由于较为复杂,这里就不详细说了。如果您有兴趣,可以直接查看源码,预计不久后就会公布。

核心实体设计

FileResource(文件资源聚合根)

它就像是文件在这个系统中的“总管家”,具备一系列重要的“领域行为”:

  • 创建文件资源,就好比是为新文件在仓库里安排一个存放位置。
  • 生成访问URL,方便用户通过网址来访问文件。
  • 验证权限,只有有权限的人才能对文件进行操作,确保文件安全。
  • 更新元数据,随时记录文件信息的变化。
  • 加密/解密文件,给文件加上或去掉密码锁。

它还包含多个“值对象”,就像是这位“总管家”的助手,各有各的职责:

  • FileMetadata:负责管理文件元数据,包括文件名、大小、类型、创建时间、修改时间等信息。这里还有一些“业务规则”,比如文件大小限制在10MB,并且优先支持PDF格式验证,就像是仓库对存放文件的一些规定。
  • StorageLocation:处理存储位置相关的事务,像bucketName、directory、fileUrl、存储路径等。同时遵循一些规则,比如保证UUID的唯一性,对路径进行规范化处理,还有bucket分类策略,这就像是仓库对不同区域的规划和管理。
  • AttachmentUuid:作为文件唯一标识符,就像每个人的身份证一样,确保每个文件都有独一无二的标识。它也有自己的“业务规则”,要验证UUID格式并且保证其唯一性。
  • EncryptionMetadata:负责加密元数据相关的工作,比如记录文件是否加密、加密算法类型、公钥信息等。并且要对AES算法和公钥格式进行验证,保证加密的可靠性。
FileMetadata(文件元数据值对象)
  • 领域概念:文件名、大小、类型、创建时间、修改时间,这些信息就像文件的“个人档案”。
  • 业务规则:文件大小限制(10MB)、支持格式验证(PDF优先),就像是仓库对文件“入住”的要求。
StorageLocation(存储位置值对象)
  • 领域概念:bucketName、directory、fileUrl、存储路径,明确文件在仓库中的具体位置。
  • 业务规则:UUID唯一性、路径规范化、bucket分类策略,确保位置的准确性和规范性。
AttachmentUuid(UUID值对象)
  • 领域概念:文件唯一标识符,是文件的独特标识。
  • 业务规则:UUID格式验证、唯一性保证,防止出现重复或错误的标识。
EncryptionMetadata(加密元数据值对象)
  • 领域概念:是否加密、加密算法类型、公钥信息,记录文件加密相关的重要信息。
  • 业务规则:AES算法验证、公钥格式验证,保障加密的正确性和安全性。

核心接口设计

FileClient(客户端接口)

它提供了8个核心方法供其他服务使用,这些方法就像是操作文件仓库的各种工具:

URL操作接口
  • uploadByUrl(file, bucketName, publicKey?):通过URL上传文件,就像是通过一个特定的地址把文件送进仓库。
  • downloadByUrl(fileUrl, publicKey?):通过URL下载文件,从指定地址把文件从仓库中取出来。
  • queryByUrl(fileUrl):通过URL查询文件信息,了解文件在仓库中的相关情况。
  • deleteByUrl(fileUrl):通过URL删除文件,把不需要的文件从仓库中移除。
UUID操作接口
  • uploadByUuid(file, bucketName, uuid?, publicKey?):通过UUID上传文件,使用文件的唯一标识来完成上传操作。
  • downloadByUuid(uuid, publicKey?):通过UUID下载文件,凭借唯一标识找到并取出文件。
  • queryByUuid(uuid):通过UUID查询文件信息,查看这个唯一标识对应的文件详情。
  • deleteByUuid(uuid):通过UUID删除文件,利用唯一标识把文件从仓库中清除。

设计模式

抽象工厂模式

采用抽象工厂模式是为了方便以后支持其他第三方存储,而且本地存储在测试的时候也非常实用。就像搭建一个可扩展的存储框架,以后可以轻松添加不同类型的“存储房间”。

// StorageProviderFactory类,根据配置创建存储提供者interfaceStorageProviderFactory{StorageProvidercreateStorageProvider();}// MinIOStorageProvider类,MinIO存储实现classMinIOStorageProviderimplementsStorageProvider{// 实现MinIO相关存储方法}// LocalStorageProvider类,本地存储实现(开发环境)classLocalStorageProviderimplementsStorageProvider{// 实现本地存储相关方法}
代理模式

代理模式在这里也发挥了重要作用。

// FileClientImpl类,FileClient接口的代理实现classFileClientImplimplementsFileClient{// 通过Feign代理调用远程file-storage-service@OverridepublicvoidsomeMethod(){try{// Feign调用逻辑}catch(Exceptione){// 处理网络异常和重试逻辑}}}

FileClientImpl作为FileClient接口的代理实现,通过Feign代理调用远程的file - storage - service,并且处理网络异常和重试逻辑,就像是一个中间人,帮你和远程的仓库管理系统打交道,并且处理可能出现的问题。

实际开发

完成以上设计后,我先开发了一个新增接口,搭建出文件结构,并用伪代码填充内容。之后让claude code生成了具体逻辑,并且测试通过了。对于之后的其他接口,我明确指定按照这个新增接口进行开发,并且严格遵守设计文档,整个开发过程还算顺利。你在开发类似功能模块时,有没有遇到过因为接口设计不合理而导致开发困难的情况呢?

验收

在验收过程中,主要问题集中在feign部分。我的初衷是让下游服务不需要太多配置就可以调用file服务,所以针对这个问题进行了一些研究,并且设计了相关的feign规范。没想到这个规范直接引出了common模块。你在项目验收时,有没有遇到过因为某个组件问题而引发一系列调整的情况呢?

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询