項目中咱們可能會遇到上傳文件到雲上,有阿里, 百度雲BOS(Baidu Object Storage), 騰訊COS(Cloud Object Storage), 七牛 等等, 統一名稱都叫 對象存儲服務. 這裏不主要講文件上傳,由於官方給的文檔已經很是很是的詳細啦, 我主要寫一下在這個文件上傳的過程當中工廠模式的應用;java
COS文檔: https://cloud.tencent.com/document/product/436/12263#object-api-.E6.8F.8F.E8.BF web
工廠模式, 什麼是工廠模式? 我想在spring使用了這麼久,仍然不知道的話,那就和我同樣啦. spring
維基百科的解釋: apache
工廠方法模式(英語:Factory method pattern)是一種實現了「工廠」概念的面向對象設計模式。就像其餘建立型模式同樣,它也是處理在不指定對象具體類型的狀況下建立對象的問題。工廠方法模式的實質是「定義一個建立對象的接口,但讓實現這個接口的類來決定實例化哪一個類。工廠方法讓類的實例化推遲到子類中進行。」設計模式
建立一個對象經常須要複雜的過程,因此不適合包含在一個複合對象中。建立對象可能會致使大量的重複代碼,可能會須要複合對象訪問不到的信息,也可能提供不了足夠級別的抽象,還可能並非複合對象概念的一部分。工廠方法模式經過定義一個單獨的建立對象的方法來解決這些問題。由子類實現這個方法來建立具體類型的對象。api
整理一下,具體的意思就是 爲了方便拓展和下降耦合,將複雜的多樣的而且有有相同功能的對象進行抽象,由不一樣的子類來實現不一樣的功能, 由工廠負責進行子類的實例化.七牛雲存儲
1, 咱們進行騰訊雲的對象操做,固然少不了他們的SDK:app
<dependency> <!-- 騰訊雲 --> <groupId>com.qcloud</groupId> <artifactId>cos_api</artifactId> <version>5.4.2</version> </dependency>
2, application.properties 中的自定義配置:dom
#騰訊雲 oss.cloud.type=1 oss.cloud.qcloudDomain=https://xxxxx-xxxxxxxx.cos.ap-chengdu.myqcloud.com oss.cloud.qcloudRegion=ap-chengdu oss.cloud.qcloudSecretId=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx oss.cloud.qcloudSecretKey=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx oss.cloud.qcloudBucketName=xxxxx-xxxxxxxxxxx
3, bean 配置: CloudConfig.javaide
package com.gy.fast.common.config.oss; import org.hibernate.validator.constraints.Range; import org.hibernate.validator.constraints.URL; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; import com.gy.fast.common.validator.AliyunGroup; import com.gy.fast.common.validator.QcloudGroup; import com.gy.fast.common.validator.QiniuGroup; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; /** * 雲存儲配置信息 * @author geYang * @date 2018-05-21 */ @Component @ConfigurationProperties(prefix = "oss.cloud") public class CloudConfig { /** * 類型 0:本地, 1:騰訊, 2:阿里雲 , 3:七牛 */ private Integer type; /** * 騰訊雲綁定的域名 */ private String qcloudDomain; /** * 騰訊雲路徑前綴 */ private String qcloudPrefix; /** * 騰訊雲AppId */ private String qcloudAppId; /** * 騰訊雲SecretId */ private String qcloudSecretId; /** * 騰訊雲SecretKey */ private String qcloudSecretKey; /** * 騰訊雲BucketName */ private String qcloudBucketName; /** * 騰訊雲COS所屬地區 */ private String qcloudRegion; // get / set // toString() }
4, 到工廠模式啦, 首先咱們要將上傳的方法抽象出來
package com.gy.fast.common.config.oss; import java.io.IOException; import java.util.Date; import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.web.multipart.MultipartFile; import com.gy.fast.common.util.DateUtil; /** * 文件上傳基礎類 * @author geYang * @date 2018-05-21 */ public abstract class BaseUpload { /** * 生成上傳文件名(key:COS的文件路徑,即從Bucket根路徑開始) * @param file 文件 * @param path 目錄 * @return 上傳文件名 * @author geYang * @date 2018-05-21 17:51 */ protected final String getKey(MultipartFile file, String path) { // 獲取文件原先名稱 String originalName = file.getOriginalFilename(); // 取到上傳圖片的後綴名 String suffix= originalName.substring(originalName.lastIndexOf(".")); // 生成新的文件名 StringBuffer key = new StringBuffer(); if (!StringUtils.isBlank(path)) { key.append(path).append("/"); } key.append(DateUtil.format(new Date(),"yyyyMMddHHmmss")) .append(RandomStringUtils.randomAlphabetic(5)) .append(suffix); return key.toString(); } /** * 獲取訪問路徑 * @param domain 訪問域名 * @param key 文件名稱 * @return 訪問路徑 * @author geYang * @date 2018-05-22 17:57 */ protected final String getUrl (String domain, String key) { return domain + "/" + key; } /** * 文件上傳 * @param file * @param path * @return 文件訪問連接 * @throws IOException * @author geYang * @date 2018-05-22 10:09 */ public abstract String upload(MultipartFile file, String path) throws IOException; /** * 文件刪除 * @param key 文件訪問路徑 * @author geYang * @date 2018-05-22 10:13 */ public abstract void delete(String url); }
5, 編寫COS上傳的實現:
package com.gy.fast.common.config.oss; 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.model.ObjectMetadata; import com.qcloud.cos.model.PutObjectResult; import com.qcloud.cos.region.Region; import org.apache.commons.lang3.StringUtils; import org.springframework.web.multipart.MultipartFile; import java.io.FileInputStream; import java.io.IOException; /** * 騰訊雲存儲 * @author geYang * @date 2018-05-21 */ public class QcloudUpload extends BaseUpload { private CloudConfig cloudConfig; // 加載配置文件 public QcloudUpload(CloudConfig cloudConfig) { this.cloudConfig = cloudConfig; } /** * 生成COS客戶端 * @return * @author geYang * @date 2018-05-21 16:34 */ private COSClient getCosClient() { System.err.println(cloudConfig); System.err.println(cloudConfig.getQcloudSecretId()); System.err.println(cloudConfig.getQcloudSecretKey()); // 1 初始化用戶身份信息(secretId, secretKey) COSCredentials cred = new BasicCOSCredentials(cloudConfig.getQcloudSecretId(), cloudConfig.getQcloudSecretKey()); // 2設置bucket的區域, COS地域的簡稱請參照 https://cloud.tencent.com/document/product/436/6224 ClientConfig clientConfig = new ClientConfig(new Region(cloudConfig.getQcloudRegion())); // 3生成COS客戶端 COSClient cosclient = new COSClient(cred, clientConfig); return cosclient; } /** * 文件上傳 * @param path * @param file * @return 訪問路徑 * @throws IOException * @author geYang * @date 2018-05-21 16:33 */ @Override public String upload(MultipartFile file, String path) throws IOException { FileInputStream fileInputStream = (FileInputStream) file.getInputStream(); ObjectMetadata objectMetadata = new ObjectMetadata(); // 設置輸入流長度(需提早告知輸入流的長度,不然可能致使OOM) objectMetadata.setContentLength(file.getSize()); String key = getKey(file, path); COSClient cosClient = getCosClient(); PutObjectResult putObjectResult = cosClient.putObject(cloudConfig.getQcloudBucketName(), key, fileInputStream, objectMetadata); String etag = putObjectResult.getETag(); cosClient.shutdown(); if (StringUtils.isBlank(etag)) { return null; } // 訪問路徑 return getUrl(cloudConfig.getQcloudDomain(), key); } /** * 刪除文件 * @param key * @author geYang * @date 2018-05-21 16:33 */ @Override public void delete(String url) { String bucketName = cloudConfig.getQcloudBucketName(); // 截取域名以後的文件名 String key = url.substring(bucketName.length()+1); COSClient cosClient = getCosClient(); // 進行刪除 cosClient.deleteObject(cloudConfig.getQcloudBucketName(), key); cosClient.shutdown(); } }
6, 編寫工廠進行實實例化上傳類, 經過調用該工廠,來完成上傳任務.
package com.gy.fast.common.config.oss; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; /** * 上傳文件工廠 * @author geYang * @date 2018-05-22 */ @Component public final class UploadFactory { /** * 雲配置信息 */ @Autowired private CloudConfig cloudConfig; /** * 實例化上傳類 * @return * @author geYang * @date 2018-05-22 18:20 */ public BaseUpload build() { int type = cloudConfig.getType(); if (type == 1) { System.out.println("騰訊雲存儲"); return new QcloudUpload(cloudConfig); } if (type == 2) { System.out.println("阿里雲存儲"); return new BaiduyunUpload(cloudConfig); } if (type == 3) { System.out.println("七牛雲存儲"); return new QiiuUpload(cloudConfig); } else { System.out.println("本地存儲"); return new MyUpload(); } } }
7, 調用應用:
package com.gy.fast.module.sys.controller; import org.apache.shiro.authz.annotation.RequiresPermissions; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import com.gy.fast.common.config.oss.UploadFactory; import com.gy.fast.common.util.R; /** * 文件上傳 * @author geYang * @date 2018-05-21 */ @RestController public class SysOssController { @Autowired protected UploadFactory uploadFactory; /** * 上傳文件 */ @PostMapping("/upload") public R upload(@RequestParam("file") MultipartFile file) throws Exception { System.out.println(getUser()); if (file.isEmpty()) { throw new SysException("上傳文件不能爲空"); } //上傳文件 String url = uploadFactory.build().upload(file, ""); System.out.println(url); return R.ok().put("url", url); } }
到此, 關於工廠模式的演示基本完成了, 集成其餘雲存儲配置的話只須要實現BaseUpload就好.