前提
首先你在阅读我这篇文字的时候可能不是很懂模板模式和策略模式,你可以先去网上看一些文章也可以直接看我写的这篇,仔细看我相信你会明白的。这是一篇有关于实战的文字,我会尽可能说的详细一点,我写这篇文字的初衷,
- 自己总结一下昨天干了些什么
- 巩固一下设计模式
- 给需要的小伙伴分享一下
正文部分
准备
首先在yml配置文件中配置一下上传策略
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| upload: mode: oss local: url: http://你的文件上传子域名/ path: /usr/local/upload/ oss: endpoint: 'xxxxx' accessKeyId: 'xxxxxx' accessKeySecret: 'xxxxxxx' bucketName: 'xxxxxxx'
|
创建一个策略的枚举类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| package com.zang.blogz.enmus;
import cn.hutool.core.util.StrUtil; import com.zang.blogz.steam.stream.Steam; import lombok.AllArgsConstructor; import lombok.Getter;
import java.util.function.Predicate;
@Getter @AllArgsConstructor public enum UploadStrategyEnum {
OSS("oss", "ossUploadStrategyImpl"),
LOCAL("local", "localUploadStrategyImpl");
private final String mode;
private final String strategy;
public static String getStrategy(String mode){
return Steam.of(UploadStrategyEnum.values()).findFirst(strategy(mode)).orElse(OSS).getStrategy();
}
public static Predicate<? super UploadStrategyEnum> strategy(String mode){
return val-> StrUtil.equals(val.getMode(), mode); }
}
|
到时候我们可以通过调用的方法在这里匹配到我们要选择的策略的服务名称,默认为OSS上传服务
创建一个UploadStrategy接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
public interface UploadStrategy {
String uploadFile(MultipartFile file, String path); }
|
我们的策略都会去实现这个接口,因为我们也使用了模板模式到时候只需要抽象模板去实现这个接口就可以了
上传策略上下文
这个类用于我们去进行策略的选择
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
|
@Service public class UploadStrategyContext {
@Value("${upload.mode}") private String uploadMode;
@Autowired private Map<String, UploadStrategy> uploadStrategyMap;
public String executeUploadStrategy(MultipartFile file, String path) {
Opp<String> ofTry = Opp.ofTry(() -> uploadStrategyMap.get(UploadStrategyEnum.getStrategy(uploadMode)) .uploadFile(file, path), NullPointerException.class);
if (Opp.of(ofTry.getException()).isNonNull()) {
throw new BizException("抱歉,请检查配置文件,当前没有你所选择的策略"); } return ofTry.get(); }
}
|
首先从配置文件读到当前选择的上传模式,然后调用我们策略的枚举类里边的方法得到当前使用的策略的服务名称然后从map中通过服务名称拿到服务的实体去执行uploadFile(file, path)方法现在已经选择好了我们的策略了到了我们的抽象模板了
抽象模板
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
|
public abstract class AbstractUploadStrategyImpl implements UploadStrategy {
@Override public String uploadFile(MultipartFile file, String path) {
Opp<String> uploadOpp = Opp.ofTry(() -> { String md5 = FileUtils.getMd5(file.getInputStream()); String extName = FileUtils.getExtName(file.getOriginalFilename()); String fileName = md5 + extName; if (!exists(path + fileName)) { upload(path, fileName, file.getInputStream()); } return getFileAccessUrl(path + fileName); });
if (Opp.of(uploadOpp.getException()).isNonNull()) {
throw new BizException("文件上传失败"); }
return uploadOpp.get(); }
public abstract Boolean exists(String filePath);
public abstract void upload(String path, String fileName, InputStream inputStream) throws IOException;
public abstract String getFileAccessUrl(String filePath); }
|
在抽象模板中去实现UploadStrategy,重写其uploadFile,然后声明三个抽象方法,因为我们的上传总体流程是一样的但是其内部的实现是不一样的,所以这就是我们的模板,我们策略的具体实现只需要继承抽象类并重写这三个方法就可以了
oss上传具体实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
|
@Service("ossUploadStrategyImpl") public class OssUploadStrategyImpl extends AbstractUploadStrategyImpl {
@Autowired private OssConfigProperties ossConfigProperties;
@Value("${upload.oss.bucketName}") private String P;
@Value("${upload.oss.endpoint}") private String I;
@Override public Boolean exists(String filePath) { return getOssClient().doesObjectExist(ossConfigProperties.getBucketName(), filePath); }
@Override public void upload(String path, String fileName, InputStream inputStream) throws IOException {
getOssClient().putObject(ossConfigProperties.getBucketName(), path + fileName, inputStream); }
@Override public String getFileAccessUrl(String filePath) {
String URL = "https://" + P + "." + I + "/";
return URL + filePath; }
private OSS getOssClient(){
return new OSSClientBuilder().build(ossConfigProperties.getEndpoint(), ossConfigProperties.getAccessKeyId(), ossConfigProperties.getAccessKeySecret());
} }
|
local上传实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
| @Service("localUploadStrategyImpl") public class LocalUploadStrategyImpl extends AbstractUploadStrategyImpl{
@Value("${upload.local.path}") private String localPath;
@Value("${upload.local.url}") private String localUrl;
@Override public Boolean exists(String filePath) {
return new File(localPath + filePath).exists(); }
@Override public void upload(String path, String fileName, InputStream inputStream) throws IOException {
File directory = new File(localPath + path);
if (!directory.exists()) {
if (!directory.mkdirs()) {
throw new BizException("创建目录失败"); } } File file = new File(localPath + path + fileName);
if (file.createNewFile()) {
BufferedInputStream bis = new BufferedInputStream(inputStream); BufferedOutputStream bos = new BufferedOutputStream(Files.newOutputStream(file.toPath()));
byte[] bytes = new byte[1024]; int length;
while ((length = bis.read(bytes)) != -1) {
bos.write(bytes, 0, length); }
bos.flush(); inputStream.close(); bis.close(); bos.close(); } }
@Override public String getFileAccessUrl(String filePath) {
return localUrl + filePath; } }
|