搭建属于自己的对象储存服务及短链服务(Minio)

文档地址

minio官方文档: https://docs.min.io/?ref=ob

minio 中文文档地址: http://docs.minio.org.cn/docs/master/java-client-api-reference

备注

不同版本的minio所实现的api和类是不同的,需要根据自己的需求版本进行实现,文档中的内容仅供参考,尤其是中文文档,版本过老,实际api调用方式已完全不同,建议以官方文档与实际版本源代码作为实现功能,本文使用 版本 8.2.2

本文版本

versionv 内容
1.0.0 初步实现,minio基础存储(获取)对象,通过redis缓存实现短链服务。

实现逻辑

实现minio储存

业务版本: version_1.0.0

业务说明: 仅需实现 minio基础的储存功能与简单的短链服务

minio储存没什么好说的,参照文档与当前版本源码即可实现,

主要在短链的服务怎么实现稍微要讲一下,

  1. 如何实现有效短链码?

    我这里直接设置了两个策略接口,一个用来校验短链码是否合理,一个用来生成短链码。

  2. 如何储存短链码与实际储存对象的关系?

    可以设置一个关系储存接口,使用例如mongo、redis等的实现,我下面的实现是没有写这个接口,直接使用redis作为储存关系的实现。

返回VO
/**
* @auth: black tea
* @date: 2021/6/18 8:45
* @description:
*       1.0.0 版本仅涉及到地址一部分属性;
*       以下大部分属性属于1.1.0的内容(例如锁定控制,无效控制,场景唯一id等)
*       1.1.0 可以精确控制是否可以访问该资源,可以设置该对象资源的私有功能,满足部分敏感文件不可以被公共访* 问的业务等,还可以将用户已经放弃的对象资源进行释放,减少服务资源空间的浪费!
*/
public class UploadBaseVo implements Serializable {private static final long serialVersionUID = 2763738636057411330L;/** 文件原名称 -前端用于文件名称替换 **/private String fileName;/** 长链原地址 **/private String url;/** 短链地址 **/private String shortUrl;/** 是否锁定,锁定后无法进行访问 **/private boolean isLock;/** 是否无效 **/private boolean isInvalid;/** 无效枚举 **/private UploadFileConstant.UploadFileInvalidEnum invalidEnum;/** 锁定或无效原因 **/private String lockOrInvalidCause;/** 最后有效时间 **/private Date lastEffectiveTime;/** 上传的客户端类型 **/private UploadFileConstant.uploadClientType clientType;/** 场景id - 唯一 - 非必有 **/private String sceneId;/** 销毁枚举 **/private UploadFileConstant.DestroyEnum destroyEnum;/*** return true 表示超时* @param date 比较的时间* @return boolean*/public boolean isTimOut(Date date){return date.getTime() - lastEffectiveTime.getTime() > 0;}
}
上传对象文件
public MinioUploadVo upload(MultipartFile file, UploadBaseDto dto) throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, ErrorResponseException {if (dto instanceof MinioUploadDto){MinioUploadDto uploadDto = (MinioUploadDto) dto;String bucketName = uploadDto.getBucketName();if (Validator.isEmpty(bucketName)){bucketName = MinioConstant.DEFAULT_STORAGE_BUCKET;}boolean isExist = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());if (isExist) {log.info("存储桶已经存在!");} else {//创建存储桶并设置只读权限minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());SetBucketPolicyArgs setBucketPolicyArgs = SetBucketPolicyArgs.builder().bucket(bucketName).config(MinioConstant.PolicyType.READ_ONLY.toString()).build();minioClient.setBucketPolicy(setBucketPolicyArgs);}String filename = file.getOriginalFilename();// 设置存储对象名称String objectName = DateUtil.format(new Date(), "yyyyMMdd") + "/" + filename;// 使用putObject上传一个文件到存储桶中String fileContent = file.getContentType();if (file.getContentType().contains("ISO-8859-1")){fileContent = fileContent.replace("ISO-8859-1", "UTF-8");}PutObjectArgs putObjectArgs = PutObjectArgs.builder().bucket(bucketName).contentType(fileContent).object(objectName).stream(file.getInputStream(), file.getSize(), PutObjectArgs.MIN_MULTIPART_SIZE).build();ObjectWriteResponse objectWriteResponse = minioClient.putObject(putObjectArgs);log.info("文件上传成功,对象:{}", JSONUtil.toJsonStr(objectWriteResponse));MinioGetObjectDto getObjectDto = new MinioGetObjectDto();getObjectDto.setBucketName(bucketName);getObjectDto.setFileName(filename);getObjectDto.setObjectName(objectName);MinioUploadVo vo = this.getObject(getObjectDto);vo.setSceneId(dto.getSceneId());String url = vo.getShortUrl();String path = URLUtil.getPath(url);String path1 = path.substring(1, path.length());// 这里默认使用的是redis的储存短链策略redisUtils.set(UploadFileConstant.filePrefix + path1.charAt(0) + "::" + path1,vo);return vo;}else {log.error("上传失败,因为当前调用的服务(minioService),入参类型dto错误!");}return null;}
获取对象文件地址
 public MinioUploadVo getObject(UploadBaseDto dto) throws IOException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, ErrorResponseException, InternalException, InvalidKeyException {if (dto instanceof MinioGetObjectDto){MinioGetObjectDto getObjectDto = (MinioGetObjectDto) dto;String bucketName = getObjectDto.getBucketName();String objectName = getObjectDto.getObjectName();if (Validator.isEmpty(bucketName)){bucketName = MinioConstant.DEFAULT_STORAGE_BUCKET;}GetPresignedObjectUrlArgs getPresignedObjectUrlArgs = GetPresignedObjectUrlArgs.builder().method(Method.GET).bucket(bucketName).object(objectName).build();String url = minioClient.getPresignedObjectUrl(getPresignedObjectUrlArgs);getObjectDto.setUrl(url);return build(getObjectDto,new MD5Strategy(),7,null);}else {log.error("错误");}return null;}
短链服务实现

先增加两个策略接口!

1: 校验短链码是否重复接口?

@FunctionalInterface
public interface CheckShortUrlStrategy<T> {/*** 短链接地址是否重复, 重复 true* @param* @return*/boolean isRepeat(T t);}

2: 自定义生成短链码的接口?

@FunctionalInterface
public interface UrlToShortUrlStrategy {/*** 长链接转短连接* @param url 长链接* @return String*/String toShortUrl(String url, int resultLength);
}

最终调用接口实现短链服务 ↓↓↓↓

 /***  生成返回客户端的vo*/
private MinioUploadVo build(MinioGetObjectDto dto, UrlToShortUrlStrategy strategy, int length, CheckShortUrlStrategy checkShortUrlStrategy){MinioUploadVo vo = new MinioUploadVo();vo.setSceneId(dto.getSceneId());vo.setBucketName(dto.getBucketName());vo.setObjectName(dto.getObjectName());vo.setFileName(dto.getFileName());String url = dto.getUrl();vo.setUrl(url);if (null == strategy){strategy = this.defaultBuildShortUrlStrategy();}String shortUrl = new UrlTpShortUrlContext(strategy).execute(url, length);while (this.shortUrlCheck(checkShortUrlStrategy,shortUrl)){shortUrl = new UrlTpShortUrlContext(strategy).execute(url, length);}vo.setShortUrl(shortUrl);vo.setClientType(UploadFileConstant.uploadClientType.MINIO_CLIENT);return vo;}// 判断是否满足短链的策略private boolean shortUrlCheck(CheckShortUrlStrategy strategy,String shortUrl){if (null == strategy) {// 短链策略默认实现校验短链码是否重复!strategy = this.defaultCheckStrategy();}return strategy.isRepeat(shortUrl);}private CheckShortUrlStrategy<String> defaultCheckStrategy(){return url -> {String path = URLUtil.getPath(url);// 取url首位作为 :: 第二重String path1 = path.substring(1, path.length());UploadBaseVo uploadBaseVo = (UploadBaseVo) redisUtils.get(UploadFileConstant.filePrefix + path1.charAt(0) + "::" + path1);// 是否存在?return Validator.isNotNull(uploadBaseVo) && Validator.isNotEmpty(uploadBaseVo.getShortUrl());};}private UrlToShortUrlStrategy defaultBuildShortUrlStrategy(){// 默认采用随机值策略return new RandomStrategy();}

效果图

  • Minio 服务

其他的功能不做介绍,自己看下文档即可。

  • 项目图

实际短链效果 -> 访问: http://localhost/iymQvia

springboot整合minio搭建对象储存及短链服务相关推荐

  1. springboot 整合minio client 简单使用 视频流展示demo

    springboot 整合minio client 简单使用 视频流展示demo 不好意思 本人没有强迫症 代码随便造 知识来源于百度,感谢百度合作伙伴以及各位网友demo的帮助 源码:https:/ ...

  2. MinIO入门-02 SpringBoot 整合MinIO并实现文件上传

    SpringBoot 整合MinIO并实现文件上传 1.依赖 <!-- https://mvnrepository.com/artifact/io.minio/minio --> < ...

  3. springboot整合minio上传文件

    1.安装minio 这里采用docker进行安装. 搜索该镜像:docker search minio 找到了镜像:minio/minio 拉取镜像:docker pull minio/minio 启 ...

  4. SpringBoot整合——阿里云对象存储(OSS)

    SpringBoot整合--阿里云对象存储 1 OSS介绍 在开发应用的过程中,我们经常会有用户需要实名认证之后才能访问的需求. 用户认证需要上传证件图片.首页轮播也需要上传图片,因此我们要做文件服务 ...

  5. SpringBoot整合Minio,一篇带你入门使用Minio

    本文介绍SpringBoot如何整合Minio,解决文件存储问题 文章目录 前言 环境搭建 项目环境搭建 添加依赖库 yml配置 Docker安装minio 代码实现 MiniConfig servi ...

  6. springboot整合minio最新版

    第一步:查找minio最新依赖,通过maven查询网站查询,这搜索框输入minio, 也可以查看MinIO官网https://docs.min.io/docs/java-client-quicksta ...

  7. 【ReactJs+springBoot项目——租房】第6章:MongoDB入门+SpringBoot整合MongoDB+搭建微聊系统+实现微聊功能

    MongoDB入门 MongoDB的java api的使用 SpringBoot整合MongoDB使用 搭建微聊系统 实现微聊功能 分布式WebSocket解决方案分析 1.MongoDB入门 1.1 ...

  8. SpringBoot整合Shiro搭建登录注册认证授权权限项目模板

    主要内容: 1 SpringBoot整合Shiro安全框架; 2 Shiro主要学习内容总结;(执行流程.主要对象接口.注意事项等) 3 Redis实现对权限信息缓存; ! 温馨提示: 想要快速搭Sh ...

  9. springboot整合rabbitmq(搭建)

    整合 第一步创建一个springboot的项目 fanout模式 创建fanout的消费者 完整版链接点击= SpringBoot整合RabbotMq完整版 第一步创建一个springboot的项目 ...

最新文章

  1. 利用反射给JAVABEAN实例赋值
  2. Ambari中Ranger安装
  3. 如何摆脱「技术思维」的惯性?
  4. linux complete函数,Linux驱动中completion接口浅析(wait_for_complete例子,很好)
  5. javaweb基础 02--javaweb基础概念
  6. 数组实例的entries(),keys() 和 values()方法
  7. ThinkPHP5如何引用新建的配置文件?
  8. layUI提交多个相同name的值
  9. 从拉萨骑行到珠峰大本营
  10. Flutter 如何实现禁止手机横屏的功能
  11. 美国华盛顿州立大学计算机排名,2019上海软科世界一流学科排名计算机科学与工程专业排名华盛顿州立大学排名第301-400...
  12. TalkingData三大产品创新,引领2022数字营销技术新格局
  13. Linux 音频驱动(六) ALSA音频驱动之PCM Write数据传递过程
  14. 硬件蓝牙测试软件,【原创】聊聊蓝牙测试专用硬件工具-Ubertooth
  15. 4412运行java_Tiny4412 Android 启动流程
  16. html 一键复制功能以及下载功能
  17. 免费且不丢失数据的MBR转GPT软件!
  18. HTML5七夕情人节表白网页(抖音超火3D炫酷魔方) HTML+CSS+JavaScript 求婚示爱代码 520情人节告白代码 程序员表白源码 3D旋转相册 js烟花代码 css爱心表白
  19. 免费WebCamps-北美,亚洲和欧洲-*立即注册*
  20. 阿里云CentOS环境之-实战docker集群swarm(十五)

热门文章

  1. Win11左边出菜单怎么弄?Windows11开始菜单放左边怎么设置?
  2. (树形dp)Binary Apple Tree
  3. dokuwiki mysql_DokuWiki安装在Windows 上
  4. [Code Jam] Millionaire
  5. 关于SQL Server 2008R2本地服务的数据库引擎里没有实例名问题
  6. 冰箱不能制冷,过滤器冰堵问题
  7. 万水千山阻挡不了我学习
  8. 工作记录-代理服务详解
  9. win7连接wifi显示有限的访问权限,没有有效的IP配置,无法上网问题的解决办法
  10. 嵌入式 按键输入实验(修改版)