main
ZhouXY108 2024-12-22 15:40:42 +08:00
commit 97a19a2d17
14 changed files with 4082 additions and 0 deletions

15
.editorconfig 100644
View File

@ -0,0 +1,15 @@
# EditorConfig is awesome: https://EditorConfig.org
# top-most EditorConfig file
root = true
[*]
indent_style = space
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.yaml]
indent_size = 2

40
.gitignore vendored 100644
View File

@ -0,0 +1,40 @@
HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
*/**/http/*.http
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
### bak ###
*.bak
**/resources/*-dev.*
**/resources/*-sit.*
**/resources/*-uat.*

View File

@ -0,0 +1,110 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>xyz.zhouxy.plusone.oss</groupId>
<artifactId>plusone-oss</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<groupId>xyz.zhouxy.plusone.oss</groupId>
<artifactId>plusone-oss-spring-boot2-test</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<java.version>17</java.version>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.7.18</spring-boot.version>
<aws.java.sdk.version>2.29.36</aws.java.sdk.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.5.14</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>bom</artifactId>
<version>${aws.java.sdk.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>17</source>
<target>17</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<configuration>
<mainClass>
xyz.zhouxy.plusone.oss.PlusoneOssTestApplication
</mainClass>
<skip>true</skip>
</configuration>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,32 @@
/*
* Copyright 2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package xyz.zhouxy.plusone.oss;
/**
*
*
* <p>
*
* </p>
*
* <p>
* <b>NOTE: </b>
* </p>
* @author <a href="http://zhouxy.xyz:3000/ZhouXY108}">ZhouXY</a>
*/
public enum OSSType {
MINIO, ALIYUN, TENCENT,
}

View File

@ -0,0 +1,11 @@
package xyz.zhouxy.plusone.oss;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class PlusoneOssTestApplication {
public static void main(String[] args) {
SpringApplication.run(PlusoneOssTestApplication.class, args);
}
}

View File

@ -0,0 +1,152 @@
/*
* Copyright 2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package xyz.zhouxy.plusone.oss;
import java.util.Objects;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;
import io.minio.MinioAsyncClient;
import io.minio.MinioClient;
import xyz.zhouxy.plusone.commons.util.AssertTools;
/**
* S3
*
* @author <a href="http://zhouxy.xyz:3000/ZhouXY108}">ZhouXY</a>
*/
@Configuration
@EnableConfigurationProperties(S3Properties.class)
@ConditionalOnClass(value = {
MinioClient.class,
MinioAsyncClient.class,
})
public class PlusoneS3AutoConfiguration {
private final OSSType ossType;
private final Protocol protocol;
private final Integer port;
private final String endpoint;
private final String accessKey;
private final String secretKey;
private final String region;
private final boolean secure;
@Autowired
public PlusoneS3AutoConfiguration(S3Properties s3Properties) {
this(s3Properties.getType(),
s3Properties.getProtocol(),
s3Properties.getEndpoint(),
s3Properties.getPort(),
s3Properties.isSecure(),
s3Properties.getAccessKey(),
s3Properties.getSecretKey(),
s3Properties.getRegion());
}
private PlusoneS3AutoConfiguration(OSSType ossType,
Protocol protocol, String endpoint, Integer port, boolean secure,
String accessKey, String secretKey, String region) {
AssertTools.checkArgument(Objects.nonNull(ossType), "Property \"ossType\" cannot be null");
AssertTools.checkArgument(StringUtils.hasText(endpoint), "Property \"endpoint\" must has text.");
AssertTools.checkArgument(StringUtils.hasText(accessKey), "Property \"accessKey\" must has text.");
AssertTools.checkArgument(StringUtils.hasText(secretKey), "Property \"secretKey\" must has text.");
AssertTools.checkArgument(StringUtils.hasText(region), "Property \"region\" must has text.");
this.ossType = ossType;
int i = endpoint.indexOf("://");
if (i == -1) {
// endpoint 不带协议
this.protocol = protocol != null ? protocol : Protocol.HTTP;
this.endpoint = endpoint;
} else {
// endpoint 带协议
if (protocol != null) {
// protocol 不为空,则使用 protocol
this.protocol = protocol;
} else {
// protocol 为空,则使用 endpoint 中的协议
String protocolInEndPoint = endpoint.substring(0, i);
this.protocol = Protocol.of(protocolInEndPoint);
}
// 去除协议部分
this.endpoint = endpoint.substring(i + "://".length());
}
this.port = port;
this.secure = secure;
this.accessKey = accessKey;
this.secretKey = secretKey;
this.region = region;
}
public MinioClient ossClient() {
final MinioClient.Builder minioClientBuilder = MinioClient.builder();
final String url = this.protocol.getCode() + "://" + this.endpoint;
if (this.port != null) {
minioClientBuilder.endpoint(url, this.port, this.secure);
}
else {
minioClientBuilder.endpoint(url);
}
return minioClientBuilder
.region(this.region)
.credentials(this.accessKey, this.secretKey)
.build();
}
/**
* @return the ossType
*/
public OSSType getOssType() {
return ossType;
}
public Protocol getProtocol() {
return protocol;
}
/**
* @return the port
*/
public Integer getPort() {
return port;
}
public String getEndpoint() {
return endpoint;
}
public String getAccessKey() {
return accessKey;
}
public String getSecretKey() {
return secretKey;
}
/**
* @return the region
*/
public String getRegion() {
return region;
}
}

View File

@ -0,0 +1,66 @@
/*
* Copyright 2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package xyz.zhouxy.plusone.oss;
import javax.annotation.Nonnull;
import xyz.zhouxy.plusone.commons.base.IWithCode;
/**
*
*
* <p>
*
* </p>
*
* <p>
* <b>NOTE: </b>
* </p>
* @author <a href="http://zhouxy.xyz:3000/ZhouXY108}">ZhouXY</a>
*/
public enum Protocol implements IWithCode<String> {
HTTP("http"),
HTTPS("https"),
;
@Nonnull
final String code;
static final Protocol[] values = { HTTP, HTTPS };
Protocol(@Nonnull String code) {
this.code = code;
}
public static Protocol of(String code) {
for (Protocol protocol : values) {
if (protocol.equalsCode(code)) {
return protocol;
}
}
throw new IllegalArgumentException("Endpoint 中使用了无效的协议");
}
/**
* @return the code
*/
@Override
@Nonnull
public String getCode() {
return code;
}
}

View File

@ -0,0 +1,143 @@
/*
* Copyright 2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package xyz.zhouxy.plusone.oss;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.util.StringUtils;
import xyz.zhouxy.plusone.commons.util.AssertTools;
/**
* S3
*
* @author <a href="http://zhouxy.xyz:3000/ZhouXY108}">ZhouXY</a>
*/
@ConfigurationProperties("plusone.s3")
public class S3Properties {
private OSSType type;
private Protocol protocol;
private String endpoint;
private Integer port;
private String accessKey;
private String secretKey;
private String region;
/**
* @return the type
*/
public OSSType getType() {
return type;
}
/**
* @param type the type to set
*/
public void setType(OSSType type) {
this.type = type;
}
/**
* @return the protocol
*/
public Protocol getProtocol() {
return protocol;
}
/**
* @param protocol the protocol to set
*/
public void setProtocol(Protocol protocol) {
this.protocol = protocol;
}
/**
* @return the endpoint
*/
public String getEndpoint() {
return endpoint;
}
/**
* @param endpoint the endpoint to set
*/
public void setEndpoint(String endpoint) {
AssertTools.checkArgument(StringUtils.hasText(endpoint), "Property \"endpoint\" must has text.");
this.endpoint = endpoint;
}
/**
* @return the port
*/
public Integer getPort() {
return port;
}
/**
* @param port the port to set
*/
public void setPort(Integer port) {
this.port = port;
}
/**
* @return the accessKey
*/
public String getAccessKey() {
return accessKey;
}
/**
* @param accessKey the accessKey to set
*/
public void setAccessKey(String accessKey) {
AssertTools.checkArgument(StringUtils.hasText(accessKey), "Property \"accessKey\" must has text.");
this.accessKey = accessKey;
}
/**
* @return the secretKey
*/
public String getSecretKey() {
return secretKey;
}
/**
* @param secretKey the secretKey to set
*/
public void setSecretKey(String secretKey) {
AssertTools.checkArgument(StringUtils.hasText(secretKey), "Property \"secretKey\" must has text.");
this.secretKey = secretKey;
}
/**
* @return the region
*/
public String getRegion() {
return region;
}
/**
* @param region the region to set
*/
public void setRegion(String region) {
this.region = region;
}
public boolean isSecure() {
return this.protocol != null && this.protocol == Protocol.HTTPS;
}
}

View File

@ -0,0 +1,37 @@
{"properties": [
{
"name": "plusone.s3.type",
"type": "java.lang.String",
"description": "A description for 'plusone.s3.type'"
},
{
"name": "plusone.s3.protocol",
"type": "software.amazon.awssdk.core.Protocol",
"description": "A description for 'plusone.s3.protocol'"
},
{
"name": "plusone.s3.endpoint",
"type": "java.lang.String",
"description": "A description for 'plusone.s3.endpoint'"
},
{
"name": "plusone.s3.access-key",
"type": "java.lang.String",
"description": "A description for 'plusone.s3.access-key'"
},
{
"name": "plusone.s3.secret-key",
"type": "java.lang.String",
"description": "A description for 'plusone.s3.secret-key'"
},
{
"name": "plusone.s3.region",
"type": "java.lang.String",
"description": "A description for 'plusone.s3.region'"
},
{
"name": "plusone.s3.port",
"type": "java.lang.String",
"description": "A description for 'plusone.s3.port'"
}
]}

View File

@ -0,0 +1,2 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
xyz.zhouxy.plusone.oss.PlusoneS3AutoConfiguration

View File

@ -0,0 +1,23 @@
spring:
application:
name: plusone-oss-test-application
plusone:
s3:
# type: minio
# protocol: http
# endpoint: zhouxy.xyz
# port: 9000
# access-key: MPvs85pvZHLgwnIpP3jD
# secret-key: gEV7mzI3UXaxoR9Y5Zi39IYl3Vny2D0fE2JNYzWF
type: tencent
protocol: https
endpoint: cos.ap-chengdu.myqcloud.com
access-key: AKIDwkMjutlPq56lBPgsw4EMG3iEVbZfbIpD
secret-key: UkoiRyIj7HJD0cIpJesukS1OXcXKuIST
region: cn-north-1
# type: aliyun
# protocol: https
# endpoint: oss-cn-beijing.aliyuncs.com
# access-key: LTAI5t8tdQCHpykg3BnXbez7
# secret-key: zCwLzF2QovtWJRRbWHpIh1JbHIofIs
# region: cn-north-1

View File

@ -0,0 +1,56 @@
package xyz.zhouxy.plusone.oss;
import static org.junit.jupiter.api.Assertions.*;
import java.time.Duration;
import java.util.concurrent.TimeUnit;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import io.minio.GetPresignedObjectUrlArgs;
import io.minio.MinioClient;
import io.minio.http.Method;
import lombok.extern.slf4j.Slf4j;
@SpringBootTest
@Slf4j
public class PlusoneOssTestApplicationTests {
@Autowired
PlusoneS3AutoConfiguration s3Config;
@Test
void testListBuckets() throws Exception {
try (MinioClient minioClient = s3Config.ossClient()) {
minioClient.listBuckets().forEach(bucket -> {
log.info("Bucket - [name: {}, creationDate: {}]", bucket.name(), bucket.creationDate());
});
} catch (Exception e) {
log.error("测试失败", e);
throw e;
}
}
@Test
void testMinIO() throws Exception {
try (MinioClient ossClient = s3Config.ossClient()) {
var url = ossClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
.bucket("code108-1300048601")
.object("plusone/表结构.xlsx")
.expiry(10, TimeUnit.MINUTES)
.method(Method.GET)
.build());
logObj(url);
} catch (Exception e) {
log.info("测试失败", e);
throw e;
}
}
static void logObj(Object obj) {
log.info("{}", obj);
}
}

22
pom.xml 100644
View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>xyz.zhouxy.plusone.oss</groupId>
<artifactId>plusone-oss</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>plusone-oss-spring-boot2-test</module>
</modules>
<dependencies>
<dependency>
<groupId>xyz.zhouxy.plusone</groupId>
<artifactId>plusone-commons</artifactId>
<version>1.0.0-alpha</version>
</dependency>
</dependencies>
</project>