SpringBoot 策略模式實(shí)現(xiàn)切換上傳文件模式
SpringBoot 策略模式
策略模式是指有一定行動內(nèi)容的相對穩(wěn)定的策略名稱。
- 我們定義一個(gè)接口(就比如接下來要實(shí)現(xiàn)的文件上傳接口)
- 我們定義所需要實(shí)現(xiàn)的策略實(shí)現(xiàn)類 A、B、C、D(也就是項(xiàng)目中所使用的四種策略阿里云Oss上傳、騰訊云Cos上傳、七牛云Kodo上傳、本地上傳)
- 我們通過策略上下文來調(diào)用策略接口,并選擇所需要使用的策略
策略接口
public interface UploadStrategy { /** * 上傳文件 * * @param file 文件 * @param filePath 文件上傳露肩 * @return {@link String} 文件上傳的全路徑 */ String uploadFile(MultipartFile file, final String filePath);
策略實(shí)現(xiàn)類內(nèi)部實(shí)現(xiàn)
@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 檢測文件是否已經(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 文件相對路徑 * @return true 已經(jīng)存在 false 不存在 */ public abstract boolean checkFileIsExisted(String fileRelativePath); /** * 執(zhí)行上傳操作 * * @param file 文件 * @param fileRelativePath 文件相對路徑 * @throws IOException io異常信息 */ public abstract void executeUpload(MultipartFile file, String fileRelativePath) throws IOException; /** * 獲取公網(wǎng)訪問路徑 * * @param fileRelativePath 文件相對路徑 * @return 公網(wǎng)訪問絕對路徑 */ 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 文件相對路徑 * @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); } }
上傳測試
參考資料:
文章來源:https://mp.weixin.qq.com/s/Bi7tFfKHXpBkXNpbTMR2lg
案例代碼:https://gitcode.net/nanshen__/store-object
到此這篇關(guān)于SpringBoot 策略模式 切換上傳文件模式的文章就介紹到這了,更多相關(guān)SpringBoot 策略模式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot實(shí)現(xiàn)統(tǒng)一功能處理的教程詳解
這篇文章主要為大家詳細(xì)介紹了SpringBoot如何實(shí)現(xiàn)統(tǒng)一功能處理,文中的示例代碼講解詳細(xì),對大家學(xué)習(xí)或工作有一定借鑒價(jià)值,感興趣的同學(xué)可以參考閱讀下2023-05-05Java使用freemarker實(shí)現(xiàn)word下載方式
文章介紹了如何使用FreeMarker實(shí)現(xiàn)Word文件下載,包括引用依賴、創(chuàng)建Word模板、將Word文件存為XML格式、更改后綴為FTL模板、處理圖片和代碼實(shí)現(xiàn)2025-02-02詳解JavaScript中的函數(shù)聲明和函數(shù)表達(dá)式
這篇文章主要介紹了詳解JavaScript中的函數(shù)聲明和函數(shù)表達(dá)式,是JS入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下2015-08-08關(guān)于StringUtils.isBlank()的使用及說明
這篇文章主要介紹了關(guān)于StringUtils.isBlank()的使用及說明,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-05-05java自定義注解實(shí)現(xiàn)前后臺參數(shù)校驗(yàn)的實(shí)例
下面小編就為大家?guī)硪黄猨ava自定義注解實(shí)現(xiàn)前后臺參數(shù)校驗(yàn)的實(shí)例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-11-11解決@DateTimeFormat格式化時(shí)間出錯問題
這篇文章主要介紹了解決@DateTimeFormat格式化時(shí)間出錯問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-12-12