首先导包,官网:https://cloud.tencent.com/document/product/436/10199
<dependency>
<groupId>com.qcloud</groupId>
<artifactId>cos_api</artifactId>
<version>5.6.97</version>
</dependency>
<!-- 依赖包 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.12</version>
</dependency>
新建一个工具类TXOSSUtil
,内容如下
package com.demo.util;
import cn.hutool.json.JSONUtil;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.exception.MultiObjectDeleteException;
import com.qcloud.cos.http.HttpProtocol;
import com.qcloud.cos.model.Bucket;
import com.qcloud.cos.model.COSObjectInputStream;
import com.qcloud.cos.model.COSObjectSummary;
import com.qcloud.cos.model.CannedAccessControlList;
import com.qcloud.cos.model.CopyObjectRequest;
import com.qcloud.cos.model.CopyResult;
import com.qcloud.cos.model.CreateBucketRequest;
import com.qcloud.cos.model.DeleteObjectsRequest;
import com.qcloud.cos.model.DeleteObjectsResult;
import com.qcloud.cos.model.GetObjectRequest;
import com.qcloud.cos.model.ListObjectsRequest;
import com.qcloud.cos.model.ObjectListing;
import com.qcloud.cos.model.ObjectMetadata;
import com.qcloud.cos.model.PutObjectRequest;
import com.qcloud.cos.model.PutObjectResult;
import com.qcloud.cos.model.UploadResult;
import com.qcloud.cos.region.Region;
import com.qcloud.cos.transfer.Copy;
import com.qcloud.cos.transfer.TransferManager;
import com.qcloud.cos.transfer.Upload;
import com.qcloud.cos.utils.IOUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.Executors;
/**
* author xiaochi
* date 2023/3/28
*/
@Slf4j
public class TXOSSUtil {
private final String region = "ap-guangzhou";//bucket 的地域
private final String secretid = "xxxxx";//secretId
private final String secretkey = "xxxxx";//secretKey
private final String bucket = "u-i-1258233335"; //存储桶名称,格式:BucketName-APPID
private final int fixedTthreadPool = 5;;//固定线程数
private static transient TXOSSUtil instance;
/**
* 获取实例
* @return
*/
public static TXOSSUtil getInstance() {
if (instance == null){
instance = new TXOSSUtil();
}
return instance;
}
/**
* 获取bucket
* @return
*/
public String getBucket() {
return bucket;
}
/**
* 获取地址
* @param key
* @return
*/
public String getPath(String key){
return getPath(bucket,key);
}
/**
* 获取地址
* @param bucketName
* @param key
*/
public String getPath(String bucketName,String key){
String url = "";
COSClient cosClient = cosClient();
try {
url = cosClient.getObject(bucketName,key).getObjectContent().getHttpRequest().getURI().toString();
}catch (Exception e){
log.error("获取地址失败:[{}]",e);
}finally {
cosClient.shutdown();
}
return url;
}
/**
* 上传文件
* @param file
* @param key
*/
public String upload(File file, String key){
return upload(file,bucket,key);
}
/**
* 上传文件
* @param file
* @param bucketName
* @param key
*/
public String upload(File file, String bucketName, String key){
String url = "";
COSClient cosClient = cosClient();
try {
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName,key,file);
PutObjectResult putObjectResult = cosClient.putObject(putObjectRequest);
url = cosClient.getObject(bucketName, key).getObjectContent().getHttpRequest().getURI().toString();
log.info("上传文件结果:[{}]", putObjectResult.getRequestId());
}catch (Exception e){
log.error("上传文件异常:[{}]",e);
}finally {
cosClient.shutdown();
}
return url;
}
/**
* 批量上传文件
* @param files
* @param keys
*/
public String upload(List<File> files,List<String> keys){
return upload(files,keys,bucket);
}
/**
* 批量上传文件
* @param files
* @param bucketName
* @param keys
*/
public String upload(List<File> files,List<String> keys, String bucketName){
String url = "";
COSClient cosClient = cosClient();
try {
for (int i = 0,len = files.size(); i < len; i++) {
String k = keys.get(i);
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName,k,files.get(i));
PutObjectResult putObjectResult = cosClient.putObject(putObjectRequest);
url = cosClient.getObject(bucketName, k).getObjectContent().getHttpRequest().getURI().toString();
log.info("上传文件结果:[{}]", putObjectResult.getRequestId());
}
}catch (Exception e){
log.error("上传文件异常:[{}]",e);
}finally {
cosClient.shutdown();
}
return url;
}
/**
* 批量上传文件
* @param files
* @param keys
*/
public List<String> uploadBatch(List<File> files, List<String> keys) {
return uploadBatch(files,keys,bucket);
}
/**
* 批量上传文件
* @param files
* @param keys
* @param bucketName
*/
public List<String> uploadBatch(List<File> files,List<String> keys, String bucketName) {
List<String> urls = new ArrayList<>();
// 指定文件上传到 COS 上的路径,即对象键。例如对象键为 folder/picture.jpg,则表示将文件 picture.jpg 上传到 folder 路径下
COSClient cosClient = cosClient();
TransferManager transferManager = transferManager();
List<Upload> uploads = new ArrayList<>();
try {
for (int i = 0,len = files.size(); i < len; i++) {
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, keys.get(i), files.get(i));
Upload upload = transferManager.upload(putObjectRequest);
uploads.add(upload);
}
for (Upload u : uploads) {
UploadResult result = u.waitForUploadResult();
log.info("批量上传文件key:[{}]", result.getKey());
String url = cosClient.getObject(bucketName, result.getKey()).getObjectContent().getHttpRequest().getURI().toString();
urls.add(url);
}
}catch (Exception e){
log.error("批量上传文件异常:[{}]",e);
}finally {
transferManager.shutdownNow();
cosClient.shutdown();
}
return urls;
}
/**
* 上传文件
* @param file
* @param key
*/
public String uploadSteam(File file, String key){
return uploadSteam(file,bucket,key);
}
/**
* 上传文件
* @param file
* @param bucketName
* @param key
*/
public String uploadSteam(File file, String bucketName, String key){
String url = "";
// 指定文件上传到 COS 上的路径,即对象键。例如对象键为 folder/picture.jpg,则表示将文件 picture.jpg 上传到 folder 路径下
COSClient cosClient = cosClient();
TransferManager transferManager = transferManager();
try {
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName,key,file);
Upload upload = transferManager.upload(putObjectRequest);
UploadResult uploadResult = upload.waitForUploadResult();
url = cosClient.getObject(bucketName, key).getObjectContent().getHttpRequest().getURI().toString();
log.info("上传文件结果:[{}]", uploadResult.getKey());
}catch (Exception e){
log.error("上传文件异常:[{}]",e);
}finally {
transferManager.shutdownNow();
cosClient.shutdown();
}
return url;
}
/**
* 上传文件
* @param in
* @param key
*/
public String upload(InputStream in, String key){
return upload(in,bucket,key);
}
/**
* 上传文件
* @param in
* @param bucketName
* @param key
*/
public String upload(InputStream in, String bucketName, String key){
String url = "";
// 指定文件上传到 COS 上的路径,即对象键。例如对象键为 folder/picture.jpg,则表示将文件 picture.jpg 上传到 folder 路径下
COSClient cosClient = cosClient();
TransferManager transferManager = transferManager();
try {
ObjectMetadata objectMetadata = new ObjectMetadata();
objectMetadata.setContentLength(in.available());
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName,key,in,objectMetadata);
/*PutObjectResult putObjectResult = cosClient.putObject(putObjectRequest);
COSObject object = cosClient.getObject(bucketName, folder);
String path = object.getObjectContent().getHttpRequest().getURI().toString();
System.out.println(path);
cosClient.shutdown();
log.info("上传文件结果:[{}]", JSONUtil.toJsonStr(putObjectResult));*/
/*URL url = cosClient.generatePresignedUrl(bucketName, folder, new Date(new Date().getTime() + 1000));
log.info("上传文件结果:[{}]",url.getProtocol()+"://"+url.getHost()+url.getPath());*/
Upload upload = transferManager.upload(putObjectRequest);
UploadResult uploadResult = upload.waitForUploadResult();
url = cosClient.getObject(bucketName, key).getObjectContent().getHttpRequest().getURI().toString();
log.info("上传文件结果:[{}]", uploadResult.getKey());
}catch (Exception e){
log.error("上传文件异常:[{}]",e);
}finally {
transferManager.shutdownNow();
cosClient.shutdown();
}
return url;
}
/**
* 复制文件(可以进行文件重命名)
* @param oldKey
* @param newKey
*/
public String copy(String oldKey,String newKey){
return copy(bucket,oldKey,bucket,newKey);
}
/**
* 复制文件(可以进行文件重命名)
* @param oldBucketName
* @param oldKey
* @param newBucketName
* @param newKey
*/
public String copy(String oldBucketName,String oldKey,String newBucketName,String newKey){
String url = "";
COSClient cosClient = cosClient();
try {
CopyObjectRequest copyObjectRequest = new CopyObjectRequest(new Region(region), oldBucketName, oldKey, newBucketName, newKey);
CopyObjectResult copyResult = cosClient.copyObject(copyObjectRequest);
url = cosClient.getObject(newBucketName,newKey).getObjectContent().getHttpRequest().getURI().toString();
log.info("复制文件结果:[{}]", copyResult.getRequestId());
}catch (Exception e){
log.error("复制文件异常:[{}]",e);
return url;
}finally {
cosClient.shutdown();
}
return url;
}
/**
* 批量复制文件(可以进行文件重命名)
* @param keys Map<oldKey.newKey>
*/
public List<String> copyBatch(Map<String,String> keys){
return copyBatch(bucket,bucket,keys);
}
/**
* 批量复制文件(可以进行文件重命名)
* @param oldBucketName
* @param keys Map<oldKey.newKey>
*/
public List<String> copyBatch(String oldBucketName,Map<String,String> keys){
return copyBatch(oldBucketName,oldBucketName,keys);
}
/**
* 批量复制文件(可以进行文件重命名)
* @param oldBucketName
* @param newBucketName
* @param keys Map<oldKey.newKey>
*/
public List<String> copyBatch(String oldBucketName, String newBucketName, Map<String,String> keys){
List<String> path = new ArrayList<>();
COSClient cosClient = cosClient();
try {
for (Map.Entry<String, String> entry : keys.entrySet()) {
String oldKey = entry.getKey();
if (cosClient.doesObjectExist(oldBucketName,oldKey)){
String newKey = entry.getValue();
CopyObjectRequest copyObjectRequest = new CopyObjectRequest(new Region(region), oldBucketName, oldKey, newBucketName, newKey);
CopyObjectResult copyResult = cosClient.copyObject(copyObjectRequest);
String url = cosClient.getObject(newBucketName,newKey).getObjectContent().getHttpRequest().getURI().toString();
path.add(url);
log.info("复制文件结果:[{}]", copyResult.getRequestId());
}else {
log.info("文件[{}]不存在",oldKey);
}
}
}catch (Exception e){
log.error("复制文件异常:[{}]",e);
return path;
}finally {
cosClient.shutdown();
}
return path;
}
/**
* 复制文件(可以进行文件重命名)
* @param oldBucketName
* @param oldKey
* @param newBucketName
* @param newKey
*/
public String copyStream(String oldBucketName,String oldKey,String newBucketName,String newKey){
String url = "";
COSClient cosClient = cosClient();
TransferManager transferManager = transferManager();
try {
CopyObjectRequest copyObjectRequest = new CopyObjectRequest(new Region(region), oldBucketName, oldKey, newBucketName, newKey);
Copy copy = transferManager.copy(copyObjectRequest);
// 高级接口会返回一个异步结果 Copy
// 可同步的调用 waitForCopyResult 等待复制结束, 成功返回 CopyResult, 失败抛出异常
CopyResult copyResult = copy.waitForCopyResult();
url = cosClient.getObject(newBucketName,newKey).getObjectContent().getHttpRequest().getURI().toString();
log.info("复制文件结果:[{}]", copyResult.getDestinationKey());
}catch (Exception e){
log.error("复制文件异常:[{}]",e);
return url;
}finally {
transferManager.shutdownNow();
cosClient.shutdown();
}
return url;
}
/**
* 检查存储桶是否存在
*/
public boolean hasBucketExist(String bucketName){
COSClient cosClient = cosClient();
try {
return cosClient.doesBucketExist(bucketName);
}catch (Exception e){
log.error("检查存储桶是否存在异常:[{}]",e);
return false;
}finally {
cosClient.shutdown();
}
}
/**
* 检查文件是否存在
* @param key
*/
public boolean hasExists(String key){
return hasExists(bucket,key);
}
/**
* 检查文件是否存在
* @param bucketName
* @param key
*/
public boolean hasExists(String bucketName,String key){
COSClient cosClient = cosClient();
try {
return cosClient.doesObjectExist(bucketName,key);
}catch (Exception e){
log.error("检查文件是否存在异常:[{}]",e);
return false;
}finally {
cosClient.shutdown();
}
}
/**
* 获取目录下所有文件
* @param dir
*/
public List<String> getFileByDir(String dir){
return getFileByDir(bucket,dir);
}
/**
* 获取目录下所有文件
* @param bucketName
* @param dir
*/
public List<String> getFileByDir(String bucketName,String dir){
List<String> list = new ArrayList<>();
COSClient cosClient = cosClient();
try {
ListObjectsRequest listObjectsRequest = new ListObjectsRequest();
// 设置 bucket 名称
listObjectsRequest.setBucketName(bucketName);
// prefix 表示列出的对象名以 prefix 为前缀
// 这里填要列出的目录的相对 bucket 的路径
listObjectsRequest.setPrefix(dir);
// 设置最大遍历出多少个对象, 一次 listobject 最大支持1000
listObjectsRequest.setMaxKeys(1000);
ObjectListing objectListing = cosClient.listObjects(listObjectsRequest);
// 这里保存列出的对象列表
List<COSObjectSummary> cosObjectSummaries = objectListing.getObjectSummaries();
if (!Objects.isNull(cosObjectSummaries) && cosObjectSummaries.size() > 0){
for (COSObjectSummary f:cosObjectSummaries){
list.add(cosClient().getObject(bucketName,f.getKey()).getObjectContent().getHttpRequest().getURI().toString());
}
}
}catch (Exception e){
log.error("获取目录下所有文件异常:[{}]",e);
}finally {
cosClient.shutdown();
}
return list;
}
/**
* 目录删除(如:2023/03/01.jpg,不能以/开头)
* @param dir 这里填要列出的目录的相对 bucket 的路径
*/
public boolean deleteDir(String dir){
return deleteDir(bucket,dir);
}
/**
* 目录删除(如:2023/03/01.jpg,不能以/开头)
* @param bucketName
* @param dir 这里填要列出的目录的相对 bucket 的路径
*/
public boolean deleteDir(String bucketName,String dir){
boolean flag = true;
COSClient cosClient = cosClient();
try {
ListObjectsRequest listObjectsRequest = new ListObjectsRequest();
// 设置 bucket 名称
listObjectsRequest.setBucketName(bucketName);
// prefix 表示列出的对象名以 prefix 为前缀
// 这里填要列出的目录的相对 bucket 的路径
listObjectsRequest.setPrefix(dir);
// 设置最大遍历出多少个对象, 一次 listobject 最大支持1000
listObjectsRequest.setMaxKeys(1000);
// 保存每次列出的结果
ObjectListing objectListing = null;
do {
objectListing = cosClient.listObjects(listObjectsRequest);
// 这里保存列出的对象列表
List<COSObjectSummary> cosObjectSummaries = objectListing.getObjectSummaries();
ArrayList<DeleteObjectsRequest.KeyVersion> delObjects = new ArrayList<DeleteObjectsRequest.KeyVersion>();
for (COSObjectSummary cosObjectSummary : cosObjectSummaries) {
delObjects.add(new DeleteObjectsRequest.KeyVersion(cosObjectSummary.getKey()));
}
DeleteObjectsRequest deleteObjectsRequest = new DeleteObjectsRequest(bucketName);
deleteObjectsRequest.setKeys(delObjects);
deleteMethod(deleteObjectsRequest);
// 标记下一次开始的位置
String nextMarker = objectListing.getNextMarker();
listObjectsRequest.setMarker(nextMarker);
} while (objectListing.isTruncated());
}catch (Exception e){
log.error("删除目录:[{}]",e);
}finally {
cosClient.shutdown();
}
return flag;
}
/**
* 删除(如:2023/03/01.jpg,不能以/开头)
* @param key
*/
public boolean delete(String key){
return delete(bucket,key);
}
/**
* 删除(如:2023/03/01.jpg,不能以/开头)
* @param bucketName
* @param key
*/
public boolean delete(String bucketName,String key){
if (key.startsWith("/")){
return false;
}
COSClient cosClient = cosClient();
try {
cosClient.deleteObject(bucketName,key);
return true;
}catch (Exception e){
log.error("删除异常:[{}]",e);
return false;
}finally {
cosClient.shutdown();
}
}
/**
* 批量删除(如:2023/03/01.jpg,不能以/开头)
* @param keys
*/
public int deleteBatch(List<String> keys){
return deleteBatch(bucket,keys);
}
/**
* 批量删除(如:2023/03/01.jpg,不能以/开头)
* @param bucketName
* @param keys
*/
public int deleteBatch(String bucketName,List<String> keys){
// 最大只能同时删除1000
List<DeleteObjectsRequest.KeyVersion> keyVersionList = new ArrayList<>();
if (keys != null && keys.size() <= 1000){
keys.forEach(f -> keyVersionList.add(new DeleteObjectsRequest.KeyVersion(f)));
keys.clear();
DeleteObjectsRequest deleteObjectsRequest = new DeleteObjectsRequest(bucketName);
deleteObjectsRequest.setKeys(keyVersionList);
return deleteMethod(deleteObjectsRequest);
}
return 0;
}
/**
* 删除方法
* @param deleteObjectsRequest
*/
private int deleteMethod(DeleteObjectsRequest deleteObjectsRequest){
COSClient cosClient = cosClient();
try {
DeleteObjectsResult objectsResult = cosClient.deleteObjects(deleteObjectsRequest);
List<DeleteObjectsResult.DeletedObject> deletedObjects = objectsResult.getDeletedObjects();
return deletedObjects.size();
}catch (MultiObjectDeleteException mde){
// 如果部分删除成功部分失败, 返回 MultiObjectDeleteException
List<DeleteObjectsResult.DeletedObject> deleteObjects = mde.getDeletedObjects();
List<MultiObjectDeleteException.DeleteError> deleteErrors = mde.getErrors();
log.error("删除部分失败:[{}]",deleteObjects);
return deleteErrors.size();
}catch (Exception e){
log.error("删除异常:[{}]",e);
return 0;
}finally {
cosClient.shutdown();
}
}
/**
* 下载文件
* @param bucketName
* @param key
* @param response
*/
public void download(String bucketName, String key, HttpServletResponse response) throws Exception {
String fileName = URLDecoder.decode(key.substring(key.lastIndexOf("/") + 1), StandardCharsets.UTF_8.name());
fileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.name());
fileName = new String(fileName.getBytes(), StandardCharsets.ISO_8859_1);
response.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_OCTET_STREAM_VALUE+";charset=utf-8");
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + fileName);
response.setHeader(HttpHeaders.PRAGMA, "no-cache");
response.addHeader(HttpHeaders.CACHE_CONTROL, "no-cache");
byte[] bytes = download(bucketName, key);
BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream());
bos.write(bytes);
bos.flush();
bos.close();
response.flushBuffer();
}
/**
* 下载文件流
* @param bucketName
* @param key
*/
public byte[] download(String bucketName,String key){
byte[] bytes = null;
COSClient cosClient = cosClient();
GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName, key);
COSObjectInputStream cosObjectInput = null;
try {
cosObjectInput = cosClient.getObject(getObjectRequest).getObjectContent();
bytes = IOUtils.toByteArray(cosObjectInput);
}catch (Exception e){
log.error("获取下载文件流异常:[{}]",e);
}finally {
cosClient.shutdown();
if (cosObjectInput != null){
try {
cosObjectInput.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return bytes;
}
/**
* 获取存储桶列表
*/
public List<Bucket> buckList(){
COSClient cosClient = cosClient();
try {
return cosClient.listBuckets();
}catch (Exception e){
log.error("获取存储桶列表异常:[{}]",e);
return new ArrayList<>();
}finally {
cosClient.shutdown();
}
}
/**
* 创建存储桶
*/
public boolean createBucket(){
COSClient cosClient = cosClient();
CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucket);
// 设置 bucket 的权限为 Private(私有读写)、其他可选有 PublicRead(公有读私有写)、PublicReadWrite(公有读写)
createBucketRequest.setCannedAcl(CannedAccessControlList.PublicRead);
try{
Bucket bucketResult = cosClient.createBucket(createBucketRequest);
log.info("创建存储桶结果:[{}]", JSONUtil.toJsonStr(bucketResult));
return true;
} catch (Exception e) {
log.error("创建存储桶异常:[{}]",e);
return false;
}finally {
cosClient.shutdown();
}
}
/**
* 创建 transferManager
*/
public TransferManager transferManager(){
COSClient cosClient = cosClient();
return new TransferManager(cosClient, Executors.newFixedThreadPool(fixedTthreadPool));
}
/**
* 创建 COSClient 实例
*/
public COSClient cosClient(){
// 1 初始化用户身份信息(secretId, secretKey)。
// SECRETID 和 SECRETKEY 请登录访问管理控制台 https://console.cloud.tencent.com/cam/capi 进行查看和管理
COSCredentials cred = new BasicCOSCredentials(secretid, secretkey);
// 2 设置 bucket 的地域, COS 地域的简称请参见 https://cloud.tencent.com/document/product/436/6224
// clientConfig 中包含了设置 region, https(默认 http), 超时, 代理等 set 方法, 使用可参见源码或者常见问题 Java SDK 部分。
Region r = new Region(region);
ClientConfig clientConfig = new ClientConfig(r);
// 这里建议设置使用 https 协议
// 从 5.6.54 版本开始,默认使用了 https
clientConfig.setHttpProtocol(HttpProtocol.https);
// 3 生成 cos 客户端。
return new COSClient(cred, clientConfig);
}
}
使用方式
package com.example.demo;
import com.example.demo.util.WXOSSUtil;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;
/**
* author chics
* date 2023/3/28
*/
public class WXOSSTest {
public static void main(String[] args) throws FileNotFoundException {
String fileName = "01.jpg";
File file = new File("D:\\"+fileName);
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM");
String p = WXOSSUtil.getInstance().upload(new FileInputStream(file), WXOSSUtil.getInstance().getBucket(), dateFormat.format(new Date()) + "/" + UUID.randomUUID().toString()+"/" + fileName);
// System.out.println(p);
// WXOSSUtil.getInstance().deleteDir("2023/03");
System.out.println(WXOSSUtil.getInstance().getFileByDir("2023/03"));
// System.out.println();
}
}
网友评论