什么!没有Starter的阿里云OSS也能集成到SpringBoot?

实际上,我们在Maven存储库中尝试搜索阿里云OSS。在此过程中,我们会发现阿里云官方未提供一种集成Spring Boot的模式,即xxx-Springboot-Starter,显然,这是一个需要自行定制的组件。然而,如今许多企业在研发过程中,基本上90%的项目都采用了Spring Boot。因此,若有与阿里云OSS对接的需求,倘若官方已提供了相应的Spring Boot快速启动集成包,那么我们的使用将会非常便捷。然而,鉴于官方并未实施该操作,我们必须手动将其集成至Spring Boot。以下文章将为大家演示如何实现该集成。

第一步,我们需要新建一个spring boot的项目

第二步,引入阿里云OSS的包

java 复制代码
        <!-- https://mvnrepository.com/artifact/com.aliyun.oss/aliyun-sdk-oss -->
        <dependency>
            <groupId>com.aliyun.oss</groupId>
            <artifactId>aliyun-sdk-oss</artifactId>
            <version>3.17.2</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.30</version>
            <scope>provided</scope>
        </dependency>

第一个是阿里云OSS的包,第二个是lombok的包,可以不引入(根据实际情况自行引入)

第三步,新建三个软件包

分别是: config 包:存放springboot的Configuration的地方,即配置bean的地方 service: 我们业务类的业务方法存放的地方 util:封装一些阿里云OSS的api的地方

第四步,新建配置类

java 复制代码
package com.masiyi.aliyun.config;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.auth.CredentialsProviderFactory;
import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider;
import com.aliyuncs.exceptions.ClientException;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @Author masiyi
 * @Date 2024/3/15
 * @PackageName:com.masiyi.aliyun.config
 * @ClassName: AliyunConfig
 * @Description: TODO
 * @Version 1.0
 */
@Data
@Configuration
@ConfigurationProperties(prefix = "aliyun")
public class AliyunConfig {

    private String endpoint;
    private String bucketName;
    private String accessKeyId;
    private String accessKeySecret;

    @Bean
    public OSS getAliyun() {
        // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
        // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。

        // 填写Bucket名称,例如examplebucket。
        // 填写Object完整路径,例如exampledir/exampleobject.txt。Object完整路径中不能包含Bucket名称。
        return new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
    }
}

这是一个名为AliyunConfig的Java类,使用了@Data、@Configuration和@ConfigurationProperties注解。

  • @Data注解:这是Lombok库提供的注解,用于自动生成Java类的getter、setter、equals、hashCode和toString等方法。
  • @Configuration注解:表明这是一个配置类,Spring会在应用启动时加载并处理该类。
  • @ConfigurationProperties(prefix = "aliyun")注解:指定了属性配置的前缀为"aliyun",用于将配置文件中以"aliyun"开头的属性值注入到该类的对应字段中。
  • AliyunConfig类:包含了endpoint、bucketName、accessKeyId和accessKeySecret等属性,用于配置阿里云OSS服务的相关信息。
  • @Bean注解:在配置类中定义了一个名为getAliyun()的Bean方法,用于创建并返回一个OSSClient实例,用于访问阿里云OSS服务。
  • getAliyun()方法:在方法中使用了OSSClientBuilder来构建一个OSSClient实例,传入了endpoint、accessKeyId和accessKeySecret等属性值。

这个时候我们就实现了对阿里云OSS服务的配置和Bean的定义,使得应用可以方便地访问和使用阿里云OSS服务。以后使用的时候直接在业务类里面 @Autowired直接注入OSS这个类即可。

第五步,封装阿里云oss的api

java 复制代码
package com.masiyi.aliyun.util;

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.Bucket;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.OSSObjectSummary;
import com.aliyun.oss.model.ObjectListing;
import com.aliyun.oss.model.PutObjectResult;
import com.masiyi.aliyun.config.AliyunConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

/**
 * @Author masiyi
 * @Date 2024/3/15
 * @PackageName:com.masiyi.aliyun.util
 * @ClassName: AliyunUtil
 * @Description: TODO
 * @Version 1.0
 */
@Component
@Slf4j
public class AliyunUtil {
    @Autowired
    private OSS oss;


    @Autowired
    private AliyunConfig aliyunConfig;

    /**
     * 上传文件
     *
     * @param txt
     * @param objectName
     */
    public PutObjectResult putObject(String txt, String objectName) {
        try {
            return oss.putObject(aliyunConfig.getBucketName(), objectName, new ByteArrayInputStream(txt.getBytes()));
        } catch (OSSException oe) {
            log.error(oe.getMessage(),oe);
        } catch (ClientException ce) {
           log.error(ce.getMessage(),ce);
        } finally {
            if (oss != null) {
                oss.shutdown();
            }
        }
        return null;
    }

    /**
     * 上传图片
     *
     * @param inputStream
     * @param fileName
     */
    public PutObjectResult putImage(InputStream inputStream, String fileName) {

        try {
            return oss.putObject(aliyunConfig.getBucketName(), fileName, inputStream);
        } catch (OSSException oe) {
            log.error(oe.getMessage(),oe);
        } catch (ClientException ce) {
            log.error(ce.getMessage(),ce);
        } finally {
            if (oss != null) {
                oss.shutdown();
            }
        }
        return null;
    }

    /**
     * 创建存储空间。
     */
    public Bucket createBucket(String bucketName) {
        Bucket bucket = null;
        try {
            // 创建存储空间。
            bucket = oss.createBucket(bucketName);
        } catch (OSSException oe) {
            log.error(oe.getMessage(),oe);
        } catch (ClientException ce) {
            log.error(ce.getMessage(),ce);
        } finally {
            if (oss != null) {
                oss.shutdown();
            }
        }
        return bucket;
    }


    /**
     * 下载文件 以下代码用于通过流式下载方式从OSS下载文件。
     */
    public void getObject(String bucketName, String objectName) {

        try {
            // 调用ossClient.getObject返回一个OSSObject实例,该实例包含文件内容及文件元数据。
            OSSObject ossObject = oss.getObject(bucketName, objectName);
            // 调用ossObject.getObjectContent获取文件输入流,可读取此输入流获取其内容。
            InputStream content = ossObject.getObjectContent();
            if (content != null) {
                BufferedReader reader = new BufferedReader(new InputStreamReader(content));
                while (true) {
                    String line = reader.readLine();
                    if (line == null) {
                        break;
                    }
                    System.out.println("\n" + line);
                }
                // 数据读取完成后,获取的流必须关闭,否则会造成连接泄漏,导致请求无连接可用,程序无法正常工作。
                content.close();
            }
        } catch (OSSException oe) {
            log.error(oe.getMessage(),oe);
        } catch (ClientException ce) {
            log.error(ce.getMessage(),ce);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            if (oss != null) {
                oss.shutdown();
            }
        }
    }

    /**
     * 列举文件
     * 以下代码用于列举存储空间bucket下的文件。默认列举100个文件。
     *
     * @param bucketName
     * @return
     */
    public ObjectListing listObjects(String bucketName) {
        ObjectListing objectListing = null;
        try {
            // ossClient.listObjects返回ObjectListing实例,包含此次listObject请求的返回结果。
            objectListing = oss.listObjects(bucketName);
            // objectListing.getObjectSummaries获取所有文件的描述信息。
            for (OSSObjectSummary objectSummary : objectListing.getObjectSummaries()) {
                System.out.println(" - " + objectSummary.getKey() + "  " +
                        "(size = " + objectSummary.getSize() + ")");
            }
        } catch (OSSException oe) {
            log.error(oe.getMessage(),oe);
        } catch (ClientException ce) {
            log.error(ce.getMessage(),ce);
        } finally {
            if (oss != null) {
                oss.shutdown();
            }
        }
        return objectListing;
    }


    /**
     * 删除文件
     * 以下代码用于删除指定文件
     * @param bucketName
     * @param objectName
     */
    public void deleteObject(String bucketName, String objectName) {
        try {
            // 删除文件。
            oss.deleteObject(bucketName, objectName);
        } catch (OSSException oe) {
            log.error(oe.getMessage(),oe);
        } catch (ClientException ce) {
            log.error(ce.getMessage(),ce);
        } finally {
            if (oss != null) {
                oss.shutdown();
            }
        }
    }

    
}

这里最关键的两行代码就是:

java 复制代码
    @Autowired
    private OSS oss;
    @Autowired
    private AliyunConfig aliyunConfig;

其中我们引入的OSS 类是为了调用阿里云oss的api,AliyunConfig 则是我们为了使用里面的属性,而这个util里面的方法就是可以直接参考阿里云官方的文档进行一个封装,例如我们看阿里云的api文档:

java 复制代码
package com.masiyi.aliyun;

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.common.auth.CredentialsProviderFactory;
import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider;

public class Demo {

    public static void main(String[] args) throws Exception {
         // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
        String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
        // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
        // 填写Bucket名称,例如examplebucket。
        String bucketName = "examplebucket";

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);

        try {
            // 创建存储空间。
            ossClient.createBucket(bucketName);

        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }
}

其实在这一段代码中:

java 复制代码
   // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
        String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
        // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
        // 填写Bucket名称,例如examplebucket。
        String bucketName = "examplebucket";

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);

我们已经在AliyunConfig这个类里面已经配置好了基础的信息,而且我们已经把oss利用spring的ioc功能交给spring去管理了,所以我们就可以每次直接从sring的ioc容器里面直接拿来用即可。我们其实要改的只是下面实际调用的代码。所以我们只需要把这个Demo类给封装成一个方法就好了,类似上面util类里面的createBucket方法这样。

第六步,编写自己的业务类

java 复制代码
package com.masiyi.aliyun.service;

import com.masiyi.aliyun.util.AliyunUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.InputStream;

/**
 * @Author masiyi
 * @Date 2024/3/15
 * @PackageName:com.masiyi.aliyun.service
 * @ClassName: AliyunService
 * @Description: TODO
 * @Version 1.0
 */
@Service
public class AliyunService {

    @Autowired
    private AliyunUtil aliyunUtil;

    public void putObject() {
        aliyunUtil.putObject("你好", "objectName.txt");
    }

    public void putImage(InputStream inputStream, String imgName) {
        aliyunUtil.putImage(inputStream, "markdown" + imgName);
    }
}

在业务类中我们直接注入AliyunUtil 类,之后就可以愉快的使用阿里云oss了!

第七步,填写你的阿里云oss的信息

java 复制代码
spring.application.name=aliyun

aliyun.bucketName=masiyi
aliyun.endpoint=https://oss-cn-guangzhou.aliyuncs.com
aliyun.accessKeyId=LTAI5tRbBzEmyo9mosdfeqqc
aliyun.accessKeySecret=aDcdesfefa02V42TGstfAJ42Ma9

这样我们的阿里云OSS的api也就集成到SpringBoot中了。

博客中的项目地址已开源,详情查看springboot+aliyun-sdk-oss

相关推荐
渣哥几秒前
面试高频:Spring 事务传播行为的核心价值是什么?
javascript·后端·面试
调试人生的显微镜5 分钟前
iOS 代上架实战指南,从账号管理到使用 开心上架 上传IPA的完整流程
后端
本就一无所有 何惧重新开始9 分钟前
Redis技术应用
java·数据库·spring boot·redis·后端·缓存
低音钢琴22 分钟前
【SpringBoot从初学者到专家的成长11】Spring Boot中的application.properties与application.yml详解
java·spring boot·后端
越千年30 分钟前
用Go实现类似WinGet风格彩色进度条
后端
蓝色汪洋35 分钟前
string字符集
java·开发语言
卿言卿语38 分钟前
CC1-二叉树的最小深度
java·数据结构·算法·leetcode·职场和发展
淳朴小学生40 分钟前
静态代理和动态代理
后端
不太会写42 分钟前
又开始了 小程序定制
vue.js·spring boot·python·小程序
=>>漫反射=>>44 分钟前
配置的前世今生:从逻辑中抽离,又与逻辑有限融合
java·设计规范