首先我们先改一下上一次创建好的子项目里的application文件,其中分别改一下对应的application的名字,以便后面介绍SpringCloud的时候Nacos注册名字方便寻找到子项目,还需要修改端口,其中端口修改分别如下:
api:9009 users:9008 image:9007 gateway:88 audit:9001(gateway和audit后面会介绍到,可以先按照之前的先创建好)
先介绍一下各个注解:
@Controller:返回给前端的内容是视图
@ResponseBody:将方法或者接口返回的数据渲染成JSON
@RestController:相当于@Controller+@ResponseBody,一般在类上注释了@RestController则就直接说明返回给前端的内容是JSON形式的,而如果只是单独需要某个方法返回JSON则可以接口注释@Controller而具体某个方法上注释@ResponseBody
@RequestParam:表示接受对应的请求里需要带有单个参数
@RequestBody:表示接受对应的请求里需要带有请求体
接下来在在cloud-photo-users项目里的UserController进行接口测试
1.先创建一个common包导入下面代码,作用是把返回的数据封装一下
BaseErrorInfo
package com.cloud.photo.users.common;
/**
* 自定义描述错误接口
* @author linzsh
*/
public interface BaseErrorInfo {
/**
* 错误码
* @return 错误码
*/
Integer getResultCode();
/**
* 错误描述
* @return 错误描述
*/
String getResultMsg();
}
CommonEnum:封装常用的自定义错误枚举类
package com.cloud.photo.users.common;
/**
* 自定义错误枚举类
* @author linzsh
*/
public enum CommonEnum implements BaseErrorInfo {
//success
SUCCESS(200, "成功!"),
//error
INTERNAL_SERVER_ERROR(90500, "服务器内部错误!"),
SAVE_ERROR(90401, "插入失败!"),
LOGIN_INFO_IS_NULL(90400, "登录信息为空!"),
USERNAME_PASSWORD_ERROR(90400, "请检查账密是否正确!"),
PHONE_IS_NULL(90400, "手机号不能为空!"),
PHONE_IS_NOT_VALID(90400, "手机号不合法!"),
FILE_LIST_IS_NULL(90400, "上传的文件列表未空!"),
TRANS_IS_NULL(90404, "传输列表为空!"),
LOGIN_FAIL(90400, "登录失败!"),
USER_INFO_NOT_INPUT(90401, "你是第一次登录, 请补全用户信息!"),
NO_LOGIN(90402, "您未登录!"),
USER_IS_NULL(90404, "用户信息不存在!"),
UNAUTHORIZED_CODE(90402,"登录Token过期,请重新登陆!"),
NO_PERMISSION_CODE(90406, "没有权限进行此操作!"),
FILE_NOT_UPLOADED(90407, "文件未上传!"),
FILE_UPLOADED_ERROR(90408, "文件上传出错!"),
NO_UPLOAD_FILE(90409, "没有获取到传输列表!"),
;
//数据操作错误定义
/** 错误码 */
private final Integer resultCode;
/** 错误描述 */
private final String resultMsg;
CommonEnum(Integer resultCode, String resultMsg) {
this.resultCode = resultCode;
this.resultMsg = resultMsg;
}
@Override
public Integer getResultCode() {
return this.resultCode;
}
@Override
public String getResultMsg() {
return this.resultMsg;
}
}
ResultBody:封装数据体
package com.cloud.photo.users.common;
import com.alibaba.fastjson.JSONObject;
import lombok.Data;
/**
* 业务响应体
*
* @author linzsh
*/
@Data
public class ResultBody {
/**
* 响应业务代码
*/
private Integer code;
/**
* 响应消息
*/
private String message;
/**
* 响应结果
*/
private Object data;
/**
* 请求ID
*/
private String requestId;
public ResultBody() {
}
public ResultBody(BaseErrorInfo errorInfo) {
this.code = errorInfo.getResultCode();
this.message = errorInfo.getResultMsg();
}
/**
* 返回默认成功
*
* @return ResultBody
*/
public static ResultBody success() {
return success(null, CommonEnum.SUCCESS);
}
/**
* 成功
*
* @param data 数据响应体
* @return ResultBody
*/
public static ResultBody success(Object data,String requestId) {
ResultBody rb = new ResultBody();
rb.setCode(CommonEnum.SUCCESS.getResultCode());
rb.setMessage(CommonEnum.SUCCESS.getResultMsg());
rb.setData(data);
rb.setRequestId(requestId);
return rb;
}
/**
* 成功
*
* @param data 数据响应体
* @return ResultBody
*/
public static ResultBody success(Object data) {
ResultBody rb = new ResultBody();
rb.setCode(CommonEnum.SUCCESS.getResultCode());
rb.setMessage(CommonEnum.SUCCESS.getResultMsg());
rb.setData(data);
return rb;
}
/**
* 成功
*
* @param data 数据体
* @param errorInfo 一个业务状态枚举
* @return ResultBody
*/
public static ResultBody success(Object data, BaseErrorInfo errorInfo) {
ResultBody rb = new ResultBody();
if (errorInfo == null) {
rb.setCode(CommonEnum.SUCCESS.getResultCode());
rb.setMessage(CommonEnum.SUCCESS.getResultMsg());
} else {
rb.setCode(errorInfo.getResultCode());
rb.setMessage(errorInfo.getResultMsg());
}
rb.setData(data);
return rb;
}
/**
* 失败
* @param errorInfo 状态信息
* @return ResultBody
*/
public static ResultBody error(BaseErrorInfo errorInfo) {
ResultBody rb = new ResultBody();
rb.setCode(errorInfo.getResultCode());
rb.setMessage(errorInfo.getResultMsg());
rb.setData(null);
return rb;
}
/**
* 失败
* @param code 状态码
* @param message 状态描述
* @return ResultBody
*/
public static ResultBody error(Integer code, String message,String requestId) {
ResultBody rb = new ResultBody();
rb.setCode(code);
rb.setMessage(message);
rb.setData(null);
rb.setRequestId(requestId);
return rb;
}
/**
* 失败
* @param message 状态描述
* @return ResultBody
*/
public static ResultBody error(String message) {
ResultBody rb = new ResultBody();
rb.setCode(CommonEnum.INTERNAL_SERVER_ERROR.getResultCode());
rb.setMessage(message);
rb.setData(null);
return rb;
}
/**
* 失败
* @param code 状态码
* @param message 状态描述
* @return ResultBody
*/
public static ResultBody error(Integer code, String message) {
ResultBody rb = new ResultBody();
rb.setCode(code);
rb.setMessage(message);
rb.setData(null);
return rb;
}
@Override
public String toString() {
return JSONObject.toJSONString(this);
}
}
2.写一个getUserInfo方法用来返回用户的手机信息
package com.cloud.photo.users.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.cloud.photo.users.common.CommonEnum;
import com.cloud.photo.users.common.ResultBody;
import com.cloud.photo.users.entity.User;
import com.cloud.photo.users.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.stereotype.Controller;
/**
*
* 前端控制器
*
*
* @author ltao
* @since 2023-07-09
*/
@RestController
@RequestMapping("/users")
@Slf4j
public class UserController {
@Autowired
private UserService userService;
/**
* 获得用户信息,根据用户手机获取用户信息
* @param phone
* @return resultBody
*/
@GetMapping("/getUserInfo")
public ResultBody getUserInfo(@RequestParam(value = "phone") String phone){
log.info("getUserInfo-phone"+ phone + ",start!");
User user = userService.getOne(new QueryWrapper().eq("phone",phone));
log.info("getUserInfo()-phone=" + phone + ",user=" + user);
ResultBody resultBody = (user == null ) ? ResultBody.error(CommonEnum.USER_IS_NULL) : ResultBody.success(user);
log.info("getUserInfo()-phone=" + phone + ",resultBody=" + resultBody);
return resultBody;
}
/**
* 添加用户
* @param user 需要一个请求体,发送请求的时候可以根据User来构造一个
* @return
*/
@PostMapping("/addUser")
public ResultBody addUser(@RequestBody User user){
boolean result = userService.save(user);
return result ? ResultBody.success() : ResultBody.error(CommonEnum.SAVE_ERROR);
}
}
3.用postman或者自己选用其他方法进行测试接口
3.1先根据User的数据类型插入一条信息,根据User结果编写json的请求体
可以看到插入成功
注意:中途我出现了 mybatis-plus出现Invalid bound statement (not found) com.atguigu.admin.service.UserService.getBaseMappe的报错
解决:这里的MapperScan要详细,不能是.*这样泛
3.2 接下来测试查询方法
成功发送后可以看到
Nacos在微服务中的作用是
官网地址:Nacos 快速开始
下载地址:Releases · alibaba/nacos (github.com)
找到自己想要的版本 (官方推荐2.1.1,但具体看当时的官方文档推荐)
nacos.core.auth.enabled=true
nacos.core.auth.server.identity.key=nacos
nacos.core.auth.server.identity.value=nacos
nacos.core.auth.plugin.nacos.token.secret.key=CloudPhoto0123456789012345678901234567890123 45678901234567890123456789
startup.cmd -m standalone
修改集群变成单机
在bin
文件夹下,修改startup.cmd
里面的内容 ,找到set MODE="cluster"
,替换为set MODE="standalone"
,原来默认的是集群,现在修改为单机模式
4.复制 给出的网页然后复制粘贴到浏览器去访问,成功则会出现下面界面
5.在IDEA里集成nacos
导入依赖
com.alibaba.nacos
nacos-client
2.1.1
com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-discovery
com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-config
yml配置 ,addr要根据启动后的nacos再来修改
nacos:
discovery:
username: nacos
password: nacos
server-addr: 127.0.0.1:8848
要记得也要去启动类的上面配置@EnableDiscoveryClient注解
启动过程这里会有一个红色的报错可以不用去理会他,因为服务一启动就会去nacos读配置,但如果没有数据的话回去微服务里的yml中寻找配置信息。
如果启动的过程遇到了以下的报错可以在application name下面配置下面信息,意思是把web-application-type这个不启动,因为现在是发生了冲突
项目启动成功后去nacos查看相关微服务已经被我们注册上来了
接下来把其他服务也启动然后注册进来
6.关闭(Windows下),意思就是直接关闭cmd窗口也可以
cmd shutdown.cmd
1.pom添加依赖
org.springframework.cloud
spring-cloud-starter-openfeign
2.1.3.RELEASE
2.在启动类上加入注解,表示feign接口扫描,
@EnableFeignClients(basePackages = {"com.cloud.photo.api.feign"})
3.测试
接下来在api项目中调用user服务中查询客户信息的测试。
大致流程思路:
3.1.在api子项目中创建一个接口类Api2UserFeginService,并在类上注释@FeignClient("cloud-photo-user"),表示这个调用了这个接口类的方法后就要去该cloud-photo-user项目下去寻找对应的方法具体实现,就像调用本地方法一样
3.2然后再编写一个Api2UserController,这是一个专属于Controller的方法,通过专属的api然后在里面调用 Api2UserFegin,Api2UserFegin再去寻找user子项目中具体的方法
3.3同时在api项目的application.yml文件里配置上,Feign的负载均衡底层用的就是Ribbon,所以这里的请求超时配置其实就是配置Ribbon
# feign 超时配置
feign:
client:
config:
default:
# 超时设置 30 秒超时
connectTimeout: 30000 #请求连接超时时间
readTimeout: 30000 #请求处理的超时时间
3.4启动nacos,和启动其他服务,将服务注册到nacos上,再打开redis。这里我只启动了users和api服务,然后发送请求
发送成功后结果如下:
总体思路:在一个服务如api想调用另一个服务如users时候要通过nacos先把服务注册到一个类似通讯录的地方然后通过fegin进行转发。如在api中写一个api/getUserInfo的Controller,再写一个fegin接口,里面调用user的接口进行转发,然后请求发到api上的时候再通过fegin把请求丢给user去处理
注意!!!!!:
1.报错:No qualifying bean of type ‘org.springframework.boot.autoconfigure.http.HttpMessageConverters‘ available
No qualifying bean of type ‘org.springframework.boot.autoconfigure.http.HttpMessageConverters‘ avail_kkoneone11的博客-CSDN博客
2.报错:Could not autowire. No beans of ‘Api2UserFegin‘ type found
使用feign调用的时候出现Could not autowire. No beans of ‘Api2UserFegin‘ type found报错_kkoneone11的博客-CSDN博客
Api2UserFegin
package com.cloud.photo.api.feign;
import com.cloud.photo.api.common.ResultBody;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
/**
* @Author:kkoneone11
* @name:Api2UserFeginService
* @Date:2023/7/12 10:53
*/
/**
* @FeignClient 表明要去寻找的项目的名字
*/
@FeignClient("cloud-photo-users")
@RequestMapping("/users")
public interface Api2UserFegin {
/**
* 调用use服务下的接口,注意接口调用要对应到具体的方法
* @param phone
* @return
*/
@GetMapping("/getUserInfo")
ResultBody getUserInfo(@RequestParam(value = "phone") String phone);
}
Api2UserController
package com.cloud.photo.api.controller;
import com.cloud.photo.api.common.ResultBody;
import com.cloud.photo.api.feign.Api2UserFegin;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* @Author:kkoneone11
* @name:Api2UserController
* @Date:2023/7/12 10:53
*/
/**
* 通过"/api/getUserInfo"路径去访问Api2UserController
*/
@RestController
@Slf4j
@RequestMapping("/api")
public class Api2UserController {
@Autowired
private Api2UserFegin api2UserFegin;
@GetMapping("/getUserInfo")
public ResultBody getUserInfo(@RequestParam(value = "phone") String phone){
log.info("getUserInfo() - phone =" + phone + ",start!");
//使用fegin调用
ResultBody resultBody = api2UserFegin.getUserInfo(phone);
log.info("getUserInfo() - phone" + phone + ",resultBody" + resultBody);
return resultBody;
}
}
通过gateway将请求
1.相关配置
1.1导入依赖
org.springframework.cloud
spring-cloud-starter-gateway
1.2SpringCloudGateway的yml配置
解析一下gateway中第一段id的含义:
这里执行顺序是:当发送一个请求过来的时候断言拦截到,然后交给filter处理完再丢回给uri
spring:
cloud:
# 网关配置
gateway:
routes:
# 高优先级路由放前面
- id: api_route
uri: lb://cloud-photo-api
predicates:
- Path=/api/**
# localhost:88/api/** --> localhost:10000/**
filters:
# - RewritePath=/api/(?/?.*), /$\{segement}
- id: audit_route
uri: lb://cloud-photo-audit
predicates:
- Path=/audit/**
# localhost:88/audit/** --> localhost:10000/**
filters:
- RewritePath=/audit/(?/?.*), /$\{segement}
# nacos config
nacos:
discovery:
username: nacos
password: nacos
server-addr: 192.168.252.1:8848
redis:
host: 127.0.0.1
port: 6379
application:
name: cloud-photo-gateway
main:
web-application-type: reactive
datasource:
url: jdbc:mysql://localhost:3306/photo?useSSL=false&characterEncoding=UTF-8&allowPublicKeyRetrieval=true
username: root
password: 1234
driver-class-name: com.mysql.jdbc.Driver
kafka:
bootstrap-servers: 127.0.0.1:9092
producer: # producer 生产者
retries: 0 # 重试次数
acks: 1 # 应答级别:多少个分区副本备份完成时向生产者发送ack确认(可选0、1、all/-1)
batch-size: 16384 # 批量大小
buffer-memory: 33554432 # 生产端缓冲区大小
key-serializer: org.apache.kafka.common.serialization.StringSerializer
value-serializer: org.apache.kafka.common.serialization.StringSerializer
consumer: # consumer消费者
group-id: javagroup # 默认的消费组ID
enable-auto-commit: true # 是否自动提交offset
auto-commit-interval: 100 # 提交offset延时(接收到消息后多久提交offset)
# earliest:当各分区下有已提交的offset时,从提交的offset开始消费;无提交的offset时,从头开始消费
# latest:当各分区下有已提交的offset时,从提交的offset开始消费;无提交的offset时,消费新产生的该分区下的数据
# none:topic各分区都存在已提交的offset时,从offset后开始消费;只要有一个分区不存在已提交的offset,则抛出异常
auto-offset-reset: latest
key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
value-deserializer: org.apache.kafka.common.serialization.StringDeserializer
#服务端口
server:
port: 88
1.3.MyCorsConfiguration跨域类
package com.photo.gateway.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
/**
* 跨域配置
* @author linzsh
*/
@Configuration
public class MyCorsConfiguration {
@Bean
public CorsWebFilter corsWebFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration corsConfiguration = new CorsConfiguration();
//1、配置跨域
//允许哪些请求头头进行跨域
corsConfiguration.addAllowedHeader("*");
//允许哪些请求方式进行跨域
corsConfiguration.addAllowedMethod("*");
//允许哪些请求来源进行跨域
corsConfiguration.addAllowedOrigin("*");
//允许携带cookies
corsConfiguration.setAllowCredentials(true);
source.registerCorsConfiguration("/**", corsConfiguration);
return new CorsWebFilter(source);
}
}
2.测试
2.1启动gateway主类确保都在nacos注册了
2.2往网关里发一条请求,使请求远程调用user中的getUserInfo。这里是发送了一条http://localhost:88/api/getUserInfo?phone=123456
请求 http://localhost:88/api/getUserInfo?phone=123456,进入网关后在断言处判断,然后通过filter变成localhost:9009/getUserInfo再丢给了api服务中去处理,而Api2UserController接受到之后又调用了fegin进行请求转发到user中去调用对应Controller处理
介绍:
1.配置
1.1hutool工具类导入依赖,如果用的阿里云的话version可能不用这么高,不然导入不成功
cn.hutool
hutool-all
5.7.4
com.amazonaws
aws-java-sdk-core
1.12.487
com.amazonaws
aws-java-sdk-s3
1.12.487
1.2导入S3Util工具类
按照自己的实际情况修改
package com.cloud.photo.api.utils;
import cn.hutool.core.codec.Base64;
import com.alibaba.fastjson.JSONObject;
import com.amazonaws.HttpMethod;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.client.builder.AwsClientBuilder;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.*;
import org.apache.commons.lang.StringUtils;
import org.apache.tomcat.util.buf.HexUtils;
import java.io.*;
import java.net.URL;
import java.net.URLEncoder;
import java.util.*;
import static org.bouncycastle.asn1.x500.style.RFC4519Style.cn;
public class S3Util {
//本地minio或者华为云的账号密码
private static String accessKey = "minioadmin";
private static String secretKey = "minioadmin";
private static String bucketName = "cloud-photo";
//本地minio或者华为云的连接
private static String serviceEndpoint = "http://127.0.0.1:9000";
private static String containerId = "10001";
/**
* 获取上传地址
* @param suffixName
* @param fileMd5
* @return
*/
public static String getPutUploadUrl(String suffixName,String fileMd5) {
//链接过期时间
Date expiration = new Date();
long expTimeMillis = expiration.getTime();
expTimeMillis += 1000 * 60 * 10;
expiration.setTime(expTimeMillis);
String objectId = UUID.randomUUID().toString().replaceAll("-","");
String base64Md5 = "";
if(StringUtils.isNotBlank(suffixName)){
objectId = objectId +"." + suffixName;
}
//建立S3客户端,获取上传地址
AmazonS3 s3Client = getAmazonS3Client();
GeneratePresignedUrlRequest generatePresignedUrlRequest =
new GeneratePresignedUrlRequest(bucketName, objectId)
.withMethod(HttpMethod.PUT)
.withExpiration(expiration);
if(StringUtils.isNotBlank(fileMd5)){
base64Md5= Base64.encode(HexUtils.fromHexString(fileMd5));
generatePresignedUrlRequest = generatePresignedUrlRequest.withContentMd5(base64Md5);
}
URL url = s3Client.generatePresignedUrl(generatePresignedUrlRequest);
JSONObject jsonObject =new JSONObject();
jsonObject.put("objectId",objectId);
jsonObject.put("url",url);
jsonObject.put("containerId",containerId);
jsonObject.put("base64Md5",base64Md5);
return jsonObject.toJSONString();
}
/**
* 获取文件资源池信息
* @param objectId
* @return
*/
public static S3ObjectSummary getObjectInfo(String objectId){
AmazonS3 s3Client = getAmazonS3Client();
ListObjectsV2Request listObjectsRequest = new ListObjectsV2Request()
.withBucketName(bucketName)
.withPrefix(objectId);
ListObjectsV2Result listing = s3Client.listObjectsV2(listObjectsRequest);
List s3ObjectSummarieList = listing.getObjectSummaries();
if(s3ObjectSummarieList!=null && s3ObjectSummarieList.size()>0){
return s3ObjectSummarieList.get(0);
}
return null;
}
public static String getDownloadUrl(String containerId, String objectId){
return getDownloadUrl(containerId, objectId,null);
}
public static String getDownloadUrl(String containerId, String objectId,String filename) {
AmazonS3 s3Client = getAmazonS3Client();
GeneratePresignedUrlRequest httpRequest = new GeneratePresignedUrlRequest(bucketName, objectId);
//设置过期时间
Date expiration = new Date();
long expTimeMillis = expiration.getTime();
expTimeMillis += 1000 * 60 * 10;
expiration.setTime(expTimeMillis);
httpRequest.setExpiration(expiration);
if(StringUtils.isNotBlank(filename)){
String responseContentDisposition = null;
try {
responseContentDisposition = "attachment;filename=" + URLEncoder.encode(filename, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
httpRequest.addRequestParameter("response-content-disposition", responseContentDisposition);
}
return s3Client.generatePresignedUrl(httpRequest).toString();
}
private static AmazonS3 getAmazonS3Client(){
AwsClientBuilder.EndpointConfiguration endpointConfiguration =new AwsClientBuilder.EndpointConfiguration(serviceEndpoint,"");
AWSCredentials awsCredentials = new BasicAWSCredentials(accessKey, secretKey);
AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
.withCredentials(new ProfileCredentialsProvider())
.withCredentials(new AWSStaticCredentialsProvider(awsCredentials))
.withEndpointConfiguration(endpointConfiguration)
.build();
return s3Client;
}
/**
* 查询桶列表
*/
public static void getBuckets() {
AmazonS3 s3Client = getAmazonS3Client();
List bucketList = s3Client.listBuckets();
for (int i = 0; i < bucketList.size(); i++) {
System.out.println(bucketList.get(i).getName());
}
}
/**
* 查询桶的文件
*/
public static void listObjects() {
AmazonS3 s3Client = getAmazonS3Client();
ListObjectsRequest listObjectRequest = new ListObjectsRequest();
ObjectListing objectListing = null;
listObjectRequest.setBucketName(bucketName);
// listObjectRequest.setPrefix("DATALAKE/LF02/");
int j=0;
int num =0;
do {
objectListing = s3Client.listObjects(listObjectRequest);
List s3ObjectSummaries = objectListing.getObjectSummaries();
if (s3ObjectSummaries != null && s3ObjectSummaries.size() > 0) {
for (int i = 0; i < s3ObjectSummaries.size(); i++) {
num =j*1000+i;
System.out.println(num+"|"+j+"|"+i + "|" + s3ObjectSummaries.get(i).getKey() + "|" + s3ObjectSummaries.get(i).getETag());
}
}
j++;
listObjectRequest.setMarker(objectListing.getNextMarker());
} while (objectListing.isTruncated());
}
/**
* 生成下载地址
*/
public static void genDownloadUrl (){
AmazonS3 s3Client = getAmazonS3Client();
//华为obs存储文件路径
String key = "123.jpg";
//一小时后
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.HOUR,1);
Date expiration = calendar.getTime();
//生成下载地址
URL url = s3Client.generatePresignedUrl(bucketName,key,expiration);
String downloadUrl = url.getProtocol()+"://"+url.getHost()+":9000"+url.getFile();
System.out.println(downloadUrl);
}
/**
* 一次上传
*/
public static void putObjectTest(){
AmazonS3 s3Client = getAmazonS3Client();
String key = "12345789.jpg";
File file = new File("D:/peixun/img/123.jpg");
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName,key,file);
s3Client.putObject(putObjectRequest);
System.out.println("putObjectTest success + src="+file.getName()+",obs dest ="+key);
}
/**
* 分片上传
*/
public static void multiPut() {
AmazonS3 s3Client = getAmazonS3Client();
//初始化上传
String key = "33333";
InitiateMultipartUploadRequest initiateMultipartUploadRequest = new InitiateMultipartUploadRequest(bucketName,key);
InitiateMultipartUploadResult initiateMultipartUploadResult = s3Client.initiateMultipartUpload(initiateMultipartUploadRequest);
if(initiateMultipartUploadResult!=null){
String uploadId = initiateMultipartUploadResult.getUploadId();
//上传文件
UploadPartRequest uploadPartRequest = new UploadPartRequest().withUploadId(uploadId);
uploadPartRequest.setUploadId(uploadId);
uploadPartRequest.setBucketName(bucketName);
uploadPartRequest.setKey(key);
List partETags = new ArrayList<>();
byte[] content = new byte[5*1024*1024];
String filePath = "d:\\SQLyog-13.1.8-0.x64Trial.exe";
File file = new File(filePath);
try{
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
int readSize = 0;
int partNum =1;
while ((readSize = bis.read(content)) > 0) {
uploadPartRequest.setPartSize(readSize);
uploadPartRequest.setPartNumber(partNum);
uploadPartRequest.setInputStream(new ByteArrayInputStream(content));
partNum++;
UploadPartResult uploadPartResult= s3Client.uploadPart(uploadPartRequest);
partETags.add(uploadPartResult.getPartETag());
System.out.println("uploadPartResult:"+uploadPartResult.getPartNumber()+"|"+uploadPartResult.getETag()+"|"+uploadPartResult.getServerSideEncryption()+"|"+uploadPartResult.getPartETag());
}
}catch (Exception e){
e.printStackTrace();
}
//合并提交
CompleteMultipartUploadRequest compRequest = new CompleteMultipartUploadRequest(bucketName, key, uploadId, partETags);
s3Client.completeMultipartUpload(compRequest);
}
}
/**
* 刪除文件
*/
public static void delObject(){
AmazonS3 s3Client = getAmazonS3Client();
String key = "123.jpg";
s3Client.deleteObject(bucketName,key);
}
public static void main(String[] args) {
//getBuckets();
listObjects();
//putObject();
// multiPut();
// genDownloadUrlTest();
// delObject();
// System.out.println("uuuuu======"+url);
}
}
2.测试
最下方有主方法可以直接进行每个方法的测试
2.1查看桶 getBucketsTest();
2.2分片上传 multiPutTest(); 记得修改上传文件的路径
2.3genDownloadUrlTest()获取上传路径
注意!!:遇到NoClassDefFoundError: org/joda/time/DateTimeZone报错可以在pom里添加一个
joda-time
joda-time
2.10
本机下创建一个文件夹,里面创建四个文件相当于四个节点
打开cmd窗口,输入已下命令启动minio的服务。如果是四台虚拟机,则文件路径换成虚拟机的http访问路径即可
minio.exe server D:\software\minio\minio_data\data1 D:\software\minio\minio_data\data2 D:\software\minio\minio_data\data3 D:\software\minio\minio_data\data4
随便查看一个节点可以看到已经有创建好的testbucket
上传文件