从Spring Boot应用中读取AWS S3对象并转换为对象列表

从Spring Boot应用中读取AWS S3对象并转换为对象列表

本文详细介绍了如何在spring Boot应用中,通过AWS SDK从S3存储桶读取包含json数据的文本文件,并将每一行JSON数据转换为Java对象,最终得到一个对象列表。文章提供了两种实现方案,一种将S3文件读取到本地文件系统再进行处理,另一种直接在内存中处理S3文件内容,并附带了完整的代码示例和配置说明,帮助开发者快速实现S3数据读取和转换的功能。

概述

在很多应用场景中,我们需要从AWS S3存储桶中读取文件,特别是那些包含结构化数据的文件,例如JSON格式。本文将演示如何使用spring boot和AWS SDK,从S3读取一个包含多行JSON对象的文本文件,并将每一行转换为Java对象,最终返回一个包含所有对象的列表。

准备工作

在开始之前,请确保你已经完成了以下准备工作:

  1. AWS账户和权限: 拥有有效的AWS账户,并配置了访问S3存储桶的权限。
  2. Spring Boot项目: 创建一个Spring Boot项目。
  3. AWS SDK依赖: 在pom.xml文件中添加AWS SDK的依赖。
<dependency>     <groupId>software.amazon.awssdk</groupId>     <artifactId>s3</artifactId>     <version>2.17.285</version> </dependency>
  1. json处理依赖: 添加Jackson依赖用于JSON序列化与反序列化
<dependency>     <groupId>com.fasterxml.jackson.core</groupId>     <artifactId>jackson-databind</artifactId>     <version>2.13.0</version> <!-- 请使用最新版本 --> </dependency>

示例数据

假设在S3存储桶中有一个名为filename.txt的文件,其内容如下:

{    "name":"rohit",    "surname":"sharma" } {    "name":"virat",    "surname":"kohli" }

创建Java对象

首先,我们需要创建一个Java类来映射JSON数据。

public class Person {     private String name;     private String surname;      public String getName() {         return name;     }      public void setName(String name) {         this.name = name;     }      public String getSurname() {         return surname;     }      public void setSurname(String surname) {         this.surname = surname;     }      @Override     public String toString() {         return "Person{" +                 "name='" + name + ''' +                 ", surname='" + surname + ''' +                 '}';     } }

配置AWS S3客户端

创建一个配置类,用于初始化AWS S3客户端。

import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; import software.amazon.awssdk.auth.credentials.StaticCredentialsprovider; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.s3.S3Client;  @Configuration public class AwsS3ClientConfig {      @Bean     public S3Client s3Client(){         AwsBasicCredentials awsBasicCredentials = AwsBasicCredentials.create("Access_KEY_ID", "SECRET_ACCESS_KEY");         return S3Client                 .builder()                 .region(Region.US_EAST_1)                 .credentialsProvider(StaticCredentialsProvider.create(awsBasicCredentials))                 .build();     } }

请确保将ACCESS_KEY_ID和SECRET_ACCESS_KEY替换为你的AWS凭证。 建议使用IAM角色或环境变量等更安全的方式管理凭证。 另外,根据你的S3存储桶所在区域设置正确的Region。

实现S3服务

接下来,我们将创建AwsS3Service类,该类负责从S3读取文件并将其转换为对象列表。

方案一:读取到本地文件

此方案首先将S3文件下载到本地文件系统,然后读取本地文件并转换为对象列表。

import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import software.amazon.awssdk.services.s3.S3Client; import software.amazon.awssdk.services.s3.model.GetObjectRequest;  import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.List;  @Service public class AwsS3Service {      private final S3Client s3Client;      @Autowired     public AwsS3Service(S3Client s3Client) {         this.s3Client = s3Client;     }       public List<Person> readFileAndCreateList(String bucketName, String keyName) throws IOException {         final Path file = readFile(bucketName, keyName);         return convertFileToList(file);     }      private Path readFile(String bucketName, String keyName) throws IOException {         GetObjectRequest getObjectRequest = GetObjectRequest                 .builder()                 .bucket(bucketName)                 .key(keyName)                 .build();          final byte[] bytes = s3Client                 .getObject(getObjectRequest)                 .readAllBytes();         final Path path = Paths.get("demo.txt");         Files.write(path, bytes);         return path;     }      private List<Person> convertFileToList(Path path) throws IOException {         final List<String> lines = Files.readAllLines(path);         StringBuilder json = new StringBuilder();         List<Person> persons=new ArrayList<>();         for (String line : lines) {             if ("{".equals(line)) {                 json = new StringBuilder("{");             } else if ("}".equals(line)) {                 json.append("}");                persons.add(new ObjectMapper()                         .readValue(json.toString(), Person.class));             } else {                 json.append(line.trim());             }         }         return persons;     } }

方案二:直接在内存中处理

此方案直接将S3文件内容读取到内存中,避免了创建本地文件的过程。

import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import software.amazon.awssdk.services.s3.S3Client; import software.amazon.awssdk.services.s3.model.GetObjectRequest;  import java.io.*; import java.util.ArrayList; import java.util.List;  @Service public class AwsS3Service {      private final S3Client s3Client;      @Autowired     public AwsS3Service(S3Client s3Client) {         this.s3Client = s3Client;     }       public List<Person> readFileAndCreateObjectList(String bucketName, String keyName) throws IOException {         final List<String> lines = readFile(bucketName, keyName);         return convertFileLinesToObjectList(lines);     }      private List<String> readFile(String bucketName, String keyName) throws IOException {         GetObjectRequest getObjectRequest = GetObjectRequest                 .builder()                 .bucket(bucketName)                 .key(keyName)                 .build();          byte[] bytes;         try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {             s3Client                     .getObject(getObjectRequest)                     .transferTo(byteArrayOutputStream);             bytes = byteArrayOutputStream.toByteArray();         }          List<String> lines=new ArrayList<>();         try(ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);             InputStreamReader inputStreamReader = new InputStreamReader(byteArrayInputStream);             BufferedReader bufferedReader=new BufferedReader(inputStreamReader)){            while (bufferedReader.ready()){               lines.add(bufferedReader.readLine());            }         }         return lines;     }      private List<Person> convertFileLinesToObjectList(List<String> lines) throws IOException {         StringBuilder json = new StringBuilder();         List<Person> persons = new ArrayList<>();         for (String line : lines) {             if ("{".equals(line)) {                 json = new StringBuilder("{");             } else if ("}".equals(line)) {                 json.append("}");                 persons.add(new ObjectMapper()                         .readValue(json.toString(), Person.class));             } else {                 json.append(line.trim());             }         }         return persons;     } }

两种方案的convertFileToList和convertFileLinesToObjectList方法都使用ObjectMapper将JSON字符串转换为Person对象。 这些方法逐行读取数据,拼接JSON字符串,并处理可能出现的异常情况。

使用示例

在Spring Boot应用的入口类中,我们可以调用AwsS3Service来读取S3文件并转换为对象列表。

import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;  import java.util.List;  @SpringBootApplication public class DemoApplication implements CommandLineRunner {      private final AwsS3Service awsS3Service;      @Autowired     public DemoApplication(AwsS3Service awsS3Service) {         this.awsS3Service = awsS3Service;     }      public static void main(String[] args) {         SpringApplication.run(DemoApplication.class);     }      @Override     public void run(String... args) throws Exception {         //KEY_NAME==filename.txt         final List<Person> peoples =                 awsS3Service                         .readFileAndCreateList("BUCKET_NAME", "KEY_NAME"); // 使用方案一         // final List<Person> peoples =         //        awsS3Service         //               .readFileAndCreateObjectList("BUCKET_NAME", "KEY_NAME"); // 使用方案二         System.out.println(peoples);     } }

请确保将BUCKET_NAME和KEY_NAME替换为你的S3存储桶名称和文件名称。

运行结果

运行Spring Boot应用后,你将在控制台中看到类似以下的输出:

[Person{name='rohit', surname='sharma'}, Person{name='virat', surname='kohli'}]

这表明我们已成功从S3读取文件并将其转换为Person对象列表。

注意事项

  • 异常处理: 在实际应用中,需要添加更完善的异常处理机制,例如处理S3连接错误、文件不存在错误和JSON解析错误等。
  • 资源释放: 确保在使用完InputStream和OutputStream后及时关闭它们,以避免资源泄漏。
  • 性能优化: 对于大型文件,可以考虑使用分块读取或异步处理等技术来提高性能。
  • 安全性: 避免在代码中硬编码AWS凭证,而是使用更安全的凭证管理方式。

总结

本文介绍了如何使用Spring Boot和AWS SDK从S3读取包含JSON数据的文本文件,并将每一行转换为Java对象,最终得到一个对象列表。 我们提供了两种实现方案,一种将S3文件读取到本地文件系统再进行处理,另一种直接在内存中处理S3文件内容。 选择哪种方案取决于你的具体需求和性能考虑。 通过本文的学习,你将能够轻松地在Spring Boot应用中实现S3数据读取和转换的功能。

© 版权声明
THE END
喜欢就支持一下吧
点赞8 分享