SpringBoot2.x整合(cos,oss,本地挂载盘)文件
2021-02-08 本文已影响0人
小胖学编程
由于项目升级,文件存储由本地磁盘(挂载盘)升级为cos(腾讯云)存储,由此实现了一套整合各家文件存储的项目。
1. 设计思想
1.1 使用到的设计模式
- 例如cos和oss提供的client不同,以及本地磁盘存储需要自己实现client端。所以需要自己实现一个公共的接口,使用适配器模式,将各种client端转换为统一的client接口实现;
- 业务端依旧使用
Template
类操作文件,Template类使用模板方法模式,来支持业务放进行扩展。 - Template类通过组合的方式选择client类,使用策略模式来自由的切换存储介质(cos,oss,本地磁盘)。
1.2 设计思想
项目默认提供cos腾讯云存储和本地挂载盘存储的template
类。当业务方在依赖中移除腾讯cos的依赖,且使用阿里云oss的依赖后。template
类将自动切换为阿里云oss的存储。
<dependency>
<groupId>com.tellme</groupId>
<artifactId>xos-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
<exclusions>
<exclusion>
<artifactId>cos_api</artifactId>
<groupId>com.qcloud</groupId>
</exclusion>
<exclusion>
<groupId>com.tencent.cloud</groupId>
<artifactId>cos-sts-java</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>2.8.3</version>
</dependency>
其思想借鉴与SpringBoot2.x-Redis实现Jedis客户端和Lettuce客户端的切换。
2. 代码实现
2.1 pom依赖
pom依赖中,使用SpringBoot2.0.4
版本。
引入了
- 腾讯云cos提供的jar;
- 阿里云oss提供的jar;
- 以及相关的工具jar;
当然阿里云oss的依赖不向下传递。
<?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>com.tellme</groupId>
<artifactId>xos-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<scope>provided</scope>
</dependency>
<!-- 通信-->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.8.1</version>
</dependency>
<dependency>
<groupId>com.qcloud</groupId>
<artifactId>cos_api</artifactId>
<version>5.6.8</version>
</dependency>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>cos-sts-java</artifactId>
<version>3.0.5</version>
</dependency>
<!--jar不向下传递(阿里云oos)-->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>2.8.3</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.0.1</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
2.2 starter的实现
在spring.factories文件中定义自动装配的类。
image.pngorg.springframework.boot.autoconfigure.EnableAutoConfiguration=com.tellme.os.config.OSAutoConfiguration
2.3 client端(适配器模式)
首先是需要提供一个项目内公共的接口类(OSClient)。无论各个厂商的client客户端都要进行适配。
public interface OSClient {
/**
* 上传文件
*
* @param storageName (bucketName)存储桶
* @param relativePath 文件上传的地址
* @param fileBytes 文件流
*/
void uploadFile(String storageName, String relativePath, byte[] fileBytes);
/**
* 下载文件
*
* @param filePath 文件地址
* @return 文件输出流
*/
ByteArrayOutputStream downloadFile(String filePath);
/**
* 客户端关闭
*/
void shutdown();
}
由于云文件存储,下载文件的方法是相同的,故可以使用模板方法模式来进行扩展。
@Slf4j
public abstract class NetOsClient implements OSClient {
@Override
public ByteArrayOutputStream downloadFile(String filePath) {
ByteArrayOutputStream data;
data = OkHttpUtil.get(filePath);
if (data == null) {
throw new OsException("下载照片失败,照片地址:" + filePath);
}
//转换流信息
return data;
}
}
2.3.1 适配腾讯云cos客户端
@Data
public class CosClient extends NetOsClient {
private COSClient cosClient;
/**
*
* @param bucketName 存储桶
* @param relativePath 文件上传的地址
* @param fileBytes 文件流
*/
@Override
public void uploadFile(String bucketName, String relativePath, byte[] fileBytes) {
ByteArrayInputStream input = new ByteArrayInputStream(fileBytes);
ObjectMetadata objectMetadata = new ObjectMetadata();
// 设置输入流长度
objectMetadata.setContentLength(input.available());
cosClient.putObject(bucketName, relativePath, input, objectMetadata);
}
/**
* 关闭客户端
*/
@Override
public void shutdown() {
cosClient.shutdown();
}
}
2.3.2 适配阿里云oss客户端
@Data
public class OssClient extends NetOsClient{
private OSSClient ossClient;
@Override
public void uploadFile(String bucketName, String relativePath, byte[] fileBytes) {
ByteArrayInputStream input = new ByteArrayInputStream(fileBytes);
ObjectMetadata objectMetadata = new ObjectMetadata();
// 设置输入流长度
objectMetadata.setContentLength(input.available());
ossClient.putObject(bucketName, relativePath, input, objectMetadata);
}
@Override
public void shutdown() {
ossClient.shutdown();
}
}
2.3.3 适配本地挂载盘客户端
@Slf4j
public class FileOsClient implements OSClient {
/**
* @param bucketName 上传的根路径
* @param relativePath 文件上传的地址
* @param fileBytes 文件流
*/
@Override
public void uploadFile(String bucketName, String relativePath, byte[] fileBytes) {
File file = new File(bucketName + File.separator + relativePath);
//获取文件夹目录
String fullPath = file.getParent();
File dir = new File(fullPath);
//创建目录
dir.mkdirs();
try {
//构建输出流
ByteArrayInputStream is = new ByteArrayInputStream(fileBytes);
FileOutputStream os = new FileOutputStream(file);
byte[] b = new byte[1024];
int nRead;
while ((nRead = is.read(b)) != -1) {
os.write(b, 0, nRead);
}
} catch (Exception e) {
log.error("", e);
throw new OsException("", e);
}
}
/**
* 读取本地文件
*
* @param filePath 文件地址
* @return 文件数组输出流
*/
@Override
public ByteArrayOutputStream downloadFile(String filePath) {
File file = new File(filePath);
if (!file.exists()) {
throw new OsException("文件不存在!");
}
InputStream is = IOUtil.getInputStream(file);
return IOUtil.convertInputStream(is);
}
@Override
public void shutdown() {
}
}
2.4 template类(模板模式+策略模式)
- template通过组合的方式引入client对象,在Spring容器初始化的时候选择合适的client策略。
- template采用模板方法模式,可自由扩展。
public interface OsTemplate {
/**
* 上传文件
*
* @param relativePath 上传文件的相对地址
* @param fileBytes 文件流
* @return 上传后的地址
*/
String saveFile(String relativePath, byte[] fileBytes);
/**
* 拼接路径,上传照片
*
* @param modulePath 项目路径
* @param fileSuffix 文件后缀
* @param base64Str base64
* @return 格式:{@code PATH_COMMON / modulePath / calculatePath() /UUID.randomUUID() + fileSuffixEnum.getType()}
*/
String saveFile(String modulePath, String fileSuffix, String base64Str);
/**
* 拼接路径,上传文件
*
* @param modulePath 项目路径
* @param fileBytes 文件流
* @param fileSuffix 文件后缀
* @return 格式:{@code PATH_COMMON / modulePath / calculatePath() /UUID.randomUUID() + fileSuffixEnum.getType()}
*/
String saveFile(String modulePath, byte[] fileBytes, String fileSuffix);
/**
* 拼接路径,上传到特定的存储桶
*
* @param bucketName 存储桶的名字
* @param modulePath 项目路径
* @param fileSuffix 文件后缀
* @param fileBytes 文件流
* @return 格式:{@code PATH_COMMON / modulePath / calculatePath() /UUID.randomUUID() + fileSuffix}
*/
String saveFile(String bucketName, String modulePath, String fileSuffix, byte[] fileBytes);
/**
* 拼接路径,上传到特定的存储桶
*
* @param bucketName 存储桶的名字
* @param relativePath 文件的相对路径
* @param fileBytes 文件流
* @return 格式:{@code PATH_COMMON / modulePath / calculatePath() /UUID.randomUUID() + fileSuffix}
*/
String saveFile(String bucketName, String relativePath, byte[] fileBytes);
/**
* 文件下载
*
* @param filePath 文件地址
* @return 下载字节流
*/
ByteArrayOutputStream downloadFile(String filePath);
/**
* CDN前缀地址
*
* @return CDN地址
*/
String getCdnHost();
}
2.4.1 云存储的template
@Data
@Slf4j
public class NetOsTemplate implements OsTemplate {
//cos连接对象
protected OSClient client;
protected OsConfigProperties osConfigProperties;
/**
* 存储介质:
* cos存储的是:bucketName
* file存储的是:根路径
*/
protected String bucketName;
/**
* cdn地址
*/
protected String cdnHost;
protected static String PATH_COMMON = "/xos";
/**
* (经常使用)使用配置文件的存储桶上传照片
*
* @param modulePath 模块路径
* @param fileSuffix 文件后缀,需要携带.
* @param base64Str 照片的base64信息
* @return 图片上传的地址
*/
public String saveFile(String modulePath, String fileSuffix, String base64Str) {
return saveFile(bucketName, modulePath, fileSuffix, IOUtil.base64ToBytes(base64Str));
}
/**
* (经常使用)使用配置文件的存储桶上传文件
*
* @param modulePath 模块路径
* @param fileSuffix 文件后缀,需要携带.
* @param fileBytes 文件流字节数组
* @return 图片上传的地址
*/
public String saveFile(String modulePath, byte[] fileBytes, String fileSuffix) {
return saveFile(bucketName, modulePath, fileSuffix, fileBytes);
}
/**
* 腾讯云上传文件
* 只需要传入模块目录,自动拼装上传腾讯云的路径。
* {@code PATH_COMMON / modulePath / calculatePath() /UUID.randomUUID() + fileSuffixEnum.getType()}
*
* @param bucketName 存储目录
* @param modulePath 模块路径(业务路径格式:{@code exercise/plan/answerImage })
* @param fileSuffix 文件后缀,需要携带.
* @param fileBytes 文件流字节数组
* @return 图片上传的地址
*/
public String saveFile(String bucketName, String modulePath, String fileSuffix, byte[] fileBytes) {
return saveFile(bucketName, getRelativeDir(modulePath) + getFileName(fileSuffix), fileBytes);
}
/**
* 腾讯云上传文件
* 返回的路径:{@code PATH_COMMON / modulePath / calculatePath() /UUID.randomUUID() + fileSuffix}
*
* @param relativePath 上传文件的相对地址
* @param fileBytes 文件流
* @return 保存到腾讯云的地址
*/
@Override
public String saveFile(String relativePath, byte[] fileBytes) {
//读取配置信息的存储桶信息
return saveFile(bucketName, relativePath, fileBytes);
}
/**
* 腾讯云上传文件
*
* @param bucketName 存储桶
* @param relativePath 文件的相对地址
* @param fileBytes 文件流的字节数组
* @return 腾讯云上的相对地址
*/
public String saveFile(String bucketName, String relativePath, byte[] fileBytes) {
client.uploadFile(bucketName, relativePath, fileBytes);
return relativePath;
}
/**
* 文件下载
* 若下载失败或者照片不存在,抛出{@link com.xdf.pscommon.os.exception.OsException}异常。
*
* @param filePath 文件地址
* @return 文件输出流
*/
@Override
public ByteArrayOutputStream downloadFile(String filePath) {
return client.downloadFile(filePath);
}
/**
* 获取腾讯云的前缀地址
*
* @return 腾讯云的CDN地址
*/
public String getCdnHost() {
return cdnHost;
}
/**
* 创建文件夹的相对路径
*
* @return 格式:{@code exam/modulePath/2021/11/1}
*/
protected String getRelativeDir(String modulePath) {
return PATH_COMMON + File.separator + modulePath + File.separator + calculatePath();
}
/**
* 创建文件名(使用UUID创建)
*/
protected String getFileName(String fileSuffix) {
return UUID.randomUUID() + fileSuffix;
}
/**
* 时间戳作为路径名
*/
protected String calculatePath() {
Calendar calendar = Calendar.getInstance();
String year = String.valueOf(calendar.get(Calendar.YEAR));
String month = String.valueOf(calendar.get(Calendar.MONTH) + 1);
String date = String.valueOf(calendar.get(Calendar.DATE));
return year + "/" + month + "/" + date + "/";
}
}
2.4.2 挂载盘存储的template
挂载盘在创建目录时,需要随机路由到不同的挂载盘上,所以需要重写getRelativeDir
方法即可。
public class FileOsTemplate extends NetOsTemplate {
private long index;
private final static String ROOTPATH = "rootPath";
private final static String FORWARDMARK = "forwardMark";
/**
* 路径填充挂载盘路径
*/
@Override
public String getRelativeDir(String modulePath) {
OperatingSystemEnum operatingSystem = IOUtil.getOperatingSystem();
if (OperatingSystemEnum.LINUX.equals(operatingSystem) &&
osConfigProperties.getFile().getRootPath() != null &&
osConfigProperties.getFile().getRootPath().size() > 1) {
Map<String, String> rootPathMap = returnRootPathMap(osConfigProperties.getFile().getRootPath());
return PATH_COMMON + File.separator + rootPathMap.get(FORWARDMARK) + File.separator + modulePath + File.separator + calculatePath();
} else {
return super.getRelativeDir(modulePath);
}
}
/**
* 返回挂载盘的具体配置
*/
private Map<String, String> returnRootPathMap(Map<String, String> rootPaths) {
int size = 2; //最少有个原磁盘以及加的共享盘,共享磁盘个数
if (rootPaths != null && rootPaths.size() > 1) {
size = rootPaths.size() - 1;
}
int rootPathIndex = Math.toIntExact(index++ % size);
Map<String, String> rootPathMap = new HashMap<>();
switch (rootPathIndex) {
case 0:
rootPathMap.put(ROOTPATH, rootPaths.get("files1"));
rootPathMap.put(FORWARDMARK, "files1/");
break;
case 1:
rootPathMap.put(ROOTPATH, rootPaths.get("files2"));
rootPathMap.put(FORWARDMARK, "files2/");
break;
case 2:
rootPathMap.put(ROOTPATH, rootPaths.get("files3"));
rootPathMap.put(FORWARDMARK, "files3/");
break;
default:
rootPathMap.put(ROOTPATH, rootPaths.get("files"));
rootPathMap.put(FORWARDMARK, "files/");
break;
}
return rootPathMap;
}
}
2.5 加入到Spring容器中
- 使用
@ConditionalOnClass
注解,当某个依赖存在时,才加载bean类; - 使用
@ConditionalOnProperty
注解,当某个配置存在时,才加载bean类; - 使用
@Import
注解,当多个配置均存在时,优先加载哪个配置; - 配合
@ConditionalOnMissingBean(name = "netOsTemplate")
注解,当加载某个配置后,便不加载同名的bean。
2.5.1 配置类
当本地磁盘加载时,支持windows,mac,linux各个配置。
@Data
@ConfigurationProperties("xos")
public class OsConfigProperties {
/**
* 腾讯云COS配置
*/
private CosProperties cos;
/**
* 阿里云OOS配置
*/
private OssProperties oss;
/**
* 共享盘文件存储配置
*/
private FileProperties file;
/**
* 云存储——存储桶
*/
private String bucketName;
/**
* 云存储——cdn地址
*/
private String cdnHost;
@Data
public static class CosProperties {
private String accessKeyId;
private String accessKeySecret;
private String region;
}
@Data
public static class OssProperties {
private String endpoint;
private String accessKeyId;
private String accessKeySecret;
}
@Data
public static class FileProperties {
/**
* Linux支持的根路径
*/
private String linuxRootPath;
/**
* window支持的根路径
*/
private String windowsRootPath;
/**
* mac支持的根路径
*/
private String macRootPath;
/**
* Linux系统设置,挂载盘映射关系
*/
private Map<String, String> rootPath;
/**
* cdn地址
*/
private String cdnHost;
}
}
2.5.2 腾讯云cos的client加入到Spring中
只有存在COSClient.class
类且存在xos.cos.accessKeyId
配置时,才会加载改bean。
@Configuration
@ConditionalOnClass(COSClient.class)
public class CosClientConfiguration {
/**
* 初始化腾讯云客户端
*/
@Bean(name = "netOSClient", destroyMethod = "shutdown")
@ConditionalOnProperty("xos.cos.accessKeyId")
@ConditionalOnMissingBean(name = "netOSClient")
public OSClient cosClient(OsConfigProperties osConfigProperties) {
CosClient cosClient = new CosClient();
OsConfigProperties.CosProperties cosProperties = osConfigProperties.getCos();
// 1 初始化用户身份信息(secretId, secretKey)。
COSCredentials cred = new BasicCOSCredentials(cosProperties.getAccessKeyId(), cosProperties.getAccessKeySecret());
// 2 设置 bucket 的区域, COS 地域的简称请参照 https://cloud.tencent.com/document/product/436/6224
// clientConfig 中包含了设置 region, https(默认 http), 超时, 代理等 set 方法, 使用可参见源码或者常见问题 Java SDK 部分。
Region cosRegion = new Region(cosProperties.getRegion());
ClientConfig clientConfig = new ClientConfig(cosRegion);
// 3 生成 cos 客户端。
COSClient cosClient = new COSClient(cred, clientConfig);
cosClient.setCosClient(cosClient);
return cosClient;
}
}
2.5.3 阿里云oss的client加入到Spring容器
@Configuration
@ConditionalOnClass(OSSClient.class)
public class OssClientConfiguration {
/**
* 初始化阿里云oss客户端
*/
@Bean(name = "netOSClient", destroyMethod = "shutdown")
@ConditionalOnProperty("xos.oss.accessKeyId")
@ConditionalOnMissingBean(name = "netOSClient")
public OSClient ossClient(OsConfigProperties osConfigProperties) {
OssClient ossClient = new OssClient();
OsConfigProperties.OssProperties ossProperties = osConfigProperties.getOss();
OSSClient ossClient = new OSSClient(ossProperties.getEndpoint(), ossProperties.getAccessKeyId(), ossProperties.getAccessKeySecret());
ossClient.setOssClient(ossClient);
return ossClient;
}
}
2.5.4 自动装配的config
-
@EnableConfigurationProperties
将配置文件类加入到Spring容器; -
@Import({CosClientConfiguration.class,OssClientConfiguration.class})
将config类加入到Spring容器;
@Slf4j
@Configuration
@EnableConfigurationProperties(value = OsConfigProperties.class)
@Import({CosClientConfiguration.class,OssClientConfiguration.class})
public class OSAutoConfiguration {
/**
* 初始化文件流客户端
*/
@Bean
@ConditionalOnMissingBean(name = "fileClient")
public lFileOsClient fileClient(OsConfigProperties osConfigProperties) {
return new FileOsClient();
}
/**
* 创建云存储的模板类
*
* @param oSClient cos的客户端
* @param osConfigProperties 配置信息
* @return 模板工具类
*/
@Bean
@Primary
@ConditionalOnBean(name = {"netOSClient"})
@ConditionalOnMissingBean(name = "netOsTemplate")
public NetOsTemplate netOsTemplate(@Qualifier("netOSClient") OSClient oSClient, OsConfigProperties osConfigProperties) {
NetOsTemplate osTemplate = new NetOsTemplate();
//放入客户端
osTemplate.setClient(oSClient);
osTemplate.setBucketName(osConfigProperties.getBucketName());
//配置文件
osTemplate.setOsConfigProperties(osConfigProperties);
osTemplate.setCdnHost(osConfigProperties.getCdnHost());
return osTemplate;
}
/**
* 共享盘OS的模板类
*/
@Bean
@ConditionalOnMissingBean(name = "fileOsTemplate")
public OsTemplate fileOsTemplate(FileOsClient cosClient, OsConfigProperties osConfigProperties) {
FileOsTemplate osTemplate = new FileOsTemplate();
//放入客户端
osTemplate.setClient(cosClient);
OperatingSystemEnum operatingSystem = IOUtil.getOperatingSystem();
osConfigProperties.FileProperties fileProperties =osConfigProperties.getFile();
//获取对应的根路径
String bucketName = null;
String cdnHost = null;
if (fileProperties != null) {
if (OperatingSystemEnum.WINDOWS.equals(operatingSystem)) {
bucketName = fileProperties.getWindowsRootPath();
} else if (OperatingSystemEnum.MAC.equals(operatingSystem)) {
bucketName = fileProperties.getMacRootPath();
} else {
bucketName = fileProperties.getLinuxRootPath();
}
cdnHost = fileProperties.getCdnHost();
}
if (bucketName == null) {
log.warn("File root path is null. use '/' is root");
//默认是根路径
bucketName = "/";
}
if (cdnHost == null) {
log.warn("File cdnHost is null.");
}
osTemplate.setCdnHost(cdnHost);
//设置存储名字
osTemplate.setBucketName(bucketName);
//配置文件
osTemplate.setOsConfigProperties(osConfigProperties);
return osTemplate;
}
}
2.6 工具类
@Slf4j
public abstract class IOUtil {
/**
* 输入流转换为输出流
*
* @param is 输入流
* @return 输出流
*/
public static ByteArrayOutputStream convertInputStream(InputStream is) {
final byte[] by = new byte[1024];
ByteArrayOutputStream data = new ByteArrayOutputStream();
try {
// 将内容读取内存中
int len;
while ((len = is.read(by)) != -1) {
data.write(by, 0, len);
}
} catch (IOException e) {
log.error("convertInputStream IO Exception", e);
}
return data;
}
/**
* base64转化为byte[]字节流
*
* @param base64Str 照片的base64
* @return 字节流
*/
public static byte[] base64ToBytes(String base64Str) {
if (StringUtils.isBlank(base64Str)) {
throw new SealOsException("base64Str is blank!");
}
return Base64.decodeBase64(base64Str);
}
/**
* 获取文件输入流
*
* @param file 文件对象
* @return 文件输入流对象
*/
public static InputStream getInputStream(File file) {
FileInputStream fin;
try {
fin = new FileInputStream(file);
} catch (FileNotFoundException e) {
if (log.isDebugEnabled()) {
log.debug(String.valueOf(e));
}
String msg = "找不到指定的文件[" + file.getName() + "]。";
if (log.isDebugEnabled()) {
log.debug(msg);
}
throw new SealOsException(msg, e);
}
return fin;
}
/**
* 获取当前系统的操作系统类型
*/
public static OperatingSystemEnum getOperatingSystem() {
if (System.getProperty("os.name").toUpperCase().contains("WINDOWS")) {
return OperatingSystemEnum.WINDOWS;
} else if (System.getProperty("os.name").toUpperCase().contains("MAC")) {
return OperatingSystemEnum.MAC;
} else {
return OperatingSystemEnum.LINUX;
}
}
/**
* 文件后缀
*
* @param fileName 文件名或者文件路径
* @return 后缀类型
*/
public static String getFileSuffix(String fileName) {
if (fileName == null) {
return null;
}
return fileName.substring(fileName.lastIndexOf("."));
}
/**
* 获取文件名
*/
public static String getFileName(String filePath) {
if (filePath == null) {
return null;
}
File file=new File(filePath);
return file.getName();
}
/**
* 获取目录
*/
public static String getDirName(String filePath) {
if (filePath == null) {
return null;
}
File file=new File(filePath);
return file.getParent();
}
}
public abstract class OkHttpUtil {
/**
* 最大连接时间
*/
public final static int CONNECTION_TIMEOUT = 15;
public final static Logger logger = LoggerFactory.getLogger(OkHttpUtil.class);
/**
* client
* 配置重试
*/
private final static OkHttpClient HTTP_CLIENT = new OkHttpClient.Builder()
.connectTimeout(CONNECTION_TIMEOUT, TimeUnit.SECONDS)
.build();
/**
* get请求,无需转换对象
*
* @param url 链接
* @return 响应信息
*/
public static ByteArrayOutputStream get(String url) {
try {
Request request = new Request.Builder().url(url).build();
Response response = HTTP_CLIENT.newCall(request).execute();
if (response.isSuccessful() && response.body() != null) {
InputStream inputStream = response.body().byteStream();
return IOUtil.convertInputStream(inputStream);
}
} catch (Exception e) {
logger.error("执行get请求,url: {} 失败!", url, e);
throw new SealOsException(e);
}
return null;
}
}
2.7 异常类
public class OsException extends RuntimeException {
public OsException() {
}
public OsException(String message) {
super(message);
}
public OsException(String message, Throwable cause) {
super(message, cause);
}
public OsException(Throwable cause) {
super(cause);
}
public OsException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}