1.什么是策略模式
在策略模式中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为模式。在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的上下文对象。策略对象更改上下文对象的执行算法。
2.策略模式具体实现
2.1 创建项目
新建一个SpringBoot项目
2.2 策略接口
- 首先我们新建一个名称为
strategy
的文件夹(在代码规范中,使用设计模式要明确的体现出来,便于后期维护) - 代码如下
/**
* @Author: hec
* @Date: 2024/4/5
* @Email: 2740860037@qq.com
* @Description: 文件上传策略接口
*/
public interface UploadStrategy {
R upload(MultipartFile img);
}
2.3 配置文件
- 总体配置文件
# 上传模式 策略模式 可选 oss或local
upload:
mode: local
local:
url: # 访问路径
path: # 文件存储路径
aliyun:
url: # 访问路径
endpoint: # 地区节点
keyid: # keyid
keysecret: # keysecret
bucketname: # 桶名称
qiniu:
url: # 访问路径
accessKey: # accessKey
accessSecretKey: # accessSecretKey
bucketname: # 桶名称
2.4 策略内部实现
2.4.1 本地上传
/**
* @Author: hec
* @Date: 2024/4/5
* @Email: 2740860037@qq.com
* @Description: 本地上传实现
*/
@Service
public class LocalUploadStrategyImpl implements UploadStrategy {
@Value("${upload.local.url}")
private String url;
@Value("${upload.local.path}")
private String path;
@Override
public R upload(MultipartFile img) {
try {
String filename = img.getOriginalFilename();
String uuid = UUID.randomUUID().toString().replace("-", "");
filename = uuid + filename;
String datePath = new DateTime().toString("yyyyMMdd");
filename = datePath + "/" + filename;
// 判断目录是否存在
File directory = new File(path + datePath);
if (!directory.exists()){
directory.mkdirs();
}
File newFile = new File(path + filename);
img.transferTo(newFile);
String fileUrl = url + filename;
return R.okResult(fileUrl);
} catch (IOException e) {
e.printStackTrace();
throw new ServiceException(HttpCodeEnum.FILE_TYPE_ERROR);
}
}
}
2.4.2 阿里云OSS
- 读取配置文件信息
@Data
@Configuration
@ConfigurationProperties(prefix = "upload.aliyun")
public class AliYunConfigProperties {
//读取配置文件内容
private String url;
private String endpoint;
private String keyId;
private String keySecret;
private String bucketName;
}
- 实现代码
/**
* @Author: hec
* @Date: 2024/4/5
* @Email: 2740860037@qq.com
* @Description: 阿里云上传实现
*/
@Service
public class AliYunUploadStrategyImpl implements UploadStrategy {
@Autowired
AliYunConfigProperties aliYunConfigProperties;
@Override
public R upload(MultipartFile img) {
try {
OSS ossClient = new OSSClientBuilder().build(aliYunConfigProperties.getEndpoint(),
aliYunConfigProperties.getKeyId(), aliYunConfigProperties.getKeySecret());
InputStream inputStream = img.getInputStream();
String filename = img.getOriginalFilename();
String uuid = UUID.randomUUID().toString().replace("-", "");
filename = uuid + filename;
String datePath = new DateTime().toString("yyyy/MM/dd");
filename = datePath + "/" + filename;
ossClient.putObject(aliYunConfigProperties.getBucketName(), filename, inputStream);
ossClient.shutdown();
String url = aliYunConfigProperties.getUrl() + filename;
return R.okResult(url);
} catch (IOException e) {
e.printStackTrace();
throw new ServiceException(HttpCodeEnum.FILE_TYPE_ERROR);
}
}
}
2.4.3 七牛云OSS
- 读取配置信息
@Data
@Configuration
@ConfigurationProperties(prefix = "upload.qiniu")
public class QiNiuConfigProperties {
//读取配置文件内容
private String url;
private String accessKey;
private String accessSecretKey;
private String bucketName;
}
- 代码实现
/**
* @Author: hec
* @Date: 2024/4/5
* @Email: 2740860037@qq.com
* @Description: 七牛云文件上传实现
*/
@Service
public class QiNiuUploadStrategyImpl implements UploadStrategy {
@Autowired
QiNiuConfigProperties qiNiuConfigProperties;
@Override
public R upload(MultipartFile img) {
try {
// 指定 Region 对象的配置类 根据自己的对象空间的地址选
Configuration configuration = new Configuration(Region.huanan());
UploadManager uploadManager = new UploadManager(configuration);
// 获取七牛云提供的 token
Auth auth = Auth.create(qiNiuConfigProperties.getAccessKey(), qiNiuConfigProperties.getAccessSecretKey());
String upToken = auth.uploadToken(qiNiuConfigProperties.getBucketName());
byte[] fileBytes = img.getBytes();
String filename = img.getOriginalFilename();
String uuid = UUID.randomUUID().toString().replace("-", "");
filename = uuid + filename;
String datePath = new DateTime().toString("yyyy/MM/dd");
filename = datePath + "/" + filename;
uploadManager.put(fileBytes,filename,upToken);
String url = qiNiuConfigProperties.getUrl() + filename;
return R.okResult(url);
} catch (IOException e) {
e.printStackTrace();
throw new ServiceException(HttpCodeEnum.FILE_TYPE_ERROR);
}
}
}
2.5 策略上下文
- 新建策略枚举类
@Getter
@AllArgsConstructor
public enum UploadModeEnum {
/**
* aliyun
*/
AliYun("aliyun", "aliYunUploadStrategyImpl"),
/**
* 千牛云
*/
QiNiu("qiniu", "qiNiuUploadStrategyImpl"),
/**
* 本地
*/
LOCAL("local", "localUploadStrategyImpl");
/**
* 模式
*/
private final String mode;
/**
* 策略
*/
private final String strategy;
/**
* 获取策略
*
* @param mode 模式
* @return {@link String} 搜索策略
*/
public static String getStrategy(String mode) {
for (UploadModeEnum value : UploadModeEnum.values()) {
if (value.getMode().equals(mode)) {
return value.getStrategy();
}
}
return null;
}
}
- 代码实现
/**
* @Author: hec
* @Date: 2024/4/5
* @Email: 2740860037@qq.com
* @Description: 文件上传上下文
*/
@Service
public class UploadStrategyContext {
/**
* 上传模式
*/
@Value("${upload.mode}")
private String uploadMode;
@Autowired
private Map<String, UploadStrategy> uploadStrategyMap;
/**
* 执行上传策略
*
* @param img 文件
* @return {@link R} 文件地址
*/
public R executeUploadStrategy(MultipartFile img) {
return uploadStrategyMap.get(getStrategy(uploadMode)).upload(img);
}
}
3.总结
上述只是对于策略模式的简单实践。
我们可以通过网站全局配制结合前端界面来完成选择使用哪个平台来进行文件的上传。
当我们选中哪种上传模式,那么后台则会执行该上传方式