当前位置:   article > 正文

springboot集成对象存储aws java v2_software.amazon.awssdk

software.amazon.awssdk

1、引入pom

  1. <dependency>
  2. <groupId>software.amazon.awssdk</groupId>
  3. <artifactId>s3</artifactId>
  4. <version>2.16.60</version>
  5. </dependency>

2、yml添加aws配置信息

  1. aws:
  2. accessKeyId: "8MIPOASDIOI9J45J"
  3. secretAccessKey: "dzWkljdfhjkne87+Jlkejerk7ujkjsU"
  4. endpointUrl: "https://s3.demo.com:8088"

3、增加aws初始化配置类

  1. @Configuration
  2. public class AwsS3Config {
  3. @Value("aws.accessKeyId")
  4. private String accessKeyId;
  5. @Value("aws.secretAccessKey")
  6. private String secretAccessKey;
  7. @Value("aws.endpointUrl")
  8. private String endpointUrl;
  9. private static final Region region = Region.US_EAST_1;
  10. @Bean
  11. public S3Client s3Client(){
  12. AwsBasicCredentials awsBasicCredentials = AwsBasicCredentials.create(accessKeyId, secretAccessKey);
  13. S3Configuration s3Config = S3Configuration.builder().pathStyleAccessEnabled(true).build();
  14. try{
  15. S3Client s3 = S3Client.builder()
  16. .endpointOverride(new URI(endpointUrl))
  17. .credentialsProvider(StaticCredentialsProvider.create(awsBasicCredentials))
  18. .region(region)
  19. .serviceConfiguration(s3Config)
  20. .build();
  21. return s3;
  22. } catch (URISyntaxException e){
  23. throw new RuntimeException(e.getMessage());
  24. }
  25. }
  26. @Bean
  27. public S3Presigner s3Presigner(){
  28. try{
  29. S3Configuration s3Config = S3Configuration.builder().pathStyleAccessEnabled(true).build();
  30. S3Presigner presigner = S3Presigner.builder()
  31. .endpointOverride(new URI(endpointUrl))
  32. .region(region)
  33. .build();
  34. return presigner;
  35. } catch (URISyntaxException e){
  36. throw new RuntimeException(e.getMessage());
  37. }
  38. }
  39. }

3、实现对象列表、异步对象上传、对象下载、对象删除

  1. @Resource
  2. private S3Client s3Client;
  3. @Resource
  4. private S3Presigner s3Presigner;
  5. /**
  6. * 对象列表
  7. * @param bucket bucket
  8. * @param key 对象路径
  9. * @param pageToken 下一页token
  10. * @param pageSize 分页大小
  11. */
  12. public ResultBean list(String bucket, String key, String pageToken, Integer pageSize) throws UnsupportedEncodingException {
  13. if(StringUtil.isEmpty(bucket)) return ResultUtil.resultFail("参数错误");
  14. ListObjectsV2Request.Builder builder = ListObjectsV2Request.builder();
  15. // 设置bucket
  16. builder.bucket(bucket);
  17. // 设置一次请求返回多少数据
  18. builder.maxKeys(pageSize);
  19. if(StringUtil.isNotEmpty(key)) {
  20. // 设置文件路径分隔符,用于查找
  21. builder.prefix(key).delimiter("/");
  22. }
  23. ListObjectsV2Request listObjReq = builder.build();
  24. ListObjectsV2Response listObjRes = s3Client.listObjectsV2(listObjReq);
  25. // 获取下一页数据
  26. if(listObjRes.isTruncated() && StringUtil.isNotEmpty(pageToken)){
  27. listObjReq = listObjReq.toBuilder().continuationToken(pageToken).build();
  28. listObjRes = s3Client.listObjectsV2(listObjReq);
  29. }
  30. List<S3Object> s3ObjectList = listObjRes.contents();
  31. // 获取下一页token
  32. String pageNextToken = listObjRes.nextContinuationToken();
  33. String finalPageNextToken = StringUtil.isEmpty(pageNextToken) ? "" : URLEncoder.encode(pageNextToken, "utf-8");
  34. // 重新组装为自己需要的数据格式
  35. List<AwsS3ObjectVO> s3ObjList = Lists.transform(s3ObjectList, (s3Object) -> {
  36. AwsS3ObjectVO vo = new AwsS3ObjectVO();
  37. vo.setBucket(bucket);
  38. vo.setKey(s3Object.key());
  39. vo.setSize(FileUtil.calSize(s3Object.size()));
  40. vo.setStorageClass(s3Object.storageClassAsString());
  41. vo.setLastModified(DateUtil.dataToStr(s3Object.lastModified(), "yyyy-MM-dd HH:mm:ss"));
  42. vo.setPageToken(finalPageNextToken);
  43. return vo;
  44. });
  45. return ResultUtil.resultSuccess(s3ObjList);
  46. }
  47. /**
  48. * 对象上传
  49. * @param bucket bucket
  50. * @param file 文件对象
  51. */
  52. public ResultBean upload(String bucket, MultipartFile file){
  53. if(StringUtil.isEmpty(bucket) || file.isEmpty()) return ResultUtil.resultFail("参数错误");
  54. SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
  55. String fileName = UUID.randomUUID().toString().trim().replaceAll("-", "");
  56. String filePath = sdf.format(new Date()) + "/" + fileName;
  57. try{
  58. ResultBean resultBean = singleUpload(bucket, filePath, file);
  59. if(resultBean.getCode().equals("-1")) return ResultUtil.resultFail(resultBean.getMsg());
  60. return ResultUtil.resultSuccess(filePath);
  61. } catch (Exception ex){
  62. throw new BizException(ex.getMessage(), ex);
  63. }
  64. }
  65. /**
  66. * 异步完整上传不分片
  67. * @param bucket bucket
  68. * @param key 对象路径
  69. * @param file 文件对象
  70. */
  71. @Async("awsThreadPoolExecutor")
  72. ResultBean singleUpload(String bucket, String key, MultipartFile file) throws IOException {
  73. Long startTime = System.currentTimeMillis() / 1000;
  74. PutObjectRequest putObjectRequest = PutObjectRequest.builder()
  75. .bucket(bucket)
  76. .key(key)
  77. .build();
  78. RequestBody requestBody = RequestBody.fromInputStream(file.getInputStream(), file.getSize());
  79. PutObjectResponse putObjectResponse = s3Client.putObject(putObjectRequest, requestBody);
  80. SdkHttpResponse sdkHttpResponse = putObjectResponse.sdkHttpResponse();
  81. if(!sdkHttpResponse.isSuccessful()){
  82. return ResultUtil.resultFail("上传对象存储失败, statusCode:" + sdkHttpResponse.statusCode() + "statusText:" + sdkHttpResponse.statusText());
  83. }
  84. long endTime = System.currentTimeMillis() / 1000;
  85. log.info("上传文件(" + key + ")总计耗费时间为:" + (endTime - startTime) + " 秒");
  86. return ResultUtil.resultSuccess();
  87. }
  88. /**
  89. * 对象下载,返回url下载地址
  90. * @param bucket bucket
  91. * @param key 对象路径
  92. */
  93. public ResultBean download(String bucket, String key){
  94. if(StringUtil.isEmpty(bucket) || StringUtil.isEmpty(key)) return ResultUtil.resultFail("参数错误");
  95. GetObjectRequest objectRequest = GetObjectRequest.builder().bucket(bucket).key(key).build();
  96. GetObjectPresignRequest objectPresignRequest = GetObjectPresignRequest.builder()
  97. .signatureDuration(Duration.ofMinutes(10))
  98. .getObjectRequest(objectRequest)
  99. .build();
  100. PresignedGetObjectRequest presignedGetObjectRequest = s3Presigner.presignGetObject(objectPresignRequest);
  101. String url = presignedGetObjectRequest.url().toString();
  102. return ResultUtil.resultSuccess(url);
  103. }
  104. /**
  105. * 对象删除,支持批量删除
  106. * @param bucket bucket
  107. * @param keyList 多个key组成的json数组转化成list对象
  108. */
  109. public ResultBean delete(String bucket, List<AwsS3ObjectVO> keyList){
  110. if(keyList == null || keyList.size() <= 0) return ResultUtil.resultFail("参数错误");
  111. List<ObjectIdentifier> identifierList = new ArrayList<>();
  112. for(AwsS3ObjectVO vo : keyList){
  113. identifierList.add(ObjectIdentifier.builder().key(vo.getKey()).build());
  114. }
  115. try{
  116. Delete delete = Delete.builder().objects(identifierList).build();
  117. DeleteObjectsRequest deleteObjectRequest = DeleteObjectsRequest.builder().bucket(bucket).delete(delete).build();
  118. s3Client.deleteObjects(deleteObjectRequest);
  119. return ResultUtil.resultSuccess();
  120. } catch (Exception ex){
  121. throw new BizException(ex.getMessage(), ex);
  122. }
  123. }

4、对象存储线程池配置,上传文件时用到

  1. /**
  2. * 对象存储线程池配置类
  3. */
  4. @EnableAsync
  5. @Configuration
  6. public class ThreadPoolConfig {
  7. @Bean("awsThreadPoolExecutor")
  8. public ThreadPoolTaskExecutor awsThreadPoolExecutor(){
  9. // cpu参数
  10. int cpuCount = Runtime.getRuntime().availableProcessors();
  11. ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
  12. // 核心线程数
  13. taskExecutor.setCorePoolSize(cpuCount);
  14. // 最大线程数
  15. taskExecutor.setMaxPoolSize(cpuCount * 2);
  16. // 任务队列容量
  17. taskExecutor.setQueueCapacity(128);
  18. // 空闲队列存活时间
  19. taskExecutor.setKeepAliveSeconds(20);
  20. // 线程前缀
  21. taskExecutor.setThreadNamePrefix("awsTaskExecutor-");
  22. // 拒绝策略
  23. taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
  24. // 任务完成后自动关闭线程池
  25. taskExecutor.setWaitForTasksToCompleteOnShutdown(true);
  26. // 初始化
  27. taskExecutor.initialize();
  28. return taskExecutor;
  29. }
  30. }

工具类ResultUtil、ResultBean和ResultPageInfo(分页需引入谷歌的pagehelper插件)

  1. public class ResultUtil {
  2. /**
  3. * 分页查询成功
  4. */
  5. public static <T> ResultPageInfo<T> pageSuccess(List<T> list){
  6. ResultPageInfo<T> bean = new ResultPageInfo();
  7. if(CollectionUtils.isEmpty(list)){
  8. bean.setCurrentPage(0);
  9. bean.setPageSize(0);
  10. bean.setData(list);
  11. bean.setTotalCount(0);
  12. bean.setCode("0");
  13. bean.setMsg("success");
  14. } else {
  15. PageInfo<T> page = new PageInfo<T>(list);
  16. bean.setCurrentPage(page.getPageNum());
  17. bean.setPageSize(page.getPageSize());
  18. bean.setData(page.getList());
  19. bean.setTotalCount(Integer.parseInt(page.getTotal() + ""));
  20. bean.setTotalPage(page.getPages());
  21. bean.setCode("0");
  22. bean.setMsg("success");
  23. }
  24. return bean;
  25. }
  26. /**
  27. * 操作成功
  28. */
  29. public static <T> ResultBean<T> resultSuccess(T t){
  30. ResultBean<T> resultBean = new ResultBean();
  31. resultBean.setCode("0");
  32. resultBean.setMsg("success");
  33. resultBean.setData(t);
  34. return resultBean;
  35. }
  36. /**
  37. * 操作成功
  38. */
  39. public static <T> ResultBean<T> resultSuccess(){
  40. ResultBean<T> resultBean = new ResultBean();
  41. resultBean.setCode("0");
  42. resultBean.setMsg("success");
  43. return resultBean;
  44. }
  45. /**
  46. * 操作失败
  47. */
  48. public static <T> ResultBean<T> resultFail(String errMsg){
  49. ResultBean<T> resultBean = new ResultBean();
  50. resultBean.setCode("-1");
  51. resultBean.setMsg(errMsg);
  52. return resultBean;
  53. }
  54. }
  1. @Data
  2. public class ResultBean<T> implements Serializable {
  3. private static final long serialVersionUID = 160311355525594862L;
  4. private String code = "0";
  5. private String msg = "success";
  6. private T data;
  7. }
  1. /**
  2. * 返回分页数据
  3. */
  4. @Data
  5. public class ResultPageInfo<T> implements Serializable {
  6. private static final long serialVersionUID = 160311355525522362L;
  7. private String code = "0";
  8. private String msg = "success";
  9. private List<T> data;
  10. /**
  11. * 分页页码
  12. */
  13. private Integer currentPage = 1;
  14. /**
  15. * 分页大小
  16. */
  17. private Integer pageSize;
  18. /**
  19. * 总页数
  20. */
  21. private Integer totalPage;
  22. /**
  23. * 总记录条数
  24. */
  25. private Integer totalCount;
  26. }

自定义异常类BizException

  1. /**
  2. * 业务逻辑通用异常
  3. */
  4. public class BizException extends RuntimeException {
  5. static final long serialVersionUID = -7034897190745766802L;
  6. private String errorCode;
  7. public BizException(String message) {
  8. super(message);
  9. }
  10. public BizException(String errorCode, String message) {
  11. super(message);
  12. setErrorCode(errorCode);
  13. }
  14. public BizException(String errorCode, String message, Throwable cause) {
  15. super(message, cause);
  16. setErrorCode(errorCode);
  17. }
  18. public BizException(String errorCode, Throwable cause) {
  19. super(cause);
  20. setErrorCode(errorCode);
  21. }
  22. public String getErrorCode() {
  23. return errorCode;
  24. }
  25. public void setErrorCode(String errorCode) {
  26. this.errorCode = errorCode;
  27. }
  28. }

全局异常捕捉类GlobalExceptionHandler

  1. /**
  2. * 全局异常捕捉
  3. */
  4. @Slf4j
  5. @RestControllerAdvice
  6. public class GlobalExceptionHandler {
  7. /**
  8. * 默认异常的捕捉
  9. */
  10. @ExceptionHandler({Throwable.class})
  11. public ResultBean exception(Throwable e){
  12. log.error("系统异常", e);
  13. return ResultUtil.resultFail(e.getMessage());
  14. }
  15. /**
  16. * 自定义业务异常的捕捉
  17. */
  18. @ExceptionHandler({BizException.class})
  19. public ResultBean exception(BizException e){
  20. log.error("业务异常", e);
  21. return ResultUtil.resultFail(e.getErrorCode(), e.getMessage());
  22. }
  23. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/285802
推荐阅读
相关标签
  

闽ICP备14008679号