9. 资源处理

Spring Framework 提供了一个抽象,用于从文件系统 servlet 上下文和 Classpath 的 Servlet 上下文。Spring Cloud AWS 增加了对 Amazon S3 服务的支持 使用资源加载器和协议加载和写入资源。org.springframework.core.io.ResourceLoaders3spring-doc.cn

资源加载器是 context 模块的一部分,因此使用资源不需要额外的依赖项 处理支持。spring-doc.cn

9.1. 配置资源加载器

Spring Cloud AWS 不会修改默认资源加载器,除非它遇到带有 XML 命名空间元素的显式配置。 该配置由整个应用程序上下文的一个元素组成,如下所示:spring-doc.cn

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aws-context="http://www.springframework.org/schema/cloud/aws/context"
       xsi:schemaLocation="http://www.springframework.org/schema/cloud/aws/context
       http://www.springframework.org/schema/cloud/aws/context/spring-cloud-aws-context.xsd">

    <aws-context:context-credentials>
            ...
        </aws-context:context-credentials>

    <aws-context:context-resource-loader/>
</beans>

9.2. 下载文件

可以通过使用协议引用 Amazon S3 存储桶及其存储桶中的对象来完成下载文件。这 典型模式是 bucket 是全局且唯一的 bucket 名称,object 是有效对象 name 中。对象名称可以是存储桶文件夹中的文件,也可以是目录中的嵌套文件 在存储桶中。s3s3://<bucket>/<object>spring-doc.cn

下一个示例演示了如何使用资源加载器来加载不同的资源。spring-doc.cn

public class SimpleResourceLoadingBean {

    @Autowired
    private ResourceLoader resourceLoader;

    public void resourceLoadingMethod() throws IOException {
        Resource resource = this.resourceLoader.getResource("s3://myBucket/rootFile.log");
        Resource secondResource = this.resourceLoader.getResource("s3://myBucket/rootFolder/subFile");

        InputStream inputStream = resource.getInputStream();
        //read file
    }
}

9.3. 上传文件

从 Spring Framework 3.1 开始,资源加载器也可以用于上传带有接口的文件,这是接口的一个特殊化。客户可以上传文件 使用界面。下一个示例演示了使用 resource loader 上传资源。org.springframework.core.io.WritableResourceorg.springframework.core.io.ResourceLoaderWritableResourcespring-doc.cn

public class SimpleResourceLoadingBean {

    @Autowired
    private ResourceLoader resourceLoader;

    public void writeResource() throws IOException {
        Resource resource = this.resourceLoader.getResource("s3://myBucket/rootFile.log");
        WritableResource writableResource = (WritableResource) resource;
        try (OutputStream outputStream = writableResource.getOutputStream()) {
            outputStream.write("test".getBytes());
        }
    }
}

9.3.1. 上传多部分文件

Amazon S3 支持将分段上传到 在上传时增加常规吞吐量。Spring Cloud AWS 默认只使用一个线程上传文件,并且 因此不提供并行上传支持。用户可以为资源加载程序配置自定义。资源加载程序将同时将多个线程排队,以使用并行分段上传。org.springframework.core.task.TaskExecutorspring-doc.cn

使用 10 个线程上传的资源加载程序的配置如下所示spring-doc.cn

<beans ...>
  <aws-context:context-resource-loader task-executor="executor" />
  <task:executor id="executor" pool-size="10" queue-capacity="0" rejection-policy="CALLER_RUNS" />
</beans>

Spring Cloud AWS 每个线程最多消耗 5 MB(至少)内存。因此,每个并行线程都会产生 因此,堆中 5 MB 的内存占用量和线程大小 10 将占用多达 50 MB 的堆空间。Spring Cloud AWS 会尽快释放内存。此外,上面的示例显示没有配置, 因为排队的请求也会消耗内存。queue-capacityspring-doc.cn

9.3.2. 使用 TransferManager 上传

Amazon SDK 还提供了一个高级抽象,可用于上传文件,也可以使用多个线程使用 多部分功能。可以在应用程序中轻松创建 A 代码并注入已创建的预配置客户端 使用 Spring Cloud AWS 资源加载器配置。com.amazonaws.services.s3.transfer.TransferManagercom.amazonaws.services.s3.AmazonS3spring-doc.cn

此示例显示了如何使用 在应用程序内 从硬盘驱动器上传文件。transferManagerspring-doc.cn

public class SimpleResourceLoadingBean {

    @Autowired
    private AmazonS3 amazonS3;

    public void withTransferManager() {
        TransferManager transferManager = new TransferManager(this.amazonS3);
        transferManager.upload("myBucket","filename",new File("someFile"));
    }
}

9.4. 搜索资源

Spring 资源加载器还支持基于 Ant 样式的路径规范收集资源。Spring Cloud AWS 提供相同的支持来解析存储桶内甚至整个存储桶中的资源。实际的资源加载程序需要 用 Spring Cloud AWS 包装以搜索 s3 存储桶,如果是非 s3 存储桶,则资源加载器 将回退到原来的下一个示例显示了使用不同模式的资源解析。spring-doc.cn

public class SimpleResourceLoadingBean {

    private ResourcePatternResolver resourcePatternResolver;

    @Autowired
    public void setupResolver(ApplicationContext applicationContext, AmazonS3 amazonS3){
        this.resourcePatternResolver = new PathMatchingSimpleStorageResourcePatternResolver(amazonS3, applicationContext);
    }

    public void resolveAndLoad() throws IOException {
        Resource[] allTxtFilesInFolder =  this.resourcePatternResolver.getResources("s3://bucket/name/*.txt");
        Resource[] allTxtFilesInBucket =  this.resourcePatternResolver.getResources("s3://bucket/**/*.txt");
        Resource[] allTxtFilesGlobally =  this.resourcePatternResolver.getResources("s3://**/*.txt");
    }
}

解析所有存储桶中的资源可能非常耗时,具体取决于用户拥有的存储桶数量。spring-doc.cn

9.5. 使用 CloudFormation

CloudFormation 还允许在堆栈创建期间创建存储桶。这些存储桶通常具有生成的名称 必须用作存储桶名称。为了允许应用程序开发人员在其 配置,Spring Cloud AWS 支持解析生成的存储桶名称。 应用程序开发人员可以使用该接口来解析 根据逻辑名称生成的物理名称。org.springframework.cloud.aws.core.env.ResourceIdResolverspring-doc.cn

下一个示例显示了 CloudFormation 堆栈模板中的存储桶定义。将使用名称创建 Bucket 比如 integrationteststack-sampleBucket-23qysofs62tc2spring-doc.cn

{
    "Resources": {
        "sampleBucket": {
            "Type": "AWS::S3::Bucket"
        }
    }
}

应用程序开发人员可以解析该名称并使用它来加载资源,如下面的下一个示例所示。spring-doc.cn

public class SimpleResourceLoadingBean {

    private final ResourceLoader loader;
    private final ResourceIdResolver idResolver;

    @Autowired
    public SimpleResourceLoadingBean(ResourceLoader loader, ResourceIdResolver idResolver) {
        this.loader = loader;
        this.idResolver = idResolver;
    }

    public void resolveAndLoad() {
        String sampleBucketName = this.idResolver.
            resolveToPhysicalResourceId("sampleBucket");
        Resource resource = this.loader.
            getResource("s3://" + sampleBucketName + "/test");
    }
}