SpringBoot 策略模式实现切换上传文件模式
作者:草木物语
策略模式是指有一定行动内容的相对稳定的策略名称,这篇文章主要介绍了SpringBoot 策略模式 切换上传文件模式,需要的朋友可以参考下
SpringBoot 策略模式
策略模式是指有一定行动内容的相对稳定的策略名称。
- 我们定义一个接口(就比如接下来要实现的文件上传接口)
- 我们定义所需要实现的策略实现类 A、B、C、D(也就是项目中所使用的四种策略阿里云Oss上传、腾讯云Cos上传、七牛云Kodo上传、本地上传)
- 我们通过策略上下文来调用策略接口,并选择所需要使用的策略

策略接口
public interface UploadStrategy {
/**
* 上传文件
*
* @param file 文件
* @param filePath 文件上传露肩
* @return {@link String} 文件上传的全路径
*/
String uploadFile(MultipartFile file, final String filePath); 策略实现类内部实现
@Getter
@Setter
public abstract class AbstractUploadStrategyImpl implements UploadStrategy {
@Override
public String uploadFile(MultipartFile file, String filePath) {
try {
//region 获取文件md5值 -> 获取文件后缀名 -> 生成相对路径
String fileMd5 = XcFileUtil.getMd5(file.getInputStream());
String extName = XcFileUtil.getExtName(file.getOriginalFilename());
String fileRelativePath = filePath + fileMd5 + extName;
//endregion
//region 初始化
initClient();
//endregion
//region 检测文件是否已经存在,不存在则进行上传操作
if (!checkFileIsExisted(fileRelativePath)) {
executeUpload(file, fileRelativePath);
}
//endregion
return getPublicNetworkAccessUrl(fileRelativePath);
} catch (IOException e) {
throw new XcException("文件上传失败");
}
}
/**
* 初始化客户端
*/
public abstract void initClient();
/**
* 检查文件是否已经存在(文件MD5值唯一)
*
* @param fileRelativePath 文件相对路径
* @return true 已经存在 false 不存在
*/
public abstract boolean checkFileIsExisted(String fileRelativePath);
/**
* 执行上传操作
*
* @param file 文件
* @param fileRelativePath 文件相对路径
* @throws IOException io异常信息
*/
public abstract void executeUpload(MultipartFile file, String fileRelativePath) throws IOException;
/**
* 获取公网访问路径
*
* @param fileRelativePath 文件相对路径
* @return 公网访问绝对路径
*/
public abstract String getPublicNetworkAccessUrl(String fileRelativePath);
} 本地上传策略具体实现
@Slf4j
@Getter
@Setter
@RequiredArgsConstructor
@Service("localUploadServiceImpl")
public class LocalUploadStrategyImpl extends AbstractUploadStrategyImpl {
/**
* 本地项目端口
*/
@Value("${server.port}")
private Integer port;
/**
* 前置路径 ip/域名
*/
private String prefixUrl;
/**
* 构造器注入bean
*/
private final ObjectStoreProperties properties;
@Override
public void initClient() {
try {
prefixUrl = ResourceUtils.getURL("classpath:").getPath() + "static/";
} catch (FileNotFoundException e) {
e.printStackTrace();
throw new XcException("文件不存在");
}
log.info("initClient Init Success...");
}
@Override
public boolean checkFileIsExisted(String fileRelativePath) {
return new File(prefixUrl + fileRelativePath).exists();
}
@Override
public void executeUpload(MultipartFile file, String fileRelativePath) throws IOException {
File dest = checkFolderIsExisted(fileRelativePath);
try {
file.transferTo(dest);
} catch (IOException e) {
e.printStackTrace();
throw new XcException("文件上传失败");
}
}
@Override
public String getPublicNetworkAccessUrl(String fileRelativePath) {
try {
String host = InetAddress.getLocalHost().getHostAddress();
if (StringUtils.isEmpty(properties.getLocal().getDomainUrl())) {
return String.format("http://%s:%d%s", host, port, fileRelativePath);
}
return properties.getLocal().getDomainUrl() + fileRelativePath;
} catch (UnknownHostException e) {
throw new XcException("HttpCodeEnum.UNKNOWN_ERROR");
}
}
/**
* 检查文件夹是否存在,若不存在则创建文件夹,最终返回上传文件
*
* @param fileRelativePath 文件相对路径
* @return {@link File} 文件
*/
private File checkFolderIsExisted(String fileRelativePath) {
File rootPath = new File(prefixUrl + fileRelativePath);
if (!rootPath.exists()) {
if (!rootPath.mkdirs()) {
throw new XcException("文件夹创建失败");
}
}
return rootPath;
}
} 策略上下文实现
@Component
@RequiredArgsConstructor
public class UploadStrategyContext {
private final Map<String, UploadStrategy> uploadStrategyMap;
/**
* 执行上传策略
*
* @param file 文件
* @param filePath 文件上传路径前缀
* @return {@link String} 文件上传全路径
*/
public String executeUploadStrategy(MultipartFile file, final String filePath, String uploadServiceName) {
// 执行特定的上传策略
return uploadStrategyMap.get(uploadServiceName).uploadFile(file, filePath);
}
}上传测试

参考资料:
文章来源:https://mp.weixin.qq.com/s/Bi7tFfKHXpBkXNpbTMR2lg
案例代码:https://gitcode.net/nanshen__/store-object
到此这篇关于SpringBoot 策略模式 切换上传文件模式的文章就介绍到这了,更多相关SpringBoot 策略模式内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
