【苍穹外卖微服务改造】引入minio

1、需求

需求来源:

在这里插入图片描述
下面我就给大家总结一下,如何在苍穹外卖的基础上,引入minio并修改图片上传方式吧!

2、步骤分析

具体如何实现呢,分为如下几个步骤:
①导入minio的依赖
②编写配置属性
③编写配置类
④编写文件相关操作的接口
⑤实现接口,编写具体的minio文件操作逻辑代码(⭐)
⑥在springboot配置文件中引入minio的配置信息

3、如何实现

导入minio依赖

在苍穹外卖下项目中的sky-server模块的pom.xml文件下:

        <dependency>
            <groupId>io.minio</groupId>
            <artifactId>minio</artifactId>
            <version>7.1.0</version>
        </dependency>

编写配置属性类

sky-common模块下找到properties配置属性包,在这个包下面新建 MinioConfigProperties.java
在这里插入图片描述

package com.sky.properties;


import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;


@Component
@Data
@ConfigurationProperties(prefix = "minio")
public class MinioConfigProperties {

    private String accessKey;
    private String secretKey;
    private String bucket;
    private String endpoint;
    private String readPath;
}

代码解释:

@ConfigurationProperties(prefix = "minio"):指定这个类的属性将从配置文件中读取以minio为前缀的配置项进行填充。例如,类的accessKey属性将由配置文件中的minio.accessKey属性值自动填充。
String accessKey:用于存储Minio服务的访问密钥。
String secretKey:用于存储Minio服务的秘密密钥。
String bucket:指定Minio中使用的默认存储桶名称。
String endpoint:Minio服务的访问端点,通常是一个URL。
String readPath:用于访问存储在Minio存储桶中的对象的路径前缀或URL。

编写配置类

sky-server模块下的config包新建MinioConfig.java
在这里插入图片描述

package com.sky.config;

import com.sky.properties.MinioConfigProperties;
import com.sky.service.FileStorageService;
import io.minio.MinioClient;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


@Configuration
//当引入FileStorageService接口时
public class MinioConfig {

    @Autowired
    private MinioConfigProperties minIOConfigProperties;

    @Bean
    @ConditionalOnMissingBean
    public MinioClient buildMinioClient() {
        return MinioClient
                .builder()
                .credentials(minIOConfigProperties.getAccessKey(), minIOConfigProperties.getSecretKey())
                .endpoint(minIOConfigProperties.getEndpoint())
                .build();
    }
}

代码解释:

buildMinioClient() 方法构建一个 MinioClient 对象,用于操作 Minio 服务。它使用从MinioConfigProperties 获取的配置数据(如访问密钥、秘密密钥和端点)来构建客户端实例

编写接口

sky-server模块下的service包新建FileStorageService.java

package com.sky.service;

import java.io.InputStream;

/**
 * @author 逐梦苍穹
 */
public interface FileStorageService {


    /**
     *  上传图片文件
     * @param prefix  文件前缀
     * @param filename  文件名
     * @param inputStream 文件流
     * @return  文件全路径
     */
    String uploadImgFile(String prefix, String filename,InputStream inputStream);

    /**
     *  上传html文件
     * @param prefix  文件前缀
     * @param filename   文件名
     * @param inputStream  文件流
     * @return  文件全路径
     */
    String uploadHtmlFile(String prefix, String filename,InputStream inputStream);

    /**
     * 删除文件
     * @param pathUrl  文件全路径
     */
    void delete(String pathUrl);

    /**
     * 下载文件
     * @param pathUrl  文件全路径
     * @return
     *
     */
    byte[]  downLoadFile(String pathUrl);

}

编写实现类

sky-server模块下的service包下的impl包新建MinioFileStorageService.java实现FileStorageService接口:

package com.sky.service.impl;


import com.sky.properties.MinioConfigProperties;
import com.sky.service.FileStorageService;
import io.minio.GetObjectArgs;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.RemoveObjectArgs;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;

@Service
@Slf4j
public class MinioFileStorageService implements FileStorageService {

    @Autowired
    private MinioClient minioClient;

    @Autowired
    private MinioConfigProperties minIOConfigProperties;

    private final static String separator = "/";

    /**
     * @param dirPath
     * @param filename  yyyy/mm/dd/file.jpg
     * @return
     */
    public String builderFilePath(String dirPath,String filename) {
        StringBuilder stringBuilder = new StringBuilder(50);
        if(!StringUtils.isEmpty(dirPath)){
            stringBuilder.append(dirPath).append(separator);
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
        String todayStr = sdf.format(new Date());
        stringBuilder.append(todayStr).append(separator);
        stringBuilder.append(filename);
        return stringBuilder.toString();
    }

    /**
     *  上传图片文件
     * @param prefix  文件前缀
     * @param filename  文件名
     * @param inputStream 文件流
     * @return  文件全路径
     */
    @Override
    public String uploadImgFile(String prefix, String filename,InputStream inputStream) {
        String filePath = builderFilePath(prefix, filename);
        try {
            PutObjectArgs putObjectArgs = PutObjectArgs.builder()
                    .object(filePath)
                    .contentType("image/jpg")
                    .bucket(minIOConfigProperties.getBucket()).stream(inputStream,inputStream.available(),-1)
                    .build();
            minioClient.putObject(putObjectArgs);
            StringBuilder urlPath = new StringBuilder(minIOConfigProperties.getReadPath());
            urlPath.append(separator+minIOConfigProperties.getBucket());
            urlPath.append(separator);
            urlPath.append(filePath);
            return urlPath.toString();
        }catch (Exception ex){
            log.error("minio put file error.",ex);
            throw new RuntimeException("上传文件失败");
        }
    }

    /**
     *  上传html文件
     * @param prefix  文件前缀
     * @param filename   文件名
     * @param inputStream  文件流
     * @return  文件全路径
     */
    @Override
    public String uploadHtmlFile(String prefix, String filename,InputStream inputStream) {
        String filePath = builderFilePath(prefix, filename);
        try {
            PutObjectArgs putObjectArgs = PutObjectArgs.builder()
                    .object(filePath)
                    .contentType("text/html")
                    .bucket(minIOConfigProperties.getBucket()).stream(inputStream,inputStream.available(),-1)
                    .build();
            minioClient.putObject(putObjectArgs);
            StringBuilder urlPath = new StringBuilder(minIOConfigProperties.getReadPath());
            urlPath.append(separator+minIOConfigProperties.getBucket());
            urlPath.append(separator);
            urlPath.append(filePath);
            return urlPath.toString();
        }catch (Exception ex){
            log.error("minio put file error.",ex);
            ex.printStackTrace();
            throw new RuntimeException("上传文件失败");
        }
    }

    /**
     * 删除文件
     * @param pathUrl  文件全路径
     */
    @Override
    public void delete(String pathUrl) {
        // 去掉URL前缀, 剩下的就是桶和路径的组合
        String key = pathUrl.replace(minIOConfigProperties.getEndpoint()+"/","");
        int index = key.indexOf(separator);
        String bucket = key.substring(0,index);
        String filePath = key.substring(index+1);
        // 删除Objects
        RemoveObjectArgs removeObjectArgs = RemoveObjectArgs.builder().bucket(bucket).object(filePath).build();
        try {
            minioClient.removeObject(removeObjectArgs);
        } catch (Exception e) {
            log.error("minio remove file error.  pathUrl:{}",pathUrl);
            e.printStackTrace();
        }
    }


    /**
     * 下载文件
     * @param pathUrl  文件全路径
     * @return  文件流
     *
     */
    @Override
    public byte[] downLoadFile(String pathUrl)  {
        String key = pathUrl.replace(minIOConfigProperties.getEndpoint()+"/","");
        int index = key.indexOf(separator);
        String bucket = key.substring(0,index);
        String filePath = key.substring(index+1);
        InputStream inputStream = null;
        try {
            inputStream = minioClient.getObject(GetObjectArgs.builder().bucket(minIOConfigProperties.getBucket()).object(filePath).build());
        } catch (Exception e) {
            log.error("minio down file error.  pathUrl:{}",pathUrl);
            e.printStackTrace();
        }

        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        byte[] buff = new byte[100];
        int rc = 0;
        while (true) {
            try {
                if (!((rc = inputStream.read(buff, 0, 100)) > 0)) {
                    break;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            byteArrayOutputStream.write(buff, 0, rc);
        }
        return byteArrayOutputStream.toByteArray();
    }
}

代码解释:

builderFilePath 方法:
功能:构建文件在Minio中的存储路径,包括可选的目录路径、日期子目录和文件名。
参数:
dirPath:目录路径前缀,可以为空。
filename:文件名,会按日期(年/月/日)进行子目录划分。
返回:完整的文件路径。

uploadImgFile 和 uploadHtmlFile 方法:

功能:上传文件到Minio。两个方法的逻辑类似,不同之处在于设置的 contentType。
参数: prefix:上传文件的前缀路径。
filename:文件名
inputStream:文件数据流
返回:上传文件后在Minio中可访问的URL路径。

delete 方法:

功能:从Minio删除指定的文件
参数: pathUrl:文件的全路径URL,方法内部会解析出存储桶和文件路径进行删除

downLoadFile 方法:
功能:从Minio下载文件,返回文件数据的字节数组
参数:pathUrl:文件的全路径URL,方法内部同样解析出存储桶和文件路径进行操作
返回:下载文件的字节数据

配置application.yml

minio:
  accessKey: minio
  secretKey: minio123
  bucket: leadnews
  endpoint: http://192.168.42.130:9000
  readPath: http://192.168.42.130:9000

记得替换为你部署minio服务的ip地址和对应端口🌹

4、其他实现:自定义stater

除了按照上面的方式集成到项目中,还有一个更为优雅的方法,就是将整个minio服务,集成为一个自定义的stater,供调用者导入,如下:
在这里插入图片描述
使用的时候只需导入maven依赖即可:

<dependencies>
	<dependency>
		<groupId>com.xzl</groupId>
		<artifactId>xzl-file-starter</artifactId>
		<version>1.0-SNAPSHOT</version>
	</dependency>
</dependencies>

使用层面上,在注解的标记上略有区别,下面我就只展现对应类的注解标记,其他的代码都是跟上面一致的:
MinioConfig:

@Data
@Configuration
@EnableConfigurationProperties({MinioConfigProperties.class})
@ConditionalOnClass(FileStorageService.class)

MinioConfigProperties:

@Data
@ConfigurationProperties(prefix = “minio”)

MinioFileStorageService:

@Slf4j
@EnableConfigurationProperties(MinioConfigProperties.class)
@Import(MinioConfig.class)

最重要的是:spring.factories

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  com.xzl.file.service.impl.MinioFileStorageService

5、总结

想引入微服务技术来改造单体项目,基本上都是这个流程
无非就是不同的服务有不同的配置方式和实现方式🌹

最后,原创不易,欢迎各位批评指点🌹

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

逐梦苍穹

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值