likes
comments
collection
share

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

作者站长头像
站长
· 阅读数 6

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

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

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

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

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


        <!-- 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的包,可以不引入(根据实际情况自行引入)

第三步,新建三个软件包

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

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

第四步,新建配置类

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

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();
            }
        }
    }

    
}

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

    @Autowired
    private OSS oss;
    @Autowired
    private AliyunConfig aliyunConfig;

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

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();
            }
        }
    }
}

其实在这一段代码中:

   // 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方法这样。

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

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的信息

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

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