首页 > 其他分享 >文件存储引擎模块封装和使用分享

文件存储引擎模块封装和使用分享

时间:2023-11-09 13:12:50浏览次数:35  
标签:存储 java zone zonezzc 模块 StorageEngine 封装 FileUploadUtil

image

背景

需求

在项目开发过程中,经常会使用到文件存储相关的功能,如:

  1. 存储发票文件
  2. 提供发票下载地址
  3. ……

调研

诸如此类的功能就需要使用到本地存储或云服务商提供的存储功能。当然,这对于开发高手的 zone 来说都是小意思,上网一查,对象存储哪家强?

image

第一位赫然显示了百家号创作者推荐的阿里云 OSS 服务,那行,就你吧,还要赶紧摸鱼等下班呢。接 API 嘛,小意思分分钟搞定,写个工具类封装一点上传下载方法那有多难。

开发

在下班点过了 1 小时之后 zone 终于写完了基于 OSS 对象存储服务封装的 FileUploadUtil.java​,并且与业务方法结合,实现了产品的需求。

同事问:「为什么是 FileUploadUtil​,光上传了那下载呢?」
zone 淡定回答:「奥,下载也在工具类里面,用 OssUtil​ 命名怕后来的同事找不到,FileUploadUtil​ 多见名知意呀。」
同事问:「下载方法也在里面那为什么不用 FileUtil​ 命名工具类呢?」
zone 淡定回答:「当然是因为 FileUtil​ 被之前的开发占用掉了,我这个工具类里面有云存储,当然比 FileUtil​ 更高级咯,得区分开来。」
同事问:「行吧,大佬 NB,回头我直接抄了昂。」
zone 淡定回答:「随便用。」

多项目复用

半年时间匆匆流逝,曾经的 FileUploadUtil​ 工具类随着 zone 和同事娴熟的 CV 大法,在公司的项目里遍地开花。闲暇时间,每当看到新接手的项目中不是由自己 V 过去的 FileUploadUtil​,自豪感爆棚,我太牛了。

服务商迁移

但是好景不长,今天新来的技术总监说 OSS 的云服务太贵了,我们要「降本」,更换 AWS 的 S3 对象存储能免费用一年,所有项目都给我迁。随着总监的一声令下,正摸鱼的 zone 不爽了,由于公司里 80% 的项目用的都是 FileUploadUtil​,迁移的事情不出所料的落在了自己头上。得,曾经觉的自己有多牛,如今就觉的自己有多苦。活还是得干,zone 看了一下 S3 的接口文档,刷刷刷的把 FileUploadUtil​ 给改了,顺便把剩下的 20% 项目里也 V 过去了新改到接入 S3 的 FileUploadUtil​。

技术总监验收之后说:「小伙子做的不错,降本这件事情我肯定记你一笔。」就这样 zone 亲眼看到总监真就打开了云笔记记了一笔,就再也没了下文。期待的升职加薪还没有发生,半个月后新的运维总监来了,直接以数据安全为由说服了爱国老板,说要把对象存储迁回 OSS。身为底层开发人员的 zone 当然什么也不知道,只看到任务系统来了个紧急任务,标题「云存储服务迁移」内容直接就三字「迁回去」。zone 看了看手里的奶茶和任务系统里的驳回选项,忍住了即将破口而出的爆珠还是选择嚼碎了吞下去,毕竟生活已然不易,更容不得一丝一毫的浪费,忍了。

多重实现导致 P0 事件

就是这次,还发现了一些隐藏问题。之前的那 20% 的项目中,为了抓紧时间下班陪妹子,并没有把别的同事写的 ossClient​ 对象删除掉,人是偷了懒,但程序可不惯着,这回 zone 在把 FileUploadUtil​ 换回来的时候,项目直接启动失败。这咋回事啊,查看报错信息,原来是有同名 Bean!

APPLICATION FAILED TO START

Description:

The bean 'ossClient', defined in class path resource [com/zonezzc/FileUploadUtil.class], could not be registered. A bean with that name has already been defined in class path resource [com/zonezzc/OssConfiguration.class] and overriding is disabled.

Action:

Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true

已与地址为 ''127.0.0.1:52291',传输: '套接字'' 的目标虚拟机断开连接

修复这个问题的同时,zone 仔细搜了搜代码,发现这还不是最坑的,最坑的是竟然还有更多的 ossClient​ Bean 并不叫这个名字,叫什么 ossClient1​、ossClient2​,由于之前没有仔细检查,在切换了 S3 服务半个月后的今天,竟然还有文件的上传和下载在使用 OSS 服务,这把 zone 吓得出了一身冷汗,赶紧修复了代码并上报了技术总监。技术总监也不含糊,10 分钟后就定了个 P0 事件给捅上去了,20 分钟后全公司就通过邮件知道了 zone 这个名字,通宵达旦的问题修复就此展开了序幕。

复盘

经过这次 P0 事件,zone 痛定思痛,决定从根本上解决。

之前存在的技术问题

  1. 工具类的使用没有在公司内进行培训,导致 CV 现象和重新开发并存,没有形成统一。
  2. 没有考虑文件存储服务商变更的可能性,导致服务商变更之后不能实现快速安全切换。
  3. 没有抽象文件存储功能,​FileUploadUtil​ 工具类代码侵入性太高,没有与业务系统解耦。

看着这些问题,zone 把脑袋一拍,接着就有了一个大胆的想法,不如就趁这次,设计一个「文件存储引擎」。

概念

image

设计

模板模式

StorageEngine​效果

第一版

实现内容

.
├── java
│   └── com
│       └── zonezzc
│           └── storage
│               └── engine
│                   ├── StorageApplication.java
│                   ├── config
│                   │   ├── CosStorageEngineConfig.java
│                   │   ├── KodoStorageEngineConfig.java
│                   │   └── OssStorageEngineConfig.java
│                   ├── core
│                   │   ├── AbstractStorageEngine.java
│                   │   ├── StorageEngine.java
│                   │   └── context
│                   │       ├── DeleteFileContext.java
│                   │       ├── DownloadUrlContext.java
│                   │       ├── ReadFileContext.java
│                   │       └── StoreFileContext.java
│                   ├── cos
│                   │   └── CosStorageEngine.java
│                   ├── kodo
│                   │   └── KodoStorageEngine.java
│                   ├── oss
│                   │   └── OssStorageEngine.java
│                   └── utils
│                       └── FileUtils.java
└── resources
    ├── application-dev.yml
    ├── application-prod.yml
    ├── application-test.yml
    └── application.yml

# application.yml
storage:
  engine:
    oss:
      endpoint: oss-cn-shanghai.aliyuncs.com
      accessKeyId: xxxxxxxxxxxxxxxxxxxxxxxx
      accessKeySecret: xxxxxxxxxxxxxxxxxxxxxxxx
      bucketName: zonezzc
    cos:
      secretId: xxxxxxxxxxxxxxxxxxxxxxxx
      secretKey: xxxxxxxxxxxxxxxxxxxxxxxx
      region: ap-shanghai
      bucketName: zonezzc-1253326811
    kodo:
      region: z2
      accessKey: xxxxxxxxxxxxxxxxxxxxxxxx
      secretKey: xxxxxxxxxxxxxxxxxxxxxxxx
      bucketName: zonezzc

使用方式

CV 大法,在项目中把所有代码复制粘贴,人工适配

注入 StorageEngine 对象
    @Resource
    private StorageEngine storageEngine;
使用 StorageEngine 提供的文件上传下载方法

image​第二版

实现内容

image​使用方式

  1. 引入对应的文件存储引擎依赖
  2. 根据提示配置 applecation.yml
  3. 注入 StorageEngine ​对象
  4. 使用 ​StorageEngine​ 提供的文件上传下载方法
引入依赖
<dependency>
    <groupId>com.zonezzc</groupId>
    <artifactId>storage-engine-oss</artifactId>
    <version>0.0.1</version>
</dependency>
配置引擎需要的信息

image

com:
  zonezzc:
    storage:
      engine:
        oss:
          access-key-id: xxxxxxxxxxxxxxxxxxxxxxxx
          access-key-secret: xxxxxxxxxxxxxxxxxxxxxxxx
          endpoint: oss-cn-shanghai.aliyuncs.com
          bucket-name: zonezzc
          auto-create-bucket: true

注入 StorageEngine 对象
    @Resource
    private StorageEngine storageEngine;

使用 StorageEngine 提供的文件上传下载方法

image

标签:存储,java,zone,zonezzc,模块,StorageEngine,封装,FileUploadUtil
From: https://www.cnblogs.com/zonezzc/p/file-storage-engine-module-packaging-and-use-sharing-z1k

相关文章

  • redis 类型Hash 中value字符串存储空间大小
    在Redis中,Hash数据类型中的value是字符串,存储空间大小取决于存储在Hash中的每个value字符串的长度。Redis内部并不会额外存储每个value的元信息,因此存储空间大小主要由存储的字符串长度决定。每个字符串值的存储空间大小取决于以下因素:字符串长度:字符串的长度是主要的决定因素。较......
  • 本地lib包多模块下开发和部署
    1首先可以放到idea的file-projectStructure-GlobalLibraries2然后添加到模块,实在不好使就手动加入到pom文件<dependency><groupId>*</groupId><artifactId>*</artifactId><scope>system</scope>&......
  • 11月9月字体的属性2以及div模块的另一种用法
    目录字体的属性2文字对齐文字的装饰首行缩进文字的距离设置块级标签的另一个作用字体的属性2文字对齐、文字装饰、首行缩进、文字之间的距离文字对齐需要用到属性text-align,该属性是用于规定元素中的文本水平对齐方式。然后就是text-align的属性值:值描述left左边......
  • salt自定义模块内使用日志例子
    如果你想要在你的SaltMinion中使用自定义的Salt模块并且记录日志,你可以创建一个自定义Salt模块,并在模块中使用Python的标准`logging`库来记录日志。以下是一个示例:首先,在SaltMaster上创建一个自定义模块的目录,例如`/srv/salt/_modules/`。然后在该目录中创建一个Python文件,例......
  • springboot中部分数据的封装方法
    //响应字符串格式数据@RequestMapping("/hello")publicResulthello(){System.out.println("HelloWorld");//returnnewResult(1,"success","HelloWorld");returnResult.success("HelloWorl......
  • 封装 Vue 组件的过程?
    组件可以提升整个项目的开发效率。能够把页面抽象成多个相对独立的模块,解决了我们传统项目开发:效率低、难维护、复用性等问题分析需求:确定业务需求,把页面中可以复用的结构,样式以及功能,单独抽离成一个文件,实现复用具体步骤:使用Vue.extend方法创建一个组件,然后使用Vue.comp......
  • Kurator v0.5.0发布,打造统一的多集群备份与存储体验
    本文分享自华为云社区《Kuratorv0.5.0正式发布!打造统一的多集群备份与存储体验》,作者:云容器大未来。Kurator是由华为云推出的开源分布式云原生套件。面向分布式云原生场景,Kurator旨在为用户提供一站式的解决方案,帮助用户快速构建自己的分布式云原生平台。在最新发布的v0.......
  • /etc/passwd 存储用户基本信息
    用户名::口令:用户标识号:组标识号:用户名:用户主目录:命令解释程序(1)注册名(login_name):用于区分不同的用户。在同一系统中注册名是惟一的。在很多系统上,该字段被限制在8个字符(字母或数字)的长度之内;并且要注意,通常在Linux系统中对字母大小写是敏感的。这与MSDOS/Windows是不一样的。......
  • 五种实现数据加密存储的方式,你选择哪一种
    前言最近由于项目需要做等保,其中有一项要求是系统中的个人信息和业务信息需要进行加密存储。经过一番搜索,最终总结出了五种数据加密存储的方法(结合SpringBoot和MyBatisPlus框架进行实现),不知道家人们在项目中使用的是哪种方式......
  • python初学者学习笔记-第八章-模块和包
    chapter8/模块和包8.1.模块8.1.1模块简介类、函数、变量等,都可重复使用。为了方便调用,我们通常把他们放到Python文件之中。单个文件的代码阅读和调用都比较混乱。代码最好分开存储,相似功能的代码放在一起。模块可以帮助我们实现这样的功能。后缀为py的文件都是python的......