update 补全漏提交文件
This commit is contained in:
parent
c76ab64e8a
commit
fd45cdb882
@ -0,0 +1,14 @@
|
||||
--- # 监控配置
|
||||
spring:
|
||||
boot:
|
||||
admin:
|
||||
# Spring Boot Admin Client 客户端的相关配置
|
||||
client:
|
||||
# 增加客户端开关
|
||||
enabled: true
|
||||
# 设置 Spring Boot Admin Server 地址
|
||||
url: http://localhost:9090/admin
|
||||
instance:
|
||||
prefer-ip: true # 注册实例时,优先使用 IP
|
||||
username: ruoyi
|
||||
password: 123456
|
@ -0,0 +1,14 @@
|
||||
--- # 监控配置
|
||||
spring:
|
||||
boot:
|
||||
admin:
|
||||
# Spring Boot Admin Client 客户端的相关配置
|
||||
client:
|
||||
# 增加客户端开关
|
||||
enabled: true
|
||||
# 设置 Spring Boot Admin Server 地址
|
||||
url: http://172.30.0.90:9090/admin
|
||||
instance:
|
||||
prefer-ip: true # 注册实例时,优先使用 IP
|
||||
username: ruoyi
|
||||
password: 123456
|
66
ruoyi-ui/src/plugins/tab.js
Normal file
66
ruoyi-ui/src/plugins/tab.js
Normal file
@ -0,0 +1,66 @@
|
||||
import store from '@/store'
|
||||
import router from '@/router';
|
||||
|
||||
export default {
|
||||
// 刷新当前tab页签
|
||||
refreshPage(obj) {
|
||||
const { path, matched } = router.currentRoute;
|
||||
if (obj === undefined) {
|
||||
matched.forEach((m) => {
|
||||
if (m.components && m.components.default && m.components.default.name) {
|
||||
if (!['Layout', 'ParentView'].includes(m.components.default.name)) {
|
||||
obj = { name: m.components.default.name, path: path };
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return store.dispatch('tagsView/delCachedView', obj).then(() => {
|
||||
const { path } = obj
|
||||
router.replace({
|
||||
path: '/redirect' + path
|
||||
})
|
||||
})
|
||||
},
|
||||
// 关闭当前tab页签,打开新页签
|
||||
closeOpenPage(obj) {
|
||||
store.dispatch("tagsView/delView", router.currentRoute);
|
||||
if (obj !== undefined) {
|
||||
return router.push(obj);
|
||||
}
|
||||
},
|
||||
// 关闭指定tab页签
|
||||
closePage(obj) {
|
||||
if (obj === undefined) {
|
||||
return store.dispatch('tagsView/delView', router.currentRoute).then(({ lastPath }) => {
|
||||
return router.push(lastPath || '/');
|
||||
});
|
||||
}
|
||||
return store.dispatch('tagsView/delView', obj);
|
||||
},
|
||||
// 关闭所有tab页签
|
||||
closeAllPage() {
|
||||
return store.dispatch('tagsView/delAllViews');
|
||||
},
|
||||
// 关闭左侧tab页签
|
||||
closeLeftPage(obj) {
|
||||
return store.dispatch('tagsView/delLeftTags', obj || router.currentRoute);
|
||||
},
|
||||
// 关闭右侧tab页签
|
||||
closeRightPage(obj) {
|
||||
return store.dispatch('tagsView/delRightTags', obj || router.currentRoute);
|
||||
},
|
||||
// 关闭其他tab页签
|
||||
closeOtherPage(obj) {
|
||||
return store.dispatch('tagsView/delOthersViews', obj || router.currentRoute);
|
||||
},
|
||||
// 添加tab页签
|
||||
openPage(title, url) {
|
||||
var obj = { path: url, meta: { title: title } }
|
||||
store.dispatch('tagsView/addView', obj);
|
||||
return router.push(url);
|
||||
},
|
||||
// 修改tab页签
|
||||
updatePage(obj) {
|
||||
return store.dispatch('tagsView/updateVisitedView', obj);
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package com.ruoyi.common.core.service;
|
||||
|
||||
/**
|
||||
* 通用 参数配置服务
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
public interface ConfigService {
|
||||
|
||||
/**
|
||||
* 根据参数 key 获取参数值
|
||||
*
|
||||
* @param configKey 参数 key
|
||||
* @return 参数值
|
||||
*/
|
||||
String getConfigValue(String configKey);
|
||||
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
package com.ruoyi.common.core.service;
|
||||
|
||||
/**
|
||||
* 通用 字典服务
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
public interface DictService {
|
||||
|
||||
/**
|
||||
* 分隔符
|
||||
*/
|
||||
String SEPARATOR = ",";
|
||||
|
||||
/**
|
||||
* 根据字典类型和字典值获取字典标签
|
||||
*
|
||||
* @param dictType 字典类型
|
||||
* @param dictValue 字典值
|
||||
* @return 字典标签
|
||||
*/
|
||||
default String getDictLabel(String dictType, String dictValue) {
|
||||
return getDictLabel(dictType, dictValue, SEPARATOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据字典类型和字典标签获取字典值
|
||||
*
|
||||
* @param dictType 字典类型
|
||||
* @param dictLabel 字典标签
|
||||
* @return 字典值
|
||||
*/
|
||||
default String getDictValue(String dictType, String dictLabel) {
|
||||
return getDictValue(dictType, dictLabel, SEPARATOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据字典类型和字典值获取字典标签
|
||||
*
|
||||
* @param dictType 字典类型
|
||||
* @param dictValue 字典值
|
||||
* @param separator 分隔符
|
||||
* @return 字典标签
|
||||
*/
|
||||
String getDictLabel(String dictType, String dictValue, String separator);
|
||||
|
||||
/**
|
||||
* 根据字典类型和字典标签获取字典值
|
||||
*
|
||||
* @param dictType 字典类型
|
||||
* @param dictLabel 字典标签
|
||||
* @param separator 分隔符
|
||||
* @return 字典值
|
||||
*/
|
||||
String getDictValue(String dictType, String dictLabel, String separator);
|
||||
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package com.ruoyi.common.core.service;
|
||||
|
||||
import com.ruoyi.common.core.domain.entity.SysUser;
|
||||
|
||||
/**
|
||||
* 通用 用户业务
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
public interface UserService {
|
||||
|
||||
/**
|
||||
* 通过用户名查询用户
|
||||
*
|
||||
* @param userName 用户名
|
||||
* @return 用户对象信息
|
||||
*/
|
||||
SysUser selectUserByUserName(String userName);
|
||||
|
||||
/**
|
||||
* 通过用户ID查询用户
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @return 用户对象信息
|
||||
*/
|
||||
SysUser selectUserById(Long userId);
|
||||
|
||||
}
|
@ -0,0 +1,108 @@
|
||||
package com.ruoyi.common.excel;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.alibaba.excel.context.AnalysisContext;
|
||||
import com.alibaba.excel.event.AnalysisEventListener;
|
||||
import com.alibaba.excel.exception.ExcelAnalysisException;
|
||||
import com.alibaba.excel.exception.ExcelDataConvertException;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.ruoyi.common.utils.ValidatorUtils;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.validation.ConstraintViolation;
|
||||
import javax.validation.ConstraintViolationException;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Excel 导入监听
|
||||
*
|
||||
* @author Yjoioooo
|
||||
* @author Lion Li
|
||||
*/
|
||||
@Slf4j
|
||||
@NoArgsConstructor
|
||||
public class DefaultExcelListener<T> extends AnalysisEventListener<T> implements ExcelListener<T> {
|
||||
|
||||
/**
|
||||
* 是否Validator检验,默认为是
|
||||
*/
|
||||
private Boolean isValidate = Boolean.TRUE;
|
||||
|
||||
/**
|
||||
* excel 表头数据
|
||||
*/
|
||||
private Map<Integer, String> headMap;
|
||||
|
||||
/**
|
||||
* 导入回执
|
||||
*/
|
||||
private ExcelResult<T> excelResult;
|
||||
|
||||
public DefaultExcelListener(boolean isValidate) {
|
||||
this.excelResult = new DefautExcelResult<>();
|
||||
this.isValidate = isValidate;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理异常
|
||||
*
|
||||
* @param exception ExcelDataConvertException
|
||||
* @param context Excel 上下文
|
||||
*/
|
||||
@Override
|
||||
public void onException(Exception exception, AnalysisContext context) throws Exception {
|
||||
String errMsg = null;
|
||||
if (exception instanceof ExcelDataConvertException) {
|
||||
// 如果是某一个单元格的转换异常 能获取到具体行号
|
||||
ExcelDataConvertException excelDataConvertException = (ExcelDataConvertException) exception;
|
||||
Integer rowIndex = excelDataConvertException.getRowIndex();
|
||||
Integer columnIndex = excelDataConvertException.getColumnIndex();
|
||||
errMsg = StrUtil.format("第{}行-第{}列-表头{}: 解析异常<br/>",
|
||||
rowIndex + 1, columnIndex + 1, headMap.get(columnIndex));
|
||||
if (log.isDebugEnabled()) {
|
||||
log.error(errMsg);
|
||||
}
|
||||
}
|
||||
if (exception instanceof ConstraintViolationException) {
|
||||
ConstraintViolationException constraintViolationException = (ConstraintViolationException) exception;
|
||||
Set<ConstraintViolation<?>> constraintViolations = constraintViolationException.getConstraintViolations();
|
||||
String constraintViolationsMsg = constraintViolations.stream()
|
||||
.map(ConstraintViolation::getMessage)
|
||||
.collect(Collectors.joining(", "));
|
||||
errMsg = StrUtil.format("第{}行数据校验异常: {}", context.readRowHolder().getRowIndex() + 1, constraintViolationsMsg);
|
||||
if (log.isDebugEnabled()) {
|
||||
log.error(errMsg);
|
||||
}
|
||||
}
|
||||
excelResult.getErrorList().add(errMsg);
|
||||
throw new ExcelAnalysisException(errMsg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
|
||||
this.headMap = headMap;
|
||||
log.debug("解析到一条表头数据: {}", JSON.toJSONString(headMap));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(T data, AnalysisContext context) {
|
||||
if (isValidate) {
|
||||
ValidatorUtils.validate(data);
|
||||
}
|
||||
excelResult.getList().add(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doAfterAllAnalysed(AnalysisContext context) {
|
||||
log.debug("所有数据解析完成!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExcelResult<T> getExcelResult() {
|
||||
return excelResult;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
package com.ruoyi.common.excel;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 默认excel返回对象
|
||||
*
|
||||
* @author Yjoioooo
|
||||
* @author Lion Li
|
||||
*/
|
||||
public class DefautExcelResult<T> implements ExcelResult<T> {
|
||||
|
||||
/**
|
||||
* 数据对象list
|
||||
*/
|
||||
@Setter
|
||||
private List<T> list;
|
||||
|
||||
/**
|
||||
* 错误信息列表
|
||||
*/
|
||||
@Setter
|
||||
private List<String> errorList;
|
||||
|
||||
public DefautExcelResult() {
|
||||
this.list = new ArrayList<>();
|
||||
this.errorList = new ArrayList<>();
|
||||
}
|
||||
|
||||
public DefautExcelResult(List<T> list, List<String> errorList) {
|
||||
this.list = list;
|
||||
this.errorList = errorList;
|
||||
}
|
||||
|
||||
public DefautExcelResult(ExcelResult<T> excelResult) {
|
||||
this.list = excelResult.getList();
|
||||
this.errorList = excelResult.getErrorList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<T> getList() {
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getErrorList() {
|
||||
return errorList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取导入回执
|
||||
*
|
||||
* @return 导入回执
|
||||
*/
|
||||
@Override
|
||||
public String getAnalysis() {
|
||||
int successCount = list.size();
|
||||
int errorCount = errorList.size();
|
||||
if (successCount == 0) {
|
||||
return "读取失败,未解析到数据";
|
||||
} else {
|
||||
if (errorCount == 0) {
|
||||
return StrUtil.format("恭喜您,全部读取成功!共{}条", successCount);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package com.ruoyi.common.excel;
|
||||
|
||||
import com.alibaba.excel.read.listener.ReadListener;
|
||||
|
||||
/**
|
||||
* Excel 导入监听
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
public interface ExcelListener<T> extends ReadListener<T> {
|
||||
|
||||
ExcelResult<T> getExcelResult();
|
||||
|
||||
}
|
26
ruoyi/src/main/java/com/ruoyi/common/excel/ExcelResult.java
Normal file
26
ruoyi/src/main/java/com/ruoyi/common/excel/ExcelResult.java
Normal file
@ -0,0 +1,26 @@
|
||||
package com.ruoyi.common.excel;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* excel返回对象
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
public interface ExcelResult<T> {
|
||||
|
||||
/**
|
||||
* 对象列表
|
||||
*/
|
||||
List<T> getList();
|
||||
|
||||
/**
|
||||
* 错误列表
|
||||
*/
|
||||
List<String> getErrorList();
|
||||
|
||||
/**
|
||||
* 导入回执
|
||||
*/
|
||||
String getAnalysis();
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package com.ruoyi.common.utils;
|
||||
|
||||
import cn.hutool.core.lang.tree.Tree;
|
||||
import cn.hutool.core.lang.tree.TreeNodeConfig;
|
||||
import cn.hutool.core.lang.tree.TreeUtil;
|
||||
import cn.hutool.core.lang.tree.parser.NodeParser;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 扩展 hutool TreeUtil 封装系统树构建
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
public class TreeBuildUtils extends TreeUtil {
|
||||
|
||||
/**
|
||||
* 根据前端定制差异化字段
|
||||
*/
|
||||
public static final TreeNodeConfig DEFAULT_CONFIG = TreeNodeConfig.DEFAULT_CONFIG.setNameKey("label");
|
||||
|
||||
/**
|
||||
* 默认树父节点id
|
||||
*/
|
||||
public static final Long DEFAULT_PARENT_ID = 0L;
|
||||
|
||||
public static <T> List<Tree<Long>> build(List<T> list, NodeParser<T, Long> nodeParser) {
|
||||
return TreeUtil.build(list, DEFAULT_PARENT_ID, DEFAULT_CONFIG, nodeParser);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package com.ruoyi.common.utils;
|
||||
|
||||
import javax.validation.ConstraintViolation;
|
||||
import javax.validation.ConstraintViolationException;
|
||||
import javax.validation.Validation;
|
||||
import javax.validation.Validator;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Validator 校验框架工具
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
public class ValidatorUtils {
|
||||
|
||||
private static final Validator VALID = Validation.buildDefaultValidatorFactory().getValidator();
|
||||
|
||||
public static <T> void validate(T object, Class<?>... groups) {
|
||||
Set<ConstraintViolation<T>> validate = VALID.validate(object, groups);
|
||||
if (!validate.isEmpty()) {
|
||||
throw new ConstraintViolationException("参数校验异常", validate);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
package com.ruoyi.demo.domain.bo;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* 测试单表业务对象 test_demo
|
||||
*
|
||||
* @author Lion Li
|
||||
* @date 2021-07-26
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("测试单表业务对象")
|
||||
public class TestDemoImportVo {
|
||||
|
||||
/**
|
||||
* 部门id
|
||||
*/
|
||||
@ApiModelProperty("部门id")
|
||||
@NotNull(message = "部门id不能为空")
|
||||
@ExcelProperty(value = "部门id")
|
||||
private Long deptId;
|
||||
|
||||
/**
|
||||
* 用户id
|
||||
*/
|
||||
@ApiModelProperty("用户id")
|
||||
@NotNull(message = "用户id不能为空")
|
||||
@ExcelProperty(value = "用户id")
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 排序号
|
||||
*/
|
||||
@ApiModelProperty("排序号")
|
||||
@NotNull(message = "排序号不能为空")
|
||||
@ExcelProperty(value = "排序号")
|
||||
private Long orderNum;
|
||||
|
||||
/**
|
||||
* key键
|
||||
*/
|
||||
@ApiModelProperty("key键")
|
||||
@NotBlank(message = "key键不能为空")
|
||||
@ExcelProperty(value = "key键")
|
||||
private String testKey;
|
||||
|
||||
/**
|
||||
* 值
|
||||
*/
|
||||
@ApiModelProperty("值")
|
||||
@NotBlank(message = "值不能为空")
|
||||
@ExcelProperty(value = "值")
|
||||
private String value;
|
||||
|
||||
}
|
38
ruoyi/src/main/java/com/ruoyi/oss/constant/OssConstant.java
Normal file
38
ruoyi/src/main/java/com/ruoyi/oss/constant/OssConstant.java
Normal file
@ -0,0 +1,38 @@
|
||||
package com.ruoyi.oss.constant;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 对象存储常量
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
public class OssConstant {
|
||||
|
||||
/**
|
||||
* OSS模块KEY
|
||||
*/
|
||||
public static final String SYS_OSS_KEY = "sys_oss:";
|
||||
|
||||
/**
|
||||
* 对象存储配置KEY
|
||||
*/
|
||||
public static final String OSS_CONFIG_KEY = "OssConfig";
|
||||
|
||||
/**
|
||||
* 缓存配置KEY
|
||||
*/
|
||||
public static final String CACHE_CONFIG_KEY = SYS_OSS_KEY + OSS_CONFIG_KEY;
|
||||
|
||||
/**
|
||||
* 预览列表资源开关Key
|
||||
*/
|
||||
public static final String PEREVIEW_LIST_RESOURCE_KEY = "sys.oss.previewListResource";
|
||||
|
||||
/**
|
||||
* 系统数据ids
|
||||
*/
|
||||
public static final List<Integer> SYSTEM_DATA_IDS = Arrays.asList(1, 2, 3, 4);
|
||||
|
||||
}
|
63
ruoyi/src/main/java/com/ruoyi/oss/enumd/OssEnumd.java
Normal file
63
ruoyi/src/main/java/com/ruoyi/oss/enumd/OssEnumd.java
Normal file
@ -0,0 +1,63 @@
|
||||
package com.ruoyi.oss.enumd;
|
||||
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.oss.service.impl.AliyunOssStrategy;
|
||||
import com.ruoyi.oss.service.impl.MinioOssStrategy;
|
||||
import com.ruoyi.oss.service.impl.QcloudOssStrategy;
|
||||
import com.ruoyi.oss.service.impl.QiniuOssStrategy;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 对象存储服务商枚举
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum OssEnumd {
|
||||
|
||||
/**
|
||||
* 七牛云
|
||||
*/
|
||||
QINIU("qiniu", QiniuOssStrategy.class),
|
||||
|
||||
/**
|
||||
* 阿里云
|
||||
*/
|
||||
ALIYUN("aliyun", AliyunOssStrategy.class),
|
||||
|
||||
/**
|
||||
* 腾讯云
|
||||
*/
|
||||
QCLOUD("qcloud", QcloudOssStrategy.class),
|
||||
|
||||
/**
|
||||
* minio
|
||||
*/
|
||||
MINIO("minio", MinioOssStrategy.class);
|
||||
|
||||
private final String value;
|
||||
|
||||
private final Class<?> serviceClass;
|
||||
|
||||
public static Class<?> getServiceClass(String value) {
|
||||
for (OssEnumd clazz : values()) {
|
||||
if (clazz.getValue().equals(value)) {
|
||||
return clazz.getServiceClass();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String getServiceName(String value) {
|
||||
for (OssEnumd clazz : values()) {
|
||||
if (clazz.getValue().equals(value)) {
|
||||
return StringUtils.uncapitalize(clazz.getServiceClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
package com.ruoyi.oss.properties;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* OSS对象存储 配置属性
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@Data
|
||||
public class OssProperties {
|
||||
|
||||
/**
|
||||
* 域名
|
||||
*/
|
||||
private String endpoint;
|
||||
|
||||
/**
|
||||
* 前缀
|
||||
*/
|
||||
private String prefix;
|
||||
|
||||
/**
|
||||
* ACCESS_KEY
|
||||
*/
|
||||
private String accessKey;
|
||||
|
||||
/**
|
||||
* SECRET_KEY
|
||||
*/
|
||||
private String secretKey;
|
||||
|
||||
/**
|
||||
* 存储空间名
|
||||
*/
|
||||
private String bucketName;
|
||||
|
||||
/**
|
||||
* 存储区域
|
||||
*/
|
||||
private String region;
|
||||
|
||||
/**
|
||||
* 是否https(Y=是,N=否)
|
||||
*/
|
||||
private String isHttps;
|
||||
|
||||
}
|
64
ruoyi/src/main/java/com/ruoyi/oss/service/IOssStrategy.java
Normal file
64
ruoyi/src/main/java/com/ruoyi/oss/service/IOssStrategy.java
Normal file
@ -0,0 +1,64 @@
|
||||
package com.ruoyi.oss.service;
|
||||
|
||||
import com.ruoyi.oss.entity.UploadResult;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* 对象存储策略
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
public interface IOssStrategy {
|
||||
|
||||
void createBucket();
|
||||
|
||||
/**
|
||||
* 获取服务商类型
|
||||
*/
|
||||
String getServiceType();
|
||||
|
||||
/**
|
||||
* 文件上传
|
||||
*
|
||||
* @param data 文件字节数组
|
||||
* @param path 文件路径,包含文件名
|
||||
* @return 返回http地址
|
||||
*/
|
||||
UploadResult upload(byte[] data, String path, String contentType);
|
||||
|
||||
/**
|
||||
* 文件删除
|
||||
*
|
||||
* @param path 文件路径,包含文件名
|
||||
*/
|
||||
void delete(String path);
|
||||
|
||||
/**
|
||||
* 文件上传
|
||||
*
|
||||
* @param data 文件字节数组
|
||||
* @param suffix 后缀
|
||||
* @return 返回http地址
|
||||
*/
|
||||
UploadResult uploadSuffix(byte[] data, String suffix, String contentType);
|
||||
|
||||
/**
|
||||
* 文件上传
|
||||
*
|
||||
* @param inputStream 字节流
|
||||
* @param path 文件路径,包含文件名
|
||||
* @return 返回http地址
|
||||
*/
|
||||
UploadResult upload(InputStream inputStream, String path, String contentType);
|
||||
|
||||
/**
|
||||
* 文件上传
|
||||
*
|
||||
* @param inputStream 字节流
|
||||
* @param suffix 后缀
|
||||
* @return 返回http地址
|
||||
*/
|
||||
UploadResult uploadSuffix(InputStream inputStream, String suffix, String contentType);
|
||||
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
package com.ruoyi.oss.service.abstractd;
|
||||
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import com.ruoyi.common.utils.DateUtils;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.oss.entity.UploadResult;
|
||||
import com.ruoyi.oss.properties.OssProperties;
|
||||
import com.ruoyi.oss.service.IOssStrategy;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* 对象存储策略(支持七牛、阿里云、腾讯云、minio)
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
public abstract class AbstractOssStrategy implements IOssStrategy {
|
||||
|
||||
protected OssProperties properties;
|
||||
|
||||
public abstract void init(OssProperties properties);
|
||||
|
||||
@Override
|
||||
public abstract void createBucket();
|
||||
|
||||
@Override
|
||||
public abstract String getServiceType();
|
||||
|
||||
public String getPath(String prefix, String suffix) {
|
||||
// 生成uuid
|
||||
String uuid = IdUtil.fastSimpleUUID();
|
||||
// 文件路径
|
||||
String path = DateUtils.datePath() + "/" + uuid;
|
||||
if (StringUtils.isNotBlank(prefix)) {
|
||||
path = prefix + "/" + path;
|
||||
}
|
||||
return path + suffix;
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract UploadResult upload(byte[] data, String path, String contentType);
|
||||
|
||||
@Override
|
||||
public abstract void delete(String path);
|
||||
|
||||
@Override
|
||||
public UploadResult upload(InputStream inputStream, String path, String contentType) {
|
||||
byte[] data = IoUtil.readBytes(inputStream);
|
||||
return this.upload(data, path, contentType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract UploadResult uploadSuffix(byte[] data, String suffix, String contentType);
|
||||
|
||||
@Override
|
||||
public abstract UploadResult uploadSuffix(InputStream inputStream, String suffix, String contentType);
|
||||
|
||||
public abstract String getEndpointLink();
|
||||
}
|
@ -0,0 +1,113 @@
|
||||
package com.ruoyi.oss.service.impl;
|
||||
|
||||
import com.aliyun.oss.ClientConfiguration;
|
||||
import com.aliyun.oss.OSSClient;
|
||||
import com.aliyun.oss.common.auth.DefaultCredentialProvider;
|
||||
import com.aliyun.oss.model.CannedAccessControlList;
|
||||
import com.aliyun.oss.model.CreateBucketRequest;
|
||||
import com.aliyun.oss.model.ObjectMetadata;
|
||||
import com.aliyun.oss.model.PutObjectRequest;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.oss.entity.UploadResult;
|
||||
import com.ruoyi.oss.enumd.OssEnumd;
|
||||
import com.ruoyi.oss.exception.OssException;
|
||||
import com.ruoyi.oss.properties.OssProperties;
|
||||
import com.ruoyi.oss.service.abstractd.AbstractOssStrategy;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* 阿里云存储策略
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
public class AliyunOssStrategy extends AbstractOssStrategy {
|
||||
|
||||
private OSSClient client;
|
||||
|
||||
@Override
|
||||
public void init(OssProperties cloudStorageProperties) {
|
||||
properties = cloudStorageProperties;
|
||||
try {
|
||||
ClientConfiguration configuration = new ClientConfiguration();
|
||||
DefaultCredentialProvider credentialProvider = new DefaultCredentialProvider(
|
||||
properties.getAccessKey(), properties.getSecretKey());
|
||||
client = new OSSClient(properties.getEndpoint(), credentialProvider, configuration);
|
||||
createBucket();
|
||||
} catch (Exception e) {
|
||||
throw new OssException("阿里云存储配置错误! 请检查系统配置:[" + e.getMessage() + "]");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createBucket() {
|
||||
try {
|
||||
String bucketName = properties.getBucketName();
|
||||
if (client.doesBucketExist(bucketName)) {
|
||||
return;
|
||||
}
|
||||
CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName);
|
||||
createBucketRequest.setCannedACL(CannedAccessControlList.PublicRead);
|
||||
client.createBucket(createBucketRequest);
|
||||
} catch (Exception e) {
|
||||
throw new OssException("创建Bucket失败, 请核对阿里云配置信息:[" + e.getMessage() + "]");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServiceType() {
|
||||
return OssEnumd.ALIYUN.getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UploadResult upload(byte[] data, String path, String contentType) {
|
||||
return upload(new ByteArrayInputStream(data), path, contentType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UploadResult upload(InputStream inputStream, String path, String contentType) {
|
||||
try {
|
||||
ObjectMetadata metadata = new ObjectMetadata();
|
||||
metadata.setContentType(contentType);
|
||||
client.putObject(new PutObjectRequest(properties.getBucketName(), path, inputStream, metadata));
|
||||
} catch (Exception e) {
|
||||
throw new OssException("上传文件失败,请检查阿里云配置信息:[" + e.getMessage() + "]");
|
||||
}
|
||||
return new UploadResult().setUrl(getEndpointLink() + "/" + path).setFilename(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(String path) {
|
||||
path = path.replace(getEndpointLink() + "/", "");
|
||||
try {
|
||||
client.deleteObject(properties.getBucketName(), path);
|
||||
} catch (Exception e) {
|
||||
throw new OssException("上传文件失败,请检查阿里云配置信息:[" + e.getMessage() + "]");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public UploadResult uploadSuffix(byte[] data, String suffix, String contentType) {
|
||||
return upload(data, getPath(properties.getPrefix(), suffix), contentType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UploadResult uploadSuffix(InputStream inputStream, String suffix, String contentType) {
|
||||
return upload(inputStream, getPath(properties.getPrefix(), suffix), contentType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEndpointLink() {
|
||||
String endpoint = properties.getEndpoint();
|
||||
StringBuilder sb = new StringBuilder(endpoint);
|
||||
if (StringUtils.containsAnyIgnoreCase(endpoint, "http://")) {
|
||||
sb.insert(7, properties.getBucketName() + ".");
|
||||
} else if (StringUtils.containsAnyIgnoreCase(endpoint, "https://")) {
|
||||
sb.insert(8, properties.getBucketName() + ".");
|
||||
} else {
|
||||
throw new OssException("Endpoint配置错误");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,181 @@
|
||||
package com.ruoyi.oss.service.impl;
|
||||
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.oss.entity.UploadResult;
|
||||
import com.ruoyi.oss.enumd.OssEnumd;
|
||||
import com.ruoyi.oss.enumd.PolicyType;
|
||||
import com.ruoyi.oss.exception.OssException;
|
||||
import com.ruoyi.oss.properties.OssProperties;
|
||||
import com.ruoyi.oss.service.abstractd.AbstractOssStrategy;
|
||||
import io.minio.*;
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* minio存储策略
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
public class MinioOssStrategy extends AbstractOssStrategy {
|
||||
|
||||
private MinioClient minioClient;
|
||||
|
||||
@Override
|
||||
public void init(OssProperties cloudStorageProperties) {
|
||||
properties = cloudStorageProperties;
|
||||
try {
|
||||
minioClient = MinioClient.builder()
|
||||
.endpoint(properties.getEndpoint())
|
||||
.credentials(properties.getAccessKey(), properties.getSecretKey())
|
||||
.build();
|
||||
createBucket();
|
||||
} catch (Exception e) {
|
||||
throw new OssException("Minio存储配置错误! 请检查系统配置:[" + e.getMessage() + "]");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createBucket() {
|
||||
try {
|
||||
String bucketName = properties.getBucketName();
|
||||
boolean exists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
|
||||
if (exists) {
|
||||
return;
|
||||
}
|
||||
// 不存在就创建桶
|
||||
minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
|
||||
minioClient.setBucketPolicy(SetBucketPolicyArgs.builder()
|
||||
.bucket(bucketName)
|
||||
.config(getPolicy(bucketName, PolicyType.READ))
|
||||
.build());
|
||||
} catch (Exception e) {
|
||||
throw new OssException("创建Bucket失败, 请核对Minio配置信息:[" + e.getMessage() + "]");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServiceType() {
|
||||
return OssEnumd.MINIO.getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UploadResult upload(byte[] data, String path, String contentType) {
|
||||
return upload(new ByteArrayInputStream(data), path, contentType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UploadResult upload(InputStream inputStream, String path, String contentType) {
|
||||
try {
|
||||
minioClient.putObject(PutObjectArgs.builder()
|
||||
.bucket(properties.getBucketName())
|
||||
.object(path)
|
||||
.contentType(StringUtils.blankToDefault(contentType, MediaType.APPLICATION_OCTET_STREAM_VALUE))
|
||||
.stream(inputStream, inputStream.available(), -1)
|
||||
.build());
|
||||
} catch (Exception e) {
|
||||
throw new OssException("上传文件失败,请核对Minio配置信息:[" + e.getMessage() + "]");
|
||||
}
|
||||
return new UploadResult().setUrl(getEndpointLink() + "/" + path).setFilename(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(String path) {
|
||||
path = path.replace(getEndpointLink() + "/", "");
|
||||
try {
|
||||
minioClient.removeObject(RemoveObjectArgs.builder()
|
||||
.bucket(properties.getBucketName())
|
||||
.object(path)
|
||||
.build());
|
||||
} catch (Exception e) {
|
||||
throw new OssException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public UploadResult uploadSuffix(byte[] data, String suffix, String contentType) {
|
||||
return upload(data, getPath(properties.getPrefix(), suffix), contentType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UploadResult uploadSuffix(InputStream inputStream, String suffix, String contentType) {
|
||||
return upload(inputStream, getPath(properties.getPrefix(), suffix), contentType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEndpointLink() {
|
||||
return properties.getEndpoint() + "/" + properties.getBucketName();
|
||||
}
|
||||
|
||||
private String getPolicy(String bucketName, PolicyType policyType) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("{\n");
|
||||
builder.append(" \"Statement\": [\n");
|
||||
builder.append(" {\n");
|
||||
builder.append(" \"Action\": [\n");
|
||||
if (policyType == PolicyType.WRITE) {
|
||||
builder.append(" \"s3:GetBucketLocation\",\n");
|
||||
builder.append(" \"s3:ListBucketMultipartUploads\"\n");
|
||||
} else if (policyType == PolicyType.READ_WRITE) {
|
||||
builder.append(" \"s3:GetBucketLocation\",\n");
|
||||
builder.append(" \"s3:ListBucket\",\n");
|
||||
builder.append(" \"s3:ListBucketMultipartUploads\"\n");
|
||||
} else {
|
||||
builder.append(" \"s3:GetBucketLocation\"\n");
|
||||
}
|
||||
builder.append(" ],\n");
|
||||
builder.append(" \"Effect\": \"Allow\",\n");
|
||||
builder.append(" \"Principal\": \"*\",\n");
|
||||
builder.append(" \"Resource\": \"arn:aws:s3:::");
|
||||
builder.append(bucketName);
|
||||
builder.append("\"\n");
|
||||
builder.append(" },\n");
|
||||
if (PolicyType.READ.equals(policyType)) {
|
||||
builder.append(" {\n");
|
||||
builder.append(" \"Action\": [\n");
|
||||
builder.append(" \"s3:ListBucket\"\n");
|
||||
builder.append(" ],\n");
|
||||
builder.append(" \"Effect\": \"Deny\",\n");
|
||||
builder.append(" \"Principal\": \"*\",\n");
|
||||
builder.append(" \"Resource\": \"arn:aws:s3:::");
|
||||
builder.append(bucketName);
|
||||
builder.append("\"\n");
|
||||
builder.append(" },\n");
|
||||
}
|
||||
builder.append(" {\n");
|
||||
builder.append(" \"Action\": ");
|
||||
switch (policyType) {
|
||||
case WRITE:
|
||||
builder.append("[\n");
|
||||
builder.append(" \"s3:AbortMultipartUpload\",\n");
|
||||
builder.append(" \"s3:DeleteObject\",\n");
|
||||
builder.append(" \"s3:ListMultipartUploadParts\",\n");
|
||||
builder.append(" \"s3:PutObject\"\n");
|
||||
builder.append(" ],\n");
|
||||
break;
|
||||
case READ_WRITE:
|
||||
builder.append("[\n");
|
||||
builder.append(" \"s3:AbortMultipartUpload\",\n");
|
||||
builder.append(" \"s3:DeleteObject\",\n");
|
||||
builder.append(" \"s3:GetObject\",\n");
|
||||
builder.append(" \"s3:ListMultipartUploadParts\",\n");
|
||||
builder.append(" \"s3:PutObject\"\n");
|
||||
builder.append(" ],\n");
|
||||
break;
|
||||
default:
|
||||
builder.append("\"s3:GetObject\",\n");
|
||||
break;
|
||||
}
|
||||
builder.append(" \"Effect\": \"Allow\",\n");
|
||||
builder.append(" \"Principal\": \"*\",\n");
|
||||
builder.append(" \"Resource\": \"arn:aws:s3:::");
|
||||
builder.append(bucketName);
|
||||
builder.append("/*\"\n");
|
||||
builder.append(" }\n");
|
||||
builder.append(" ],\n");
|
||||
builder.append(" \"Version\": \"2012-10-17\"\n");
|
||||
builder.append("}\n");
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,121 @@
|
||||
package com.ruoyi.oss.service.impl;
|
||||
|
||||
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.http.HttpProtocol;
|
||||
import com.qcloud.cos.model.*;
|
||||
import com.qcloud.cos.region.Region;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.oss.entity.UploadResult;
|
||||
import com.ruoyi.oss.enumd.OssEnumd;
|
||||
import com.ruoyi.oss.exception.OssException;
|
||||
import com.ruoyi.oss.properties.OssProperties;
|
||||
import com.ruoyi.oss.service.abstractd.AbstractOssStrategy;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* 腾讯云存储策略
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
public class QcloudOssStrategy extends AbstractOssStrategy {
|
||||
|
||||
private COSClient client;
|
||||
|
||||
@Override
|
||||
public void init(OssProperties cloudStorageProperties) {
|
||||
properties = cloudStorageProperties;
|
||||
try {
|
||||
COSCredentials credentials = new BasicCOSCredentials(
|
||||
properties.getAccessKey(), properties.getSecretKey());
|
||||
// 初始化客户端配置
|
||||
ClientConfig clientConfig = new ClientConfig();
|
||||
// 设置bucket所在的区域,华南:gz 华北:tj 华东:sh
|
||||
clientConfig.setRegion(new Region(properties.getRegion()));
|
||||
if ("Y".equals(properties.getIsHttps())) {
|
||||
clientConfig.setHttpProtocol(HttpProtocol.https);
|
||||
} else {
|
||||
clientConfig.setHttpProtocol(HttpProtocol.http);
|
||||
}
|
||||
client = new COSClient(credentials, clientConfig);
|
||||
createBucket();
|
||||
} catch (Exception e) {
|
||||
throw new OssException("腾讯云存储配置错误! 请检查系统配置:[" + e.getMessage() + "]");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createBucket() {
|
||||
try {
|
||||
String bucketName = properties.getBucketName();
|
||||
if (client.doesBucketExist(bucketName)) {
|
||||
return;
|
||||
}
|
||||
CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName);
|
||||
createBucketRequest.setCannedAcl(CannedAccessControlList.PublicRead);
|
||||
client.createBucket(createBucketRequest);
|
||||
} catch (Exception e) {
|
||||
throw new OssException("创建Bucket失败, 请核对腾讯云配置信息:[" + e.getMessage() + "]");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServiceType() {
|
||||
return OssEnumd.QCLOUD.getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UploadResult upload(byte[] data, String path, String contentType) {
|
||||
return upload(new ByteArrayInputStream(data), path, contentType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UploadResult upload(InputStream inputStream, String path, String contentType) {
|
||||
try {
|
||||
ObjectMetadata metadata = new ObjectMetadata();
|
||||
metadata.setContentType(contentType);
|
||||
client.putObject(new PutObjectRequest(properties.getBucketName(), path, inputStream, metadata));
|
||||
} catch (Exception e) {
|
||||
throw new OssException("上传文件失败,请检查腾讯云配置信息:[" + e.getMessage() + "]");
|
||||
}
|
||||
return new UploadResult().setUrl(getEndpointLink() + "/" + path).setFilename(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(String path) {
|
||||
path = path.replace(getEndpointLink() + "/", "");
|
||||
try {
|
||||
client.deleteObject(new DeleteObjectRequest(properties.getBucketName(), path));
|
||||
} catch (Exception e) {
|
||||
throw new OssException("上传文件失败,请检腾讯云查配置信息:[" + e.getMessage() + "]");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public UploadResult uploadSuffix(byte[] data, String suffix, String contentType) {
|
||||
return upload(data, getPath(properties.getPrefix(), suffix), contentType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UploadResult uploadSuffix(InputStream inputStream, String suffix, String contentType) {
|
||||
return upload(inputStream, getPath(properties.getPrefix(), suffix), contentType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEndpointLink() {
|
||||
String endpoint = properties.getEndpoint();
|
||||
StringBuilder sb = new StringBuilder(endpoint);
|
||||
if (StringUtils.containsAnyIgnoreCase(endpoint, "http://")) {
|
||||
sb.insert(7, properties.getBucketName() + ".");
|
||||
} else if (StringUtils.containsAnyIgnoreCase(endpoint, "https://")) {
|
||||
sb.insert(8, properties.getBucketName() + ".");
|
||||
} else {
|
||||
throw new OssException("Endpoint配置错误");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,127 @@
|
||||
package com.ruoyi.oss.service.impl;
|
||||
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import com.qiniu.http.Response;
|
||||
import com.qiniu.storage.BucketManager;
|
||||
import com.qiniu.storage.Configuration;
|
||||
import com.qiniu.storage.Region;
|
||||
import com.qiniu.storage.UploadManager;
|
||||
import com.qiniu.util.Auth;
|
||||
import com.ruoyi.oss.entity.UploadResult;
|
||||
import com.ruoyi.oss.enumd.OssEnumd;
|
||||
import com.ruoyi.oss.exception.OssException;
|
||||
import com.ruoyi.oss.properties.OssProperties;
|
||||
import com.ruoyi.oss.service.abstractd.AbstractOssStrategy;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* 七牛云存储策略
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
public class QiniuOssStrategy extends AbstractOssStrategy {
|
||||
|
||||
private UploadManager uploadManager;
|
||||
private BucketManager bucketManager;
|
||||
private Auth auth;
|
||||
|
||||
@Override
|
||||
public void init(OssProperties cloudStorageProperties) {
|
||||
properties = cloudStorageProperties;
|
||||
try {
|
||||
Configuration config = new Configuration(getRegion(properties.getRegion()));
|
||||
// https设置
|
||||
config.useHttpsDomains = false;
|
||||
config.useHttpsDomains = "Y".equals(properties.getIsHttps());
|
||||
uploadManager = new UploadManager(config);
|
||||
auth = Auth.create(properties.getAccessKey(), properties.getSecretKey());
|
||||
String bucketName = properties.getBucketName();
|
||||
bucketManager = new BucketManager(auth, config);
|
||||
|
||||
if (!ArrayUtil.contains(bucketManager.buckets(), bucketName)) {
|
||||
bucketManager.createBucket(bucketName, properties.getRegion());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new OssException("七牛云存储配置错误! 请检查系统配置:[" + e.getMessage() + "]");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createBucket() {
|
||||
try {
|
||||
String bucketName = properties.getBucketName();
|
||||
if (ArrayUtil.contains(bucketManager.buckets(), bucketName)) {
|
||||
return;
|
||||
}
|
||||
bucketManager.createBucket(bucketName, properties.getRegion());
|
||||
} catch (Exception e) {
|
||||
throw new OssException("创建Bucket失败, 请核对七牛云配置信息:[" + e.getMessage() + "]");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServiceType() {
|
||||
return OssEnumd.QINIU.getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UploadResult upload(byte[] data, String path, String contentType) {
|
||||
try {
|
||||
String token = auth.uploadToken(properties.getBucketName());
|
||||
Response res = uploadManager.put(data, path, token, null, contentType, false);
|
||||
if (!res.isOK()) {
|
||||
throw new RuntimeException("上传七牛出错:" + res.error);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new OssException("上传文件失败,请核对七牛配置信息:[" + e.getMessage() + "]");
|
||||
}
|
||||
return new UploadResult().setUrl(getEndpointLink() + "/" + path).setFilename(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(String path) {
|
||||
try {
|
||||
path = path.replace(getEndpointLink() + "/", "");
|
||||
Response res = bucketManager.delete(properties.getBucketName(), path);
|
||||
if (!res.isOK()) {
|
||||
throw new RuntimeException("删除七牛文件出错:" + res.error);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new OssException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public UploadResult uploadSuffix(byte[] data, String suffix, String contentType) {
|
||||
return upload(data, getPath(properties.getPrefix(), suffix), contentType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UploadResult uploadSuffix(InputStream inputStream, String suffix, String contentType) {
|
||||
return upload(inputStream, getPath(properties.getPrefix(), suffix), contentType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEndpointLink() {
|
||||
return properties.getEndpoint();
|
||||
}
|
||||
|
||||
private Region getRegion(String region) {
|
||||
switch (region) {
|
||||
case "z0":
|
||||
return Region.region0();
|
||||
case "z1":
|
||||
return Region.region1();
|
||||
case "z2":
|
||||
return Region.region2();
|
||||
case "na0":
|
||||
return Region.regionNa0();
|
||||
case "as0":
|
||||
return Region.regionAs0();
|
||||
default:
|
||||
return Region.autoRegion();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,109 @@
|
||||
package com.ruoyi.system.listener;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import com.alibaba.excel.context.AnalysisContext;
|
||||
import com.alibaba.excel.event.AnalysisEventListener;
|
||||
import com.ruoyi.common.core.domain.entity.SysUser;
|
||||
import com.ruoyi.common.excel.ExcelListener;
|
||||
import com.ruoyi.common.excel.ExcelResult;
|
||||
import com.ruoyi.common.exception.ServiceException;
|
||||
import com.ruoyi.common.utils.SecurityUtils;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.common.utils.spring.SpringUtils;
|
||||
import com.ruoyi.system.domain.vo.SysUserImportVo;
|
||||
import com.ruoyi.system.service.ISysConfigService;
|
||||
import com.ruoyi.system.service.ISysUserService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 系统用户自定义导入
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@Slf4j
|
||||
public class SysUserImportListener extends AnalysisEventListener<SysUserImportVo> implements ExcelListener<SysUserImportVo> {
|
||||
|
||||
private final ISysUserService userService;
|
||||
|
||||
private final String password;
|
||||
|
||||
private final Boolean isUpdateSupport;
|
||||
|
||||
private final String operName;
|
||||
|
||||
private int successNum = 0;
|
||||
private int failureNum = 0;
|
||||
private final StringBuilder successMsg = new StringBuilder();
|
||||
private final StringBuilder failureMsg = new StringBuilder();
|
||||
|
||||
public SysUserImportListener(Boolean isUpdateSupport) {
|
||||
this.userService = SpringUtils.getBean(ISysUserService.class);
|
||||
this.password = SpringUtils.getBean(ISysConfigService.class)
|
||||
.selectConfigByKey("sys.user.initPassword");
|
||||
this.isUpdateSupport = isUpdateSupport;
|
||||
this.operName = SecurityUtils.getUsername();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(SysUserImportVo userVo, AnalysisContext context) {
|
||||
SysUser user = this.userService.selectUserByUserName(userVo.getUserName());
|
||||
try {
|
||||
// 验证是否存在这个用户
|
||||
if (StringUtils.isNull(user)) {
|
||||
user = BeanUtil.toBean(userVo, SysUser.class);
|
||||
user.setPassword(SecurityUtils.encryptPassword(password));
|
||||
user.setCreateBy(operName);
|
||||
userService.insertUser(user);
|
||||
successNum++;
|
||||
successMsg.append("<br/>").append(successNum).append("、账号 ").append(user.getUserName()).append(" 导入成功");
|
||||
} else if (isUpdateSupport) {
|
||||
user.setUpdateBy(operName);
|
||||
userService.updateUser(user);
|
||||
successNum++;
|
||||
successMsg.append("<br/>").append(successNum).append("、账号 ").append(user.getUserName()).append(" 更新成功");
|
||||
} else {
|
||||
failureNum++;
|
||||
failureMsg.append("<br/>").append(failureNum).append("、账号 ").append(user.getUserName()).append(" 已存在");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
failureNum++;
|
||||
String msg = "<br/>" + failureNum + "、账号 " + user.getUserName() + " 导入失败:";
|
||||
failureMsg.append(msg).append(e.getMessage());
|
||||
log.error(msg, e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doAfterAllAnalysed(AnalysisContext context) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExcelResult<SysUserImportVo> getExcelResult() {
|
||||
return new ExcelResult<SysUserImportVo>() {
|
||||
|
||||
@Override
|
||||
public String getAnalysis() {
|
||||
if (failureNum > 0) {
|
||||
failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:");
|
||||
throw new ServiceException(failureMsg.toString());
|
||||
} else {
|
||||
successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:");
|
||||
}
|
||||
return successMsg.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SysUserImportVo> getList() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getErrorList() {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package com.ruoyi.system.runner;
|
||||
|
||||
import com.ruoyi.common.config.RuoYiConfig;
|
||||
import com.ruoyi.system.service.ISysConfigService;
|
||||
import com.ruoyi.system.service.ISysDictTypeService;
|
||||
import com.ruoyi.system.service.ISysOssConfigService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.ApplicationArguments;
|
||||
import org.springframework.boot.ApplicationRunner;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 初始化 system 模块对应业务数据
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor(onConstructor_ = @Autowired)
|
||||
@Component
|
||||
public class SystemApplicationRunner implements ApplicationRunner {
|
||||
|
||||
private final RuoYiConfig ruoyiConfig;
|
||||
private final ISysConfigService configService;
|
||||
private final ISysDictTypeService dictTypeService;
|
||||
private final ISysOssConfigService ossConfigService;
|
||||
|
||||
@Override
|
||||
public void run(ApplicationArguments args) throws Exception {
|
||||
ossConfigService.init();
|
||||
log.info("初始化OSS配置成功");
|
||||
if (ruoyiConfig.isCacheLazy()){
|
||||
return;
|
||||
}
|
||||
configService.loadingConfigCache();
|
||||
log.info("加载参数缓存数据成功");
|
||||
dictTypeService.loadingDictCache();
|
||||
log.info("加载字典缓存数据成功");
|
||||
}
|
||||
|
||||
}
|
@ -180,7 +180,6 @@ public class SysUserServiceImpl extends ServicePlusImpl<SysUserMapper, SysUser,
|
||||
public String checkPhoneUnique(SysUser user) {
|
||||
Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId();
|
||||
long count = count(new LambdaQueryWrapper<SysUser>()
|
||||
.select(SysUser::getUserId, SysUser::getPhonenumber)
|
||||
.eq(SysUser::getPhonenumber, user.getPhonenumber())
|
||||
.ne(SysUser::getUserId, userId));
|
||||
if (count > 0) {
|
||||
@ -199,7 +198,6 @@ public class SysUserServiceImpl extends ServicePlusImpl<SysUserMapper, SysUser,
|
||||
public String checkEmailUnique(SysUser user) {
|
||||
Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId();
|
||||
long count = count(new LambdaQueryWrapper<SysUser>()
|
||||
.select(SysUser::getUserId, SysUser::getEmail)
|
||||
.eq(SysUser::getEmail, user.getEmail())
|
||||
.ne(SysUser::getUserId, userId));
|
||||
if (count > 0) {
|
||||
|
3
ruoyi/src/main/resources/mapper/package-info.md
Normal file
3
ruoyi/src/main/resources/mapper/package-info.md
Normal file
@ -0,0 +1,3 @@
|
||||
java包使用 `.` 分割 resource 目录使用 `/` 分割
|
||||
<br>
|
||||
此文件目的 防止文件夹粘连找不到 `xml` 文件
|
@ -644,10 +644,10 @@ create table gen_table_column (
|
||||
drop table if exists sys_oss;
|
||||
create table sys_oss (
|
||||
oss_id bigint(20) not null auto_increment comment '对象存储主键',
|
||||
file_name varchar(64) not null default '' comment '文件名',
|
||||
original_name varchar(64) not null default '' comment '原名',
|
||||
file_name varchar(255) not null default '' comment '文件名',
|
||||
original_name varchar(255) not null default '' comment '原名',
|
||||
file_suffix varchar(10) not null default '' comment '文件后缀名',
|
||||
url varchar(200) not null comment 'URL地址',
|
||||
url varchar(500) not null comment 'URL地址',
|
||||
create_time datetime default null comment '创建时间',
|
||||
create_by varchar(64) default '' comment '上传人',
|
||||
update_time datetime default null comment '更新时间',
|
||||
|
Loading…
x
Reference in New Issue
Block a user