SpringBoot 策略模式實(shí)現(xiàn)切換上傳文件模式
SpringBoot 策略模式
策略模式是指有一定行動(dòng)內(nèi)容的相對(duì)穩(wěn)定的策略名稱(chēng)。
- 我們定義一個(gè)接口(就比如接下來(lái)要實(shí)現(xiàn)的文件上傳接口)
- 我們定義所需要實(shí)現(xiàn)的策略實(shí)現(xiàn)類(lèi) A、B、C、D(也就是項(xiàng)目中所使用的四種策略阿里云Oss上傳、騰訊云Cos上傳、七牛云Kodo上傳、本地上傳)
- 我們通過(guò)策略上下文來(lái)調(diào)用策略接口,并選擇所需要使用的策略

策略接口
public interface UploadStrategy {
/**
* 上傳文件
*
* @param file 文件
* @param filePath 文件上傳露肩
* @return {@link String} 文件上傳的全路徑
*/
String uploadFile(MultipartFile file, final String filePath); 策略實(shí)現(xiàn)類(lèi)內(nèi)部實(shí)現(xiàn)
@Getter
@Setter
public abstract class AbstractUploadStrategyImpl implements UploadStrategy {
@Override
public String uploadFile(MultipartFile file, String filePath) {
try {
//region 獲取文件md5值 -> 獲取文件后綴名 -> 生成相對(duì)路徑
String fileMd5 = XcFileUtil.getMd5(file.getInputStream());
String extName = XcFileUtil.getExtName(file.getOriginalFilename());
String fileRelativePath = filePath + fileMd5 + extName;
//endregion
//region 初始化
initClient();
//endregion
//region 檢測(cè)文件是否已經(jīng)存在,不存在則進(jìn)行上傳操作
if (!checkFileIsExisted(fileRelativePath)) {
executeUpload(file, fileRelativePath);
}
//endregion
return getPublicNetworkAccessUrl(fileRelativePath);
} catch (IOException e) {
throw new XcException("文件上傳失敗");
}
}
/**
* 初始化客戶端
*/
public abstract void initClient();
/**
* 檢查文件是否已經(jīng)存在(文件MD5值唯一)
*
* @param fileRelativePath 文件相對(duì)路徑
* @return true 已經(jīng)存在 false 不存在
*/
public abstract boolean checkFileIsExisted(String fileRelativePath);
/**
* 執(zhí)行上傳操作
*
* @param file 文件
* @param fileRelativePath 文件相對(duì)路徑
* @throws IOException io異常信息
*/
public abstract void executeUpload(MultipartFile file, String fileRelativePath) throws IOException;
/**
* 獲取公網(wǎng)訪問(wèn)路徑
*
* @param fileRelativePath 文件相對(duì)路徑
* @return 公網(wǎng)訪問(wèn)絕對(duì)路徑
*/
public abstract String getPublicNetworkAccessUrl(String fileRelativePath);
} 本地上傳策略具體實(shí)現(xiàn)
@Slf4j
@Getter
@Setter
@RequiredArgsConstructor
@Service("localUploadServiceImpl")
public class LocalUploadStrategyImpl extends AbstractUploadStrategyImpl {
/**
* 本地項(xiàng)目端口
*/
@Value("${server.port}")
private Integer port;
/**
* 前置路徑 ip/域名
*/
private String prefixUrl;
/**
* 構(gòu)造器注入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");
}
}
/**
* 檢查文件夾是否存在,若不存在則創(chuàng)建文件夾,最終返回上傳文件
*
* @param fileRelativePath 文件相對(duì)路徑
* @return {@link File} 文件
*/
private File checkFolderIsExisted(String fileRelativePath) {
File rootPath = new File(prefixUrl + fileRelativePath);
if (!rootPath.exists()) {
if (!rootPath.mkdirs()) {
throw new XcException("文件夾創(chuàng)建失敗");
}
}
return rootPath;
}
} 策略上下文實(shí)現(xiàn)
@Component
@RequiredArgsConstructor
public class UploadStrategyContext {
private final Map<String, UploadStrategy> uploadStrategyMap;
/**
* 執(zhí)行上傳策略
*
* @param file 文件
* @param filePath 文件上傳路徑前綴
* @return {@link String} 文件上傳全路徑
*/
public String executeUploadStrategy(MultipartFile file, final String filePath, String uploadServiceName) {
// 執(zhí)行特定的上傳策略
return uploadStrategyMap.get(uploadServiceName).uploadFile(file, filePath);
}
}上傳測(cè)試

參考資料:
文章來(lái)源:https://mp.weixin.qq.com/s/Bi7tFfKHXpBkXNpbTMR2lg
案例代碼:https://gitcode.net/nanshen__/store-object
到此這篇關(guān)于SpringBoot 策略模式 切換上傳文件模式的文章就介紹到這了,更多相關(guān)SpringBoot 策略模式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
mybatis@insert?注解如何判斷insert或是update
這篇文章主要介紹了mybatis@insert?注解如何判斷insert或是update,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07
springboot使用注解實(shí)現(xiàn)鑒權(quán)功能
這篇文章主要介紹了springboot使用注解實(shí)現(xiàn)鑒權(quán)功能,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧2024-12-12
Vue中computed計(jì)算屬性和data數(shù)據(jù)獲取方式
這篇文章主要介紹了Vue中computed計(jì)算屬性和data數(shù)據(jù)獲取方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03
@TableField(typeHandler = FastjsonTypeHandler.clas
文章總結(jié)個(gè)人前端上傳經(jīng)驗(yàn),提出了一些優(yōu)化上傳方法的建議,旨在提高上傳效率和用戶體驗(yàn),希望能為開(kāi)發(fā)者提供參考2026-04-04
Java-文件File簡(jiǎn)單實(shí)用方法(分享)
下面小編就為大家?guī)?lái)一篇Java-文件File簡(jiǎn)單實(shí)用方法(分享)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-08-08

