唠嗑前言
个人工作开发,备注学习和开源记录!!!
代码比较简单、有点开发技术的应该都看得懂(虽然本人工作五年经验了,但还是小小开发 哈哈哈)
主要是理解设计理念:利用反射机制, 实现租户数据库存各云存储配置、走不同上传方式。
可广泛扩展之类啥的、不仅文件上传,还有发短信、发邮件,希望对长江前后浪开发学习有所帮助。
封装common-dfs包
- 1、定义一个文件上传接口
public interface IDfsBaseService {
/**
* 文件上传接口
*/
FileInfo uploadFile(MultipartFile file) throws Exception;
}
封装commoon-dfs-minio包
- 1、实现上传接口
@Slf4j
@RequiredArgsConstructor
public class MinioFileServiceImpl implements IDfsBaseService {
private final MinioClient minioClient;
private final MinioOssProperties minioOssProperties;
@Override
public FileInfo uploadFile(MultipartFile file) throws Exception {
String fileName = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"))
+ StrUtil.SLASH+ IdUtil.simpleUUID() + StrUtil.DOT + FileUploadUtils.getExtension(file);
minioClient.putObject(PutObjectArgs.builder()
.bucket(minioOssProperties.getBucket())
.stream(file.getInputStream(), file.getSize(), -1)
.contentType(file.getContentType())
.object(fileName)
.build());
//记录下预览地址
String url = minioClient.getPresignedObjectUrl(
GetPresignedObjectUrlArgs.builder()
.method(Method.GET)
.bucket(minioOssProperties.getBucket())
.object(fileName)
// .expiry(1, TimeUnit.DAYS)
.build());
FileInfo fileInfo = new FileInfo();
fileInfo.setFileName(FileUtils.getName(fileName));
fileInfo.setUrl(url);
fileInfo.setType(FileUtil.extName(fileName));
return fileInfo;
}
}
以此类推其它上传方案 如阿里、腾讯、七牛等存储方式
封装commoon-dfs-qiniu包
@Slf4j
@RequiredArgsConstructor
public class QiniuFileImpl implements IDfsBaseService {
@Override
public FileInfo uploadFile(MultipartFile file) throws Exception {
return null;
}
}
封装commoon-dfs-aliyun包
@Slf4j
@RequiredArgsConstructor
public class AliyunFileServiceImpl implements IDfsBaseService {
@Override
public FileInfo uploadFile(MultipartFile file) throws Exception {
return null;
}
}
封装commoon-dfs-tencent包
@Slf4j
@RequiredArgsConstructor
public class TencentFileImpl implements IDfsBaseService {
@Override
public FileInfo uploadFile(MultipartFile file) throws Exception {
return null;
}
}
重点开始-反射
springboot-web实战
- 1、定义个获得租户文件上传工厂类
@Component
public class DfsFactory {
/**
* DfsService 缓存
*/
private final static Map<Long, IDfsBaseService> dfsBaseServiceMap = new ConcurrentHashMap<>();
/**
* 通过反射静态方法获取 DfsService
*
* @param dfsConfig 分布式存储配置
* @return dfsService
*/
public IDfsBaseService getDfsBaseService(DfsConfig dfsConfig) {
//根据dfsId获取对应的分布式存储服务接口,dfsId是唯一的,每个租户有其自有的dfsId
Long dfsId = dfsConfig.getId();
IDfsBaseService dfsBaseService = dfsBaseServiceMap.get(dfsId);
if (null == dfsBaseService) {
Class cls = null;
try {
//获取目标
cls = Class.forName(DfsFactoryClassEnum.getValue(dfsConfig.getDfsType()));
Method staticMethod = cls.getDeclaredMethod("getDfsBaseService", DfsConfig.class);
dfsBaseService = (IDfsBaseService) staticMethod.invoke(cls, dfsConfig);
dfsBaseServiceMap.put(dfsId, dfsBaseService);
} catch (Exception e) {
throw new ServiceException("分布式存储配置错误,上传失败");
}
}
return dfsBaseService;
}
}
- 2、枚举
/**
* 分布式存储工厂类枚举
*/
public enum DfsFactoryClassEnum {
/**
* MINIO
*/
MINIO("minio", "com.lzmh.tools.service.factory.DfsMinioFactory", "MINIO存储"),
/**
* 七牛云
*/
QI_NIU("qiniu", "com.lzmh.tools.service.factory.DfsQiniuFactory", "七牛云存储"),
/**
* 阿里云
*/
ALI_YUN("aliyun", "com.lzmh.tools.service.factory.DfsAliyunFactory", "阿里云存储"),
/**
* 腾讯云
*/
TENCENT("tencent", "com.lzmh.tools.service.factory.DfsTencentFactory", "腾讯云存储");
@Getter
private String code;
@Getter
private String value;
@Getter
private String title;
DfsFactoryClassEnum(String code, String value, String title) {
this.code = code;
this.value = value;
this.title = title;
}
public static String getValue(String code) {
DfsFactoryClassEnum[] smsFactoryClassEnums = values();
for (DfsFactoryClassEnum smsFactoryClassEnum : smsFactoryClassEnums) {
if (smsFactoryClassEnum.getCode().equals(code)) {
return smsFactoryClassEnum.getValue();
}
}
throw new BusinessException("暂未实现该分布式存储实现:" + code );
}
}
- 3、示例 mino工厂、还有DfsQiniuFactory、DfsAliyunFactory、DfsTencentFactory类似
package com.lzmh.tools.service.factory;
/**
* Minio存储工厂类
*
* @author ycs
* @date 2023/8/15
*/
public class DfsMinioFactory {
public static IDfsBaseService getDfsBaseService(DfsConfig dfsConfig) {
MinioClient minioClient =
MinioClient.builder()
.endpoint(dfsConfig.getUploadUrl())
.credentials(dfsConfig.getAccessKey(), dfsConfig.getSecretKey()).build();
MinioOssProperties minioOssProperties = new MinioOssProperties();
minioOssProperties.setAccessKey(dfsConfig.getAccessKey());
minioOssProperties.setSecretKey(dfsConfig.getSecretKey());
minioOssProperties.setRegion(dfsConfig.getRegion());
minioOssProperties.setBucket(dfsConfig.getBucket());
minioOssProperties.setUploadUrl(dfsConfig.getUploadUrl());
return new MinioFileServiceImpl(minioClient, minioOssProperties);
}
}
业务开始使用工厂类上传service
/**
* 文件管理Service业务层处理
*
* @author admin
* @date 2023-08-14
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class DfsFileServiceImpl extends ServicePlusImpl<DfsFileMapper, DfsFile, DfsFile> implements IDfsFileService {
private final DfsConfigMapper dfsConfigMapper;
private final DfsFactory dfsFactory;
@Override
public DfsFile upload(MultipartFile file, String tenantId) {
DfsConfig dfsConfig = dfsConfigMapper.selectOne(Wrappers.<DfsConfig>lambdaQuery()
.eq(DfsConfig::getTenantId, tenantId)
.eq(DfsConfig::getDfsStatus, Boolean.TRUE));
if (dfsConfig == null) {
throw new BusinessException("该租户没有分布式存储配置, 请核查上传配置");
}
// 获取租户上传对象
IDfsBaseService dfsBaseService = dfsFactory.getDfsBaseService(dfsConfig);
DfsFile dfsFile = new DfsFile();
dfsFile.setDfsId(dfsConfig.getId())
.setTenantId(Convert.toLong(tenantId))
.setOriginal(file.getOriginalFilename())
.setFileSize(file.getSize());
try {
// 执行分布式存储上传
FileInfo fileInfo = dfsBaseService.uploadFile(file);
dfsFile.setFileName(fileInfo.getFileName())
.setUrl(fileInfo.getUrl())
.setType(fileInfo.getType())
.setStatus(Boolean.TRUE)
.setMd5(DigestUtils.md5DigestAsHex(file.getInputStream()));
// 文件的MD5值
// String hash = Etag.data(file.getBytes());
return dfsFile;
} catch (Exception e) {
log.warn("租户上传文件异常,检查配置{}", dfsConfig);
dfsFile.setStatus(Boolean.FALSE);
throw new BusinessException(e.getMessage());
} finally {
//保存文件记录
this.save(dfsFile);
}
}
}
项目截图
- 公共包
*实现
鸣谢开源地址:gitee.com/ychunsheng/…