init
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
package org.dromara.resource;
|
||||
|
||||
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||
import org.springframework.boot.context.metrics.buffering.BufferingApplicationStartup;
|
||||
|
||||
/**
|
||||
* 资源服务
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@EnableDubbo
|
||||
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
|
||||
public class RuoYiResourceApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication application = new SpringApplication(RuoYiResourceApplication.class);
|
||||
application.setApplicationStartup(new BufferingApplicationStartup(2048));
|
||||
application.run(args);
|
||||
System.out.println("(♥◠‿◠)ノ゙ 资源服务模块启动成功 ლ(´ڡ`ლ)゙ ");
|
||||
}
|
||||
}
|
@@ -0,0 +1,70 @@
|
||||
package org.dromara.resource.controller;
|
||||
|
||||
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.common.core.constant.Constants;
|
||||
import org.dromara.common.core.constant.GlobalConstants;
|
||||
import org.dromara.common.core.domain.R;
|
||||
import org.dromara.common.core.exception.ServiceException;
|
||||
import org.dromara.common.core.utils.SpringUtils;
|
||||
import org.dromara.common.ratelimiter.annotation.RateLimiter;
|
||||
import org.dromara.common.web.core.BaseController;
|
||||
import org.dromara.common.mail.config.properties.MailProperties;
|
||||
import org.dromara.common.mail.utils.MailUtils;
|
||||
import org.dromara.common.redis.utils.RedisUtils;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import java.time.Duration;
|
||||
|
||||
/**
|
||||
* 邮件功能
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@Slf4j
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/email")
|
||||
public class SysEmailController extends BaseController {
|
||||
|
||||
private final MailProperties mailProperties;
|
||||
|
||||
/**
|
||||
* 邮箱验证码
|
||||
*
|
||||
* @param email 邮箱
|
||||
*/
|
||||
@GetMapping("/code")
|
||||
public R<Void> emailCode(@NotBlank(message = "{user.email.not.blank}") String email) {
|
||||
if (!mailProperties.getEnabled()) {
|
||||
return R.fail("当前系统没有开启邮箱功能!");
|
||||
}
|
||||
SpringUtils.getAopProxy(this).emailCodeImpl(email);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 邮箱验证码
|
||||
* 独立方法避免验证码关闭之后仍然走限流
|
||||
*/
|
||||
@RateLimiter(key = "#email", time = 60, count = 1)
|
||||
public void emailCodeImpl(String email) {
|
||||
String key = GlobalConstants.CAPTCHA_CODE_KEY + email;
|
||||
String code = RandomUtil.randomNumbers(4);
|
||||
RedisUtils.setCacheObject(key, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION));
|
||||
try {
|
||||
MailUtils.sendText(email, "登录验证码", "您本次验证码为:" + code + ",有效性为" + Constants.CAPTCHA_EXPIRATION + "分钟,请尽快填写。");
|
||||
} catch (Exception e) {
|
||||
log.error("验证码短信发送异常 => {}", e.getMessage());
|
||||
throw new ServiceException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,100 @@
|
||||
package org.dromara.resource.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import org.dromara.common.core.domain.R;
|
||||
import org.dromara.common.core.validate.AddGroup;
|
||||
import org.dromara.common.core.validate.EditGroup;
|
||||
import org.dromara.common.core.validate.QueryGroup;
|
||||
import org.dromara.common.web.core.BaseController;
|
||||
import org.dromara.common.log.annotation.Log;
|
||||
import org.dromara.common.log.enums.BusinessType;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.resource.domain.bo.SysOssConfigBo;
|
||||
import org.dromara.resource.domain.vo.SysOssConfigVo;
|
||||
import org.dromara.resource.service.ISysOssConfigService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* 对象存储配置Controller
|
||||
*
|
||||
* @author Lion Li
|
||||
* @author 孤舟烟雨
|
||||
* @date 2021-08-13
|
||||
*/
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/oss/config")
|
||||
public class SysOssConfigController extends BaseController {
|
||||
|
||||
private final ISysOssConfigService iSysOssConfigService;
|
||||
|
||||
/**
|
||||
* 查询对象存储配置列表
|
||||
*/
|
||||
@SaCheckPermission("system:ossConfig:list")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo<SysOssConfigVo> list(@Validated(QueryGroup.class) SysOssConfigBo bo, PageQuery pageQuery) {
|
||||
return iSysOssConfigService.queryPageList(bo, pageQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取对象存储配置详细信息
|
||||
*
|
||||
* @param ossConfigId OSS配置ID
|
||||
*/
|
||||
@SaCheckPermission("system:ossConfig:list")
|
||||
@GetMapping("/{ossConfigId}")
|
||||
public R<SysOssConfigVo> getInfo(@NotNull(message = "主键不能为空") @PathVariable("ossConfigId") Long ossConfigId) {
|
||||
return R.ok(iSysOssConfigService.queryById(ossConfigId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增对象存储配置
|
||||
*/
|
||||
@SaCheckPermission("system:ossConfig:add")
|
||||
@Log(title = "对象存储配置", businessType = BusinessType.INSERT)
|
||||
@PostMapping()
|
||||
public R<Void> add(@Validated(AddGroup.class) @RequestBody SysOssConfigBo bo) {
|
||||
return toAjax(iSysOssConfigService.insertByBo(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改对象存储配置
|
||||
*/
|
||||
@SaCheckPermission("system:ossConfig:edit")
|
||||
@Log(title = "对象存储配置", businessType = BusinessType.UPDATE)
|
||||
@PutMapping()
|
||||
public R<Void> edit(@Validated(EditGroup.class) @RequestBody SysOssConfigBo bo) {
|
||||
return toAjax(iSysOssConfigService.updateByBo(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除对象存储配置
|
||||
*
|
||||
* @param ossConfigIds OSS配置ID串
|
||||
*/
|
||||
@SaCheckPermission("system:ossConfig:remove")
|
||||
@Log(title = "对象存储配置", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ossConfigIds}")
|
||||
public R<Void> remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] ossConfigIds) {
|
||||
return toAjax(iSysOssConfigService.deleteWithValidByIds(Arrays.asList(ossConfigIds), true));
|
||||
}
|
||||
|
||||
/**
|
||||
* 状态修改
|
||||
*/
|
||||
@SaCheckPermission("system:ossConfig:edit")
|
||||
@Log(title = "对象存储状态修改", businessType = BusinessType.UPDATE)
|
||||
@PutMapping("/changeStatus")
|
||||
public R<Void> changeStatus(@RequestBody SysOssConfigBo bo) {
|
||||
return toAjax(iSysOssConfigService.updateOssConfigStatus(bo));
|
||||
}
|
||||
}
|
@@ -0,0 +1,106 @@
|
||||
package org.dromara.resource.controller;
|
||||
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.dromara.common.core.domain.R;
|
||||
import org.dromara.common.core.validate.QueryGroup;
|
||||
import org.dromara.common.web.core.BaseController;
|
||||
import org.dromara.common.log.annotation.Log;
|
||||
import org.dromara.common.log.enums.BusinessType;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.resource.domain.bo.SysOssBo;
|
||||
import org.dromara.resource.domain.vo.SysOssUploadVo;
|
||||
import org.dromara.resource.domain.vo.SysOssVo;
|
||||
import org.dromara.resource.service.ISysOssService;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 文件上传 控制层
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/oss")
|
||||
public class SysOssController extends BaseController {
|
||||
|
||||
private final ISysOssService iSysOssService;
|
||||
|
||||
/**
|
||||
* 查询OSS对象存储列表
|
||||
*/
|
||||
@SaCheckPermission("system:oss:list")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo<SysOssVo> list(@Validated(QueryGroup.class) SysOssBo bo, PageQuery pageQuery) {
|
||||
return iSysOssService.queryPageList(bo, pageQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询OSS对象基于id串
|
||||
*
|
||||
* @param ossIds OSS对象ID串
|
||||
*/
|
||||
@SaCheckPermission("system:oss:query")
|
||||
@GetMapping("/listByIds/{ossIds}")
|
||||
public R<List<SysOssVo>> listByIds(@NotEmpty(message = "主键不能为空") @PathVariable Long[] ossIds) {
|
||||
List<SysOssVo> list = iSysOssService.listByIds(Arrays.asList(ossIds));
|
||||
return R.ok(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传OSS对象存储
|
||||
*
|
||||
* @param file 文件
|
||||
*/
|
||||
@SaCheckPermission("system:oss:upload")
|
||||
@Log(title = "OSS对象存储", businessType = BusinessType.INSERT)
|
||||
@PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
public R<SysOssUploadVo> upload(@RequestPart("file") MultipartFile file) {
|
||||
if (ObjectUtil.isNull(file)) {
|
||||
return R.fail("上传文件不能为空");
|
||||
}
|
||||
SysOssVo oss = iSysOssService.upload(file);
|
||||
SysOssUploadVo uploadVo = new SysOssUploadVo();
|
||||
uploadVo.setUrl(oss.getUrl());
|
||||
uploadVo.setFileName(oss.getOriginalName());
|
||||
uploadVo.setOssId(oss.getOssId().toString());
|
||||
return R.ok(uploadVo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载OSS对象存储
|
||||
*
|
||||
* @param ossId OSS对象ID
|
||||
*/
|
||||
@SaCheckPermission("system:oss:download")
|
||||
@GetMapping("/download/{ossId}")
|
||||
public void download(@PathVariable Long ossId, HttpServletResponse response) throws IOException {
|
||||
iSysOssService.download(ossId, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除OSS对象存储
|
||||
*
|
||||
* @param ossIds OSS对象ID串
|
||||
*/
|
||||
@SaCheckPermission("system:oss:remove")
|
||||
@Log(title = "OSS对象存储", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ossIds}")
|
||||
public R<Void> remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] ossIds) {
|
||||
return toAjax(iSysOssService.deleteWithValidByIds(Arrays.asList(ossIds), true));
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,61 @@
|
||||
package org.dromara.resource.controller;
|
||||
|
||||
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.common.core.constant.Constants;
|
||||
import org.dromara.common.core.constant.GlobalConstants;
|
||||
import org.dromara.common.core.domain.R;
|
||||
import org.dromara.common.ratelimiter.annotation.RateLimiter;
|
||||
import org.dromara.common.redis.utils.RedisUtils;
|
||||
import org.dromara.common.web.core.BaseController;
|
||||
import org.dromara.sms4j.api.SmsBlend;
|
||||
import org.dromara.sms4j.api.entity.SmsResponse;
|
||||
import org.dromara.sms4j.core.factory.SmsFactory;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
/**
|
||||
* 短信功能
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@Slf4j
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/sms")
|
||||
public class SysSmsController extends BaseController {
|
||||
|
||||
/**
|
||||
* 短信验证码
|
||||
*
|
||||
* @param phonenumber 用户手机号
|
||||
*/
|
||||
@RateLimiter(key = "#phonenumber", time = 60, count = 1)
|
||||
@GetMapping("/code")
|
||||
public R<Void> smsCaptcha(@NotBlank(message = "{user.phonenumber.not.blank}") String phonenumber) {
|
||||
String key = GlobalConstants.CAPTCHA_CODE_KEY + phonenumber;
|
||||
String code = RandomUtil.randomNumbers(4);
|
||||
RedisUtils.setCacheObject(key, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION));
|
||||
// 验证码模板id 自行处理 (查数据库或写死均可)
|
||||
String templateId = "";
|
||||
LinkedHashMap<String, String> map = new LinkedHashMap<>(1);
|
||||
map.put("code", code);
|
||||
SmsBlend smsBlend = SmsFactory.getSmsBlend("tx1");
|
||||
SmsResponse smsResponse = smsBlend.sendMessage(phonenumber, templateId, map);
|
||||
if (!smsResponse.isSuccess()) {
|
||||
log.error("验证码短信发送异常 => {}", smsResponse);
|
||||
return R.fail(smsResponse.getData().toString());
|
||||
}
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,55 @@
|
||||
package org.dromara.resource.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.dromara.common.tenant.core.TenantEntity;
|
||||
|
||||
/**
|
||||
* OSS对象存储对象
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("sys_oss")
|
||||
public class SysOss extends TenantEntity {
|
||||
|
||||
/**
|
||||
* 对象存储主键
|
||||
*/
|
||||
@TableId(value = "oss_id")
|
||||
private Long ossId;
|
||||
|
||||
/**
|
||||
* 文件名
|
||||
*/
|
||||
private String fileName;
|
||||
|
||||
/**
|
||||
* 原名
|
||||
*/
|
||||
private String originalName;
|
||||
|
||||
/**
|
||||
* 文件后缀名
|
||||
*/
|
||||
private String fileSuffix;
|
||||
|
||||
/**
|
||||
* URL地址
|
||||
*/
|
||||
private String url;
|
||||
|
||||
/**
|
||||
* 扩展字段
|
||||
*/
|
||||
private String ext1;
|
||||
|
||||
/**
|
||||
* 服务商
|
||||
*/
|
||||
private String service;
|
||||
|
||||
}
|
@@ -0,0 +1,91 @@
|
||||
package org.dromara.resource.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.dromara.common.mybatis.core.domain.BaseEntity;
|
||||
|
||||
/**
|
||||
* 对象存储配置对象 sys_oss_config
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("sys_oss_config")
|
||||
public class SysOssConfig extends BaseEntity {
|
||||
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
@TableId(value = "oss_config_id")
|
||||
private Long ossConfigId;
|
||||
|
||||
/**
|
||||
* 配置key
|
||||
*/
|
||||
private String configKey;
|
||||
|
||||
/**
|
||||
* accessKey
|
||||
*/
|
||||
private String accessKey;
|
||||
|
||||
/**
|
||||
* 秘钥
|
||||
*/
|
||||
private String secretKey;
|
||||
|
||||
/**
|
||||
* 桶名称
|
||||
*/
|
||||
private String bucketName;
|
||||
|
||||
/**
|
||||
* 前缀
|
||||
*/
|
||||
private String prefix;
|
||||
|
||||
/**
|
||||
* 访问站点
|
||||
*/
|
||||
private String endpoint;
|
||||
|
||||
/**
|
||||
* 自定义域名
|
||||
*/
|
||||
private String domain;
|
||||
|
||||
|
||||
/**
|
||||
* 是否https(0否 1是)
|
||||
*/
|
||||
private String isHttps;
|
||||
|
||||
/**
|
||||
* 域
|
||||
*/
|
||||
private String region;
|
||||
|
||||
/**
|
||||
* 是否默认(0=是,1=否)
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 扩展字段
|
||||
*/
|
||||
private String ext1;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 桶权限类型(0private 1public 2custom)
|
||||
*/
|
||||
private String accessPolicy;
|
||||
|
||||
}
|
@@ -0,0 +1,54 @@
|
||||
package org.dromara.resource.domain.bo;
|
||||
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.dromara.common.mybatis.core.domain.BaseEntity;
|
||||
import org.dromara.resource.domain.SysOss;
|
||||
|
||||
/**
|
||||
* OSS对象存储分页查询对象 sys_oss
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@AutoMapper(target = SysOss.class, reverseConvertGenerate = false)
|
||||
public class SysOssBo extends BaseEntity {
|
||||
|
||||
/**
|
||||
* ossId
|
||||
*/
|
||||
private Long ossId;
|
||||
|
||||
/**
|
||||
* 文件名
|
||||
*/
|
||||
private String fileName;
|
||||
|
||||
/**
|
||||
* 原名
|
||||
*/
|
||||
private String originalName;
|
||||
|
||||
/**
|
||||
* 文件后缀名
|
||||
*/
|
||||
private String fileSuffix;
|
||||
|
||||
/**
|
||||
* URL地址
|
||||
*/
|
||||
private String url;
|
||||
|
||||
/**
|
||||
* 扩展字段
|
||||
*/
|
||||
private String ext1;
|
||||
|
||||
/**
|
||||
* 服务商
|
||||
*/
|
||||
private String service;
|
||||
|
||||
}
|
@@ -0,0 +1,109 @@
|
||||
package org.dromara.resource.domain.bo;
|
||||
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.dromara.common.core.validate.AddGroup;
|
||||
import org.dromara.common.core.validate.EditGroup;
|
||||
import org.dromara.common.mybatis.core.domain.BaseEntity;
|
||||
import org.dromara.resource.domain.SysOssConfig;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
/**
|
||||
* 对象存储配置业务对象 sys_oss_config
|
||||
*
|
||||
* @author Lion Li
|
||||
* @author 孤舟烟雨
|
||||
* @date 2021-08-13
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@AutoMapper(target = SysOssConfig.class, reverseConvertGenerate = false)
|
||||
public class SysOssConfigBo extends BaseEntity {
|
||||
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
@NotNull(message = "主键不能为空", groups = {EditGroup.class})
|
||||
private Long ossConfigId;
|
||||
|
||||
/**
|
||||
* 配置key
|
||||
*/
|
||||
@NotBlank(message = "配置key不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||
@Size(min = 2, max = 100, message = "configKey长度必须介于2和20 之间")
|
||||
private String configKey;
|
||||
|
||||
/**
|
||||
* accessKey
|
||||
*/
|
||||
@NotBlank(message = "accessKey不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||
@Size(min = 2, max = 100, message = "accessKey长度必须介于2和100 之间")
|
||||
private String accessKey;
|
||||
|
||||
/**
|
||||
* 秘钥
|
||||
*/
|
||||
@NotBlank(message = "secretKey不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||
@Size(min = 2, max = 100, message = "secretKey长度必须介于2和100 之间")
|
||||
private String secretKey;
|
||||
|
||||
/**
|
||||
* 桶名称
|
||||
*/
|
||||
@NotBlank(message = "桶名称不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||
@Size(min = 2, max = 100, message = "bucketName长度必须介于2和100之间")
|
||||
private String bucketName;
|
||||
|
||||
/**
|
||||
* 前缀
|
||||
*/
|
||||
private String prefix;
|
||||
|
||||
/**
|
||||
* 访问站点
|
||||
*/
|
||||
@NotBlank(message = "访问站点不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||
@Size(min = 2, max = 100, message = "endpoint长度必须介于2和100之间")
|
||||
private String endpoint;
|
||||
|
||||
/**
|
||||
* 自定义域名
|
||||
*/
|
||||
private String domain;
|
||||
|
||||
/**
|
||||
* 是否https(Y=是,N=否)
|
||||
*/
|
||||
private String isHttps;
|
||||
|
||||
/**
|
||||
* 是否默认(0=是,1=否)
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 域
|
||||
*/
|
||||
private String region;
|
||||
|
||||
/**
|
||||
* 扩展字段
|
||||
*/
|
||||
private String ext1;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 桶权限类型(0private 1public 2custom)
|
||||
*/
|
||||
@NotBlank(message = "桶权限类型不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||
private String accessPolicy;
|
||||
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
package org.dromara.resource.domain.convert;
|
||||
|
||||
import io.github.linpeilie.BaseMapper;
|
||||
import org.dromara.resource.api.domain.RemoteFile;
|
||||
import org.dromara.resource.domain.vo.SysOssVo;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.MappingConstants;
|
||||
import org.mapstruct.ReportingPolicy;
|
||||
|
||||
/**
|
||||
* 用户信息转换器
|
||||
* @author zhujie
|
||||
*/
|
||||
@Mapper(componentModel = MappingConstants.ComponentModel.SPRING, unmappedTargetPolicy = ReportingPolicy.IGNORE)
|
||||
public interface SysOssVoConvert extends BaseMapper<SysOssVo, RemoteFile> {
|
||||
|
||||
@Mapping(target = "name", source = "fileName")
|
||||
RemoteFile convert(SysOssVo sysOssVo);
|
||||
|
||||
}
|
@@ -0,0 +1,96 @@
|
||||
package org.dromara.resource.domain.vo;
|
||||
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import lombok.Data;
|
||||
import org.dromara.resource.domain.SysOssConfig;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
|
||||
/**
|
||||
* 对象存储配置视图对象 sys_oss_config
|
||||
*
|
||||
* @author Lion Li
|
||||
* @author 孤舟烟雨
|
||||
* @date 2021-08-13
|
||||
*/
|
||||
@Data
|
||||
@AutoMapper(target = SysOssConfig.class)
|
||||
public class SysOssConfigVo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
private Long ossConfigId;
|
||||
|
||||
/**
|
||||
* 配置key
|
||||
*/
|
||||
private String configKey;
|
||||
|
||||
/**
|
||||
* accessKey
|
||||
*/
|
||||
private String accessKey;
|
||||
|
||||
/**
|
||||
* 秘钥
|
||||
*/
|
||||
private String secretKey;
|
||||
|
||||
/**
|
||||
* 桶名称
|
||||
*/
|
||||
private String bucketName;
|
||||
|
||||
/**
|
||||
* 前缀
|
||||
*/
|
||||
private String prefix;
|
||||
|
||||
/**
|
||||
* 访问站点
|
||||
*/
|
||||
private String endpoint;
|
||||
|
||||
/**
|
||||
* 自定义域名
|
||||
*/
|
||||
private String domain;
|
||||
|
||||
/**
|
||||
* 是否https(Y=是,N=否)
|
||||
*/
|
||||
private String isHttps;
|
||||
|
||||
/**
|
||||
* 域
|
||||
*/
|
||||
private String region;
|
||||
|
||||
/**
|
||||
* 是否默认(0=是,1=否)
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 扩展字段
|
||||
*/
|
||||
private String ext1;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 桶权限类型(0private 1public 2custom)
|
||||
*/
|
||||
private String accessPolicy;
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1,34 @@
|
||||
package org.dromara.resource.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 上传对象信息
|
||||
*
|
||||
* @author Michelle.Chung
|
||||
*/
|
||||
@Data
|
||||
public class SysOssUploadVo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* URL地址
|
||||
*/
|
||||
private String url;
|
||||
|
||||
/**
|
||||
* 文件名
|
||||
*/
|
||||
private String fileName;
|
||||
|
||||
/**
|
||||
* 对象存储主键
|
||||
*/
|
||||
private String ossId;
|
||||
|
||||
}
|
@@ -0,0 +1,77 @@
|
||||
package org.dromara.resource.domain.vo;
|
||||
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import lombok.Data;
|
||||
import org.dromara.common.translation.annotation.Translation;
|
||||
import org.dromara.common.translation.constant.TransConstant;
|
||||
import org.dromara.resource.domain.SysOss;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* OSS对象存储视图对象 sys_oss
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@Data
|
||||
@AutoMapper(target = SysOss.class)
|
||||
public class SysOssVo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 对象存储主键
|
||||
*/
|
||||
private Long ossId;
|
||||
|
||||
/**
|
||||
* 文件名
|
||||
*/
|
||||
private String fileName;
|
||||
|
||||
/**
|
||||
* 原名
|
||||
*/
|
||||
private String originalName;
|
||||
|
||||
/**
|
||||
* 文件后缀名
|
||||
*/
|
||||
private String fileSuffix;
|
||||
|
||||
/**
|
||||
* URL地址
|
||||
*/
|
||||
private String url;
|
||||
|
||||
/**
|
||||
* 扩展字段
|
||||
*/
|
||||
private String ext1;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 上传人
|
||||
*/
|
||||
private Long createBy;
|
||||
|
||||
/**
|
||||
* 上传人名称
|
||||
*/
|
||||
@Translation(type = TransConstant.USER_ID_TO_NAME, mapper = "createBy")
|
||||
private String createByName;
|
||||
|
||||
/**
|
||||
* 服务商
|
||||
*/
|
||||
private String service;
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1,89 @@
|
||||
package org.dromara.resource.dubbo;
|
||||
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.dubbo.config.annotation.DubboService;
|
||||
import org.dromara.common.core.exception.ServiceException;
|
||||
import org.dromara.common.core.utils.MapstructUtils;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.oss.core.OssClient;
|
||||
import org.dromara.common.oss.entity.UploadResult;
|
||||
import org.dromara.common.oss.factory.OssFactory;
|
||||
import org.dromara.resource.api.RemoteFileService;
|
||||
import org.dromara.resource.api.domain.RemoteFile;
|
||||
import org.dromara.resource.domain.bo.SysOssBo;
|
||||
import org.dromara.resource.domain.vo.SysOssVo;
|
||||
import org.dromara.resource.service.ISysOssService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 文件请求处理
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@DubboService
|
||||
public class RemoteFileServiceImpl implements RemoteFileService {
|
||||
|
||||
private final ISysOssService sysOssService;
|
||||
|
||||
/**
|
||||
* 文件上传请求
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public RemoteFile upload(String name, String originalFilename, String contentType, byte[] file) throws ServiceException {
|
||||
try {
|
||||
String suffix = StringUtils.substring(originalFilename, originalFilename.lastIndexOf("."), originalFilename.length());
|
||||
OssClient storage = OssFactory.instance();
|
||||
UploadResult uploadResult = storage.uploadSuffix(file, suffix, contentType);
|
||||
// 保存文件信息
|
||||
SysOssBo oss = new SysOssBo();
|
||||
oss.setUrl(uploadResult.getUrl());
|
||||
oss.setFileSuffix(suffix);
|
||||
oss.setFileName(uploadResult.getFilename());
|
||||
oss.setOriginalName(originalFilename);
|
||||
oss.setService(storage.getConfigKey());
|
||||
sysOssService.insertByBo(oss);
|
||||
RemoteFile sysFile = new RemoteFile();
|
||||
sysFile.setOssId(oss.getOssId());
|
||||
sysFile.setName(uploadResult.getFilename());
|
||||
sysFile.setUrl(uploadResult.getUrl());
|
||||
sysFile.setOriginalName(originalFilename);
|
||||
sysFile.setFileSuffix(suffix);
|
||||
return sysFile;
|
||||
} catch (Exception e) {
|
||||
log.error("上传文件失败", e);
|
||||
throw new ServiceException("上传文件失败");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过ossId查询对应的url
|
||||
*
|
||||
* @param ossIds ossId串逗号分隔
|
||||
* @return url串逗号分隔
|
||||
*/
|
||||
@Override
|
||||
public String selectUrlByIds(String ossIds) {
|
||||
return sysOssService.selectUrlByIds(ossIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过ossId查询列表
|
||||
*
|
||||
* @param ossIds ossId串逗号分隔
|
||||
* @return 列表
|
||||
*/
|
||||
@Override
|
||||
public List<RemoteFile> selectByIds(String ossIds){
|
||||
List<SysOssVo> sysOssVos = sysOssService.listByIds(StringUtils.splitTo(ossIds, Convert::toLong));
|
||||
return MapstructUtils.convert(sysOssVos, RemoteFile.class);
|
||||
}
|
||||
}
|
@@ -0,0 +1,34 @@
|
||||
package org.dromara.resource.dubbo;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.dubbo.config.annotation.DubboService;
|
||||
import org.dromara.common.core.exception.ServiceException;
|
||||
import org.dromara.common.mail.utils.MailUtils;
|
||||
import org.dromara.resource.api.RemoteMailService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 邮件服务
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
@DubboService
|
||||
public class RemoteMailServiceImpl implements RemoteMailService {
|
||||
|
||||
/**
|
||||
* 发送邮件
|
||||
*
|
||||
* @param to 接收人
|
||||
* @param subject 标题
|
||||
* @param text 内容
|
||||
*/
|
||||
@Override
|
||||
public void send(String to, String subject, String text) throws ServiceException {
|
||||
MailUtils.sendText(to, subject, text);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,48 @@
|
||||
package org.dromara.resource.dubbo;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.dubbo.config.annotation.DubboService;
|
||||
import org.dromara.common.sse.dto.SseMessageDto;
|
||||
import org.dromara.common.sse.utils.SseMessageUtils;
|
||||
import org.dromara.resource.api.RemoteMessageService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 消息服务
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
@DubboService
|
||||
public class RemoteMessageServiceImpl implements RemoteMessageService {
|
||||
|
||||
/**
|
||||
* 发送消息
|
||||
*
|
||||
* @param sessionKey session主键 一般为用户id
|
||||
* @param message 消息文本
|
||||
*/
|
||||
@Override
|
||||
public void publishMessage(List<Long> sessionKey, String message) {
|
||||
SseMessageDto dto = new SseMessageDto();
|
||||
dto.setMessage(message);
|
||||
dto.setUserIds(sessionKey);
|
||||
SseMessageUtils.publishMessage(dto);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发布订阅的消息(群发)
|
||||
*
|
||||
* @param message 消息内容
|
||||
*/
|
||||
@Override
|
||||
public void publishAll(String message) {
|
||||
SseMessageUtils.publishAll(message);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,236 @@
|
||||
package org.dromara.resource.dubbo;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.dubbo.config.annotation.DubboService;
|
||||
import org.dromara.resource.api.RemoteSmsService;
|
||||
import org.dromara.resource.api.domain.RemoteSms;
|
||||
import org.dromara.sms4j.api.SmsBlend;
|
||||
import org.dromara.sms4j.api.entity.SmsResponse;
|
||||
import org.dromara.sms4j.core.factory.SmsFactory;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 短信服务
|
||||
*
|
||||
* @author Feng
|
||||
*/
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
@DubboService
|
||||
public class RemoteSmsServiceImpl implements RemoteSmsService {
|
||||
|
||||
/**
|
||||
* 获取特定供应商类型的 SmsBlend 实例
|
||||
*
|
||||
* @return SmsBlend 实例,代表指定供应商类型
|
||||
*/
|
||||
private SmsBlend getSmsBlend() {
|
||||
// 可自定义厂商配置获取规则 例如根据租户获取 或 负载均衡多个厂商等
|
||||
return SmsFactory.getSmsBlend("config1");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据给定的 SmsResponse 对象创建并返回一个 RemoteSms 对象,封装短信发送的响应信息
|
||||
*
|
||||
* @param smsResponse 短信发送的响应信息
|
||||
* @return 封装了短信发送结果的 RemoteSms 对象
|
||||
*/
|
||||
private RemoteSms getRemoteSms(SmsResponse smsResponse) {
|
||||
// 创建一个 RemoteSms 对象,封装响应信息
|
||||
RemoteSms sms = new RemoteSms();
|
||||
sms.setSuccess(smsResponse.isSuccess());
|
||||
sms.setResponse(smsResponse.getData().toString());
|
||||
sms.setConfigId(smsResponse.getConfigId());
|
||||
return sms;
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步方法:发送简单文本短信
|
||||
*
|
||||
* @param phone 目标手机号
|
||||
* @param message 短信内容
|
||||
* @return 封装了短信发送结果的 RemoteSms 对象
|
||||
*/
|
||||
@Override
|
||||
public RemoteSms sendMessage(String phone, String message) {
|
||||
// 调用 getSmsBlend 方法获取对应短信供应商的 SmsBlend 实例
|
||||
SmsResponse smsResponse = getSmsBlend().sendMessage(phone, message);
|
||||
return getRemoteSms(smsResponse);
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步方法:发送固定消息模板多模板参数短信
|
||||
*
|
||||
* @param phone 目标手机号
|
||||
* @param messages 短信模板参数,使用 LinkedHashMap 以保持参数顺序
|
||||
* @return 封装了短信发送结果的 RemoteSms 对象
|
||||
*/
|
||||
@Override
|
||||
public RemoteSms sendMessage(String phone, LinkedHashMap<String, String> messages) {
|
||||
SmsResponse smsResponse = getSmsBlend().sendMessage(phone, messages);
|
||||
return getRemoteSms(smsResponse);
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步方法:发送带参数的短信
|
||||
*
|
||||
* @param phone 目标手机号
|
||||
* @param templateId 短信模板ID
|
||||
* @param messages 短信模板参数,使用 LinkedHashMap 以保持参数顺序
|
||||
* @return 封装了短信发送结果的 RemoteSms 对象
|
||||
*/
|
||||
@Override
|
||||
public RemoteSms sendMessage(String phone, String templateId, LinkedHashMap<String, String> messages) {
|
||||
// 调用 getSmsBlend 方法获取对应短信供应商的 SmsBlend 实例
|
||||
SmsResponse smsResponse = getSmsBlend().sendMessage(phone, templateId, messages);
|
||||
return getRemoteSms(smsResponse);
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步方法:群发简单文本短信
|
||||
*
|
||||
* @param phones 目标手机号列表
|
||||
* @param message 短信内容
|
||||
* @return 封装了短信发送结果的 RemoteSms 对象
|
||||
*/
|
||||
@Override
|
||||
public RemoteSms messageTexting(List<String> phones, String message) {
|
||||
// 调用 getSmsBlend 方法获取对应短信供应商的 SmsBlend 实例
|
||||
SmsResponse smsResponse = getSmsBlend().massTexting(phones, message);
|
||||
return getRemoteSms(smsResponse);
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步方法:群发带参数的短信
|
||||
*
|
||||
* @param phones 目标手机号列表
|
||||
* @param templateId 短信模板ID
|
||||
* @param messages 短信模板参数,使用 LinkedHashMap 以保持参数顺序
|
||||
* @return 封装了短信发送结果的 RemoteSms 对象
|
||||
*/
|
||||
@Override
|
||||
public RemoteSms messageTexting(List<String> phones, String templateId, LinkedHashMap<String, String> messages) {
|
||||
// 调用 getSmsBlend 方法获取对应短信供应商的 SmsBlend 实例
|
||||
SmsResponse smsResponse = getSmsBlend().massTexting(phones, templateId, messages);
|
||||
return getRemoteSms(smsResponse);
|
||||
}
|
||||
|
||||
/**
|
||||
* 异步方法:发送简单文本短信
|
||||
*
|
||||
* @param phone 目标手机号
|
||||
* @param message 短信内容
|
||||
*/
|
||||
@Override
|
||||
public void sendMessageAsync(String phone, String message) {
|
||||
getSmsBlend().sendMessageAsync(phone, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 异步方法:发送带参数的短信
|
||||
*
|
||||
* @param phone 目标手机号
|
||||
* @param templateId 短信模板ID
|
||||
* @param messages 短信模板参数,使用 LinkedHashMap 以保持参数顺序
|
||||
*/
|
||||
@Override
|
||||
public void sendMessageAsync(String phone, String templateId, LinkedHashMap<String, String> messages) {
|
||||
getSmsBlend().sendMessageAsync(phone, templateId, messages);
|
||||
}
|
||||
|
||||
/**
|
||||
* 延迟发送简单文本短信
|
||||
*
|
||||
* @param phone 目标手机号
|
||||
* @param message 短信内容
|
||||
* @param delayedTime 延迟发送时间(毫秒)
|
||||
*/
|
||||
@Override
|
||||
public void delayMessage(String phone, String message, Long delayedTime) {
|
||||
getSmsBlend().delayedMessage(phone, message, delayedTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* 延迟发送带参数的短信
|
||||
*
|
||||
* @param phone 目标手机号
|
||||
* @param templateId 短信模板ID
|
||||
* @param messages 短信模板参数,使用 LinkedHashMap 以保持参数顺序
|
||||
* @param delayedTime 延迟发送时间(毫秒)
|
||||
*/
|
||||
@Override
|
||||
public void delayMessage(String phone, String templateId, LinkedHashMap<String, String> messages, Long delayedTime) {
|
||||
getSmsBlend().delayedMessage(phone, templateId, messages, delayedTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* 延迟群发简单文本短信
|
||||
*
|
||||
* @param phones 目标手机号列表
|
||||
* @param message 短信内容
|
||||
* @param delayedTime 延迟发送时间(毫秒)
|
||||
*/
|
||||
@Override
|
||||
public void delayMessageTexting(List<String> phones, String message, Long delayedTime) {
|
||||
getSmsBlend().delayMassTexting(phones, message, delayedTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* 延迟批量发送带参数的短信
|
||||
*
|
||||
* @param phones 目标手机号列表
|
||||
* @param templateId 短信模板ID
|
||||
* @param messages 短信模板参数,使用 LinkedHashMap 以保持参数顺序
|
||||
* @param delayedTime 延迟发送时间(毫秒)
|
||||
*/
|
||||
@Override
|
||||
public void delayMessageTexting(List<String> phones, String templateId, LinkedHashMap<String, String> messages, Long delayedTime) {
|
||||
getSmsBlend().delayMassTexting(phones, templateId, messages, delayedTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* 加入黑名单
|
||||
*
|
||||
* @param phone 手机号
|
||||
*/
|
||||
@Override
|
||||
public void addBlacklist(String phone) {
|
||||
getSmsBlend().joinInBlacklist(phone);
|
||||
}
|
||||
|
||||
/**
|
||||
* 加入黑名单
|
||||
*
|
||||
* @param phones 手机号列表
|
||||
*/
|
||||
@Override
|
||||
public void addBlacklist(List<String> phones) {
|
||||
getSmsBlend().batchJoinBlacklist(phones);
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除黑名单
|
||||
*
|
||||
* @param phone 手机号
|
||||
*/
|
||||
@Override
|
||||
public void removeBlacklist(String phone) {
|
||||
getSmsBlend().removeFromBlacklist(phone);
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除黑名单
|
||||
*
|
||||
* @param phones 手机号
|
||||
*/
|
||||
@Override
|
||||
public void removeBlacklist(List<String> phones) {
|
||||
getSmsBlend().batchRemovalFromBlacklist(phones);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,17 @@
|
||||
package org.dromara.resource.mapper;
|
||||
|
||||
|
||||
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
|
||||
import org.dromara.resource.domain.SysOssConfig;
|
||||
import org.dromara.resource.domain.vo.SysOssConfigVo;
|
||||
|
||||
/**
|
||||
* 对象存储配置Mapper接口
|
||||
*
|
||||
* @author Lion Li
|
||||
* @author 孤舟烟雨
|
||||
* @date 2021-08-13
|
||||
*/
|
||||
public interface SysOssConfigMapper extends BaseMapperPlus<SysOssConfig, SysOssConfigVo> {
|
||||
|
||||
}
|
@@ -0,0 +1,14 @@
|
||||
package org.dromara.resource.mapper;
|
||||
|
||||
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
|
||||
import org.dromara.resource.domain.SysOss;
|
||||
import org.dromara.resource.domain.vo.SysOssVo;
|
||||
|
||||
/**
|
||||
* 文件上传 数据层
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
public interface SysOssMapper extends BaseMapperPlus<SysOss, SysOssVo> {
|
||||
|
||||
}
|
@@ -0,0 +1,28 @@
|
||||
package org.dromara.resource.runner;
|
||||
|
||||
import org.dromara.resource.service.ISysOssConfigService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.ApplicationArguments;
|
||||
import org.springframework.boot.ApplicationRunner;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 初始化 system 模块对应业务数据
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@Component
|
||||
public class ResourceApplicationRunner implements ApplicationRunner {
|
||||
|
||||
private final ISysOssConfigService ossConfigService;
|
||||
|
||||
@Override
|
||||
public void run(ApplicationArguments args) throws Exception {
|
||||
ossConfigService.init();
|
||||
log.info("初始化OSS配置成功");
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,66 @@
|
||||
package org.dromara.resource.service;
|
||||
|
||||
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.resource.domain.bo.SysOssConfigBo;
|
||||
import org.dromara.resource.domain.vo.SysOssConfigVo;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* 对象存储配置Service接口
|
||||
*
|
||||
* @author Lion Li
|
||||
* @author 孤舟烟雨
|
||||
* @date 2021-08-13
|
||||
*/
|
||||
public interface ISysOssConfigService {
|
||||
|
||||
/**
|
||||
* 初始化OSS配置
|
||||
*/
|
||||
void init();
|
||||
|
||||
/**
|
||||
* 查询单个
|
||||
*/
|
||||
SysOssConfigVo queryById(Long ossConfigId);
|
||||
|
||||
/**
|
||||
* 查询列表
|
||||
*/
|
||||
TableDataInfo<SysOssConfigVo> queryPageList(SysOssConfigBo bo, PageQuery pageQuery);
|
||||
|
||||
|
||||
/**
|
||||
* 根据新增业务对象插入对象存储配置
|
||||
*
|
||||
* @param bo 对象存储配置新增业务对象
|
||||
* @return 结果
|
||||
*/
|
||||
Boolean insertByBo(SysOssConfigBo bo);
|
||||
|
||||
/**
|
||||
* 根据编辑业务对象修改对象存储配置
|
||||
*
|
||||
* @param bo 对象存储配置编辑业务对象
|
||||
* @return 结果
|
||||
*/
|
||||
Boolean updateByBo(SysOssConfigBo bo);
|
||||
|
||||
/**
|
||||
* 校验并删除数据
|
||||
*
|
||||
* @param ids 主键集合
|
||||
* @param isValid 是否校验,true-删除前校验,false-不校验
|
||||
* @return 结果
|
||||
*/
|
||||
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||
|
||||
/**
|
||||
* 启用停用状态
|
||||
*/
|
||||
int updateOssConfigStatus(SysOssConfigBo bo);
|
||||
|
||||
}
|
@@ -0,0 +1,95 @@
|
||||
package org.dromara.resource.service;
|
||||
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.resource.domain.bo.SysOssBo;
|
||||
import org.dromara.resource.domain.vo.SysOssVo;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 文件上传 服务层
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
public interface ISysOssService {
|
||||
|
||||
/**
|
||||
* 查询OSS对象存储列表
|
||||
*
|
||||
* @param sysOss OSS对象存储分页查询对象
|
||||
* @param pageQuery 分页查询实体类
|
||||
* @return 结果
|
||||
*/
|
||||
TableDataInfo<SysOssVo> queryPageList(SysOssBo sysOss, PageQuery pageQuery);
|
||||
|
||||
/**
|
||||
* 根据一组 ossIds 获取对应的 SysOssVo 列表
|
||||
*
|
||||
* @param ossIds 一组文件在数据库中的唯一标识集合
|
||||
* @return 包含 SysOssVo 对象的列表
|
||||
*/
|
||||
List<SysOssVo> listByIds(Collection<Long> ossIds);
|
||||
|
||||
/**
|
||||
* 根据一组 ossIds 获取对应文件的 URL 列表
|
||||
*
|
||||
* @param ossIds 以逗号分隔的 ossId 字符串
|
||||
* @return 以逗号分隔的文件 URL 字符串
|
||||
*/
|
||||
String selectUrlByIds(String ossIds);
|
||||
|
||||
/**
|
||||
* 根据 ossId 从缓存或数据库中获取 SysOssVo 对象
|
||||
*
|
||||
* @param ossId 文件在数据库中的唯一标识
|
||||
* @return SysOssVo 对象,包含文件信息
|
||||
*/
|
||||
SysOssVo getById(Long ossId);
|
||||
|
||||
/**
|
||||
* 上传 MultipartFile 到对象存储服务,并保存文件信息到数据库
|
||||
*
|
||||
* @param file 要上传的 MultipartFile 对象
|
||||
* @return 上传成功后的 SysOssVo 对象,包含文件信息
|
||||
*/
|
||||
SysOssVo upload(MultipartFile file);
|
||||
|
||||
/**
|
||||
* 上传文件到对象存储服务,并保存文件信息到数据库
|
||||
*
|
||||
* @param file 要上传的文件对象
|
||||
* @return 上传成功后的 SysOssVo 对象,包含文件信息
|
||||
*/
|
||||
SysOssVo upload(File file);
|
||||
|
||||
/**
|
||||
* 新增OSS对象存储
|
||||
*
|
||||
* @param bo SysOssBo 对象,包含待插入的数据
|
||||
* @return 插入操作是否成功的布尔值
|
||||
*/
|
||||
Boolean insertByBo(SysOssBo bo);
|
||||
|
||||
/**
|
||||
* 文件下载方法,支持一次性下载完整文件
|
||||
*
|
||||
* @param ossId OSS对象ID
|
||||
* @param response HttpServletResponse对象,用于设置响应头和向客户端发送文件内容
|
||||
*/
|
||||
void download(Long ossId, HttpServletResponse response) throws IOException;
|
||||
|
||||
/**
|
||||
* 删除OSS对象存储
|
||||
*
|
||||
* @param ids OSS对象ID串
|
||||
* @param isValid 判断是否需要校验
|
||||
* @return 结果
|
||||
*/
|
||||
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||
}
|
@@ -0,0 +1,176 @@
|
||||
package org.dromara.resource.service.impl;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.common.core.constant.CacheNames;
|
||||
import org.dromara.common.core.exception.ServiceException;
|
||||
import org.dromara.common.core.utils.ObjectUtils;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.json.utils.JsonUtils;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.oss.constant.OssConstant;
|
||||
import org.dromara.common.redis.utils.CacheUtils;
|
||||
import org.dromara.common.redis.utils.RedisUtils;
|
||||
import org.dromara.resource.domain.SysOssConfig;
|
||||
import org.dromara.resource.domain.bo.SysOssConfigBo;
|
||||
import org.dromara.resource.domain.vo.SysOssConfigVo;
|
||||
import org.dromara.resource.mapper.SysOssConfigMapper;
|
||||
import org.dromara.resource.service.ISysOssConfigService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 对象存储配置Service业务层处理
|
||||
*
|
||||
* @author Lion Li
|
||||
* @author 孤舟烟雨
|
||||
* @date 2021-08-13
|
||||
*/
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class SysOssConfigServiceImpl implements ISysOssConfigService {
|
||||
|
||||
private final SysOssConfigMapper baseMapper;
|
||||
|
||||
/**
|
||||
* 项目启动时,初始化参数到缓存,加载配置类
|
||||
*/
|
||||
@Override
|
||||
public void init() {
|
||||
List<SysOssConfig> list = baseMapper.selectList();
|
||||
// 加载OSS初始化配置
|
||||
for (SysOssConfig config : list) {
|
||||
String configKey = config.getConfigKey();
|
||||
if ("0".equals(config.getStatus())) {
|
||||
RedisUtils.setCacheObject(OssConstant.DEFAULT_CONFIG_KEY, configKey);
|
||||
}
|
||||
CacheUtils.put(CacheNames.SYS_OSS_CONFIG, config.getConfigKey(), JsonUtils.toJsonString(config));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SysOssConfigVo queryById(Long ossConfigId) {
|
||||
return baseMapper.selectVoById(ossConfigId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableDataInfo<SysOssConfigVo> queryPageList(SysOssConfigBo bo, PageQuery pageQuery) {
|
||||
LambdaQueryWrapper<SysOssConfig> lqw = buildQueryWrapper(bo);
|
||||
Page<SysOssConfigVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
|
||||
return TableDataInfo.build(result);
|
||||
}
|
||||
|
||||
|
||||
private LambdaQueryWrapper<SysOssConfig> buildQueryWrapper(SysOssConfigBo bo) {
|
||||
LambdaQueryWrapper<SysOssConfig> lqw = Wrappers.lambdaQuery();
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getConfigKey()), SysOssConfig::getConfigKey, bo.getConfigKey());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getBucketName()), SysOssConfig::getBucketName, bo.getBucketName());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getStatus()), SysOssConfig::getStatus, bo.getStatus());
|
||||
lqw.orderByAsc(SysOssConfig::getOssConfigId);
|
||||
return lqw;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean insertByBo(SysOssConfigBo bo) {
|
||||
SysOssConfig config = BeanUtil.toBean(bo, SysOssConfig.class);
|
||||
validEntityBeforeSave(config);
|
||||
boolean flag = baseMapper.insert(config) > 0;
|
||||
if (flag) {
|
||||
// 从数据库查询完整的数据做缓存
|
||||
config = baseMapper.selectById(config.getOssConfigId());
|
||||
CacheUtils.put(CacheNames.SYS_OSS_CONFIG, config.getConfigKey(), JsonUtils.toJsonString(config));
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean updateByBo(SysOssConfigBo bo) {
|
||||
SysOssConfig config = BeanUtil.toBean(bo, SysOssConfig.class);
|
||||
validEntityBeforeSave(config);
|
||||
LambdaUpdateWrapper<SysOssConfig> luw = new LambdaUpdateWrapper<>();
|
||||
luw.set(ObjectUtil.isNull(config.getPrefix()), SysOssConfig::getPrefix, "");
|
||||
luw.set(ObjectUtil.isNull(config.getRegion()), SysOssConfig::getRegion, "");
|
||||
luw.set(ObjectUtil.isNull(config.getExt1()), SysOssConfig::getExt1, "");
|
||||
luw.set(ObjectUtil.isNull(config.getRemark()), SysOssConfig::getRemark, "");
|
||||
luw.eq(SysOssConfig::getOssConfigId, config.getOssConfigId());
|
||||
boolean flag = baseMapper.update(config, luw) > 0;
|
||||
if (flag) {
|
||||
// 从数据库查询完整的数据做缓存
|
||||
config = baseMapper.selectById(config.getOssConfigId());
|
||||
CacheUtils.put(CacheNames.SYS_OSS_CONFIG, config.getConfigKey(), JsonUtils.toJsonString(config));
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存前的数据校验
|
||||
*/
|
||||
private void validEntityBeforeSave(SysOssConfig entity) {
|
||||
if (StringUtils.isNotEmpty(entity.getConfigKey()) && !checkConfigKeyUnique(entity)) {
|
||||
throw new ServiceException("操作配置'" + entity.getConfigKey() + "'失败, 配置key已存在!");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
||||
if (isValid) {
|
||||
if (CollUtil.containsAny(ids, OssConstant.SYSTEM_DATA_IDS)) {
|
||||
throw new ServiceException("系统内置, 不可删除!");
|
||||
}
|
||||
}
|
||||
List<SysOssConfig> list = CollUtil.newArrayList();
|
||||
for (Long configId : ids) {
|
||||
SysOssConfig config = baseMapper.selectById(configId);
|
||||
list.add(config);
|
||||
}
|
||||
boolean flag = baseMapper.deleteByIds(ids) > 0;
|
||||
if (flag) {
|
||||
list.forEach(sysOssConfig ->
|
||||
CacheUtils.evict(CacheNames.SYS_OSS_CONFIG, sysOssConfig.getConfigKey()));
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断configKey是否唯一
|
||||
*/
|
||||
private boolean checkConfigKeyUnique(SysOssConfig sysOssConfig) {
|
||||
long ossConfigId = ObjectUtils.notNull(sysOssConfig.getOssConfigId(), -1L);
|
||||
SysOssConfig info = baseMapper.selectOne(new LambdaQueryWrapper<SysOssConfig>()
|
||||
.select(SysOssConfig::getOssConfigId, SysOssConfig::getConfigKey)
|
||||
.eq(SysOssConfig::getConfigKey, sysOssConfig.getConfigKey()));
|
||||
if (ObjectUtil.isNotNull(info) && info.getOssConfigId() != ossConfigId) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 启用禁用状态
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public int updateOssConfigStatus(SysOssConfigBo bo) {
|
||||
SysOssConfig sysOssConfig = BeanUtil.toBean(bo, SysOssConfig.class);
|
||||
int row = baseMapper.update(null, new LambdaUpdateWrapper<SysOssConfig>()
|
||||
.set(SysOssConfig::getStatus, "1"));
|
||||
row += baseMapper.updateById(sysOssConfig);
|
||||
if (row > 0) {
|
||||
RedisUtils.setCacheObject(OssConstant.DEFAULT_CONFIG_KEY, sysOssConfig.getConfigKey());
|
||||
}
|
||||
return row;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,263 @@
|
||||
package org.dromara.resource.service.impl;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.dromara.common.core.constant.CacheNames;
|
||||
import org.dromara.common.core.exception.ServiceException;
|
||||
import org.dromara.common.core.utils.MapstructUtils;
|
||||
import org.dromara.common.core.utils.SpringUtils;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.core.utils.file.FileUtils;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.oss.core.OssClient;
|
||||
import org.dromara.common.oss.entity.UploadResult;
|
||||
import org.dromara.common.oss.enums.AccessPolicyType;
|
||||
import org.dromara.common.oss.factory.OssFactory;
|
||||
import org.dromara.resource.domain.SysOss;
|
||||
import org.dromara.resource.domain.bo.SysOssBo;
|
||||
import org.dromara.resource.domain.vo.SysOssVo;
|
||||
import org.dromara.resource.mapper.SysOssMapper;
|
||||
import org.dromara.resource.service.ISysOssService;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 文件上传 服务层实现
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class SysOssServiceImpl implements ISysOssService {
|
||||
|
||||
private final SysOssMapper baseMapper;
|
||||
|
||||
/**
|
||||
* 查询OSS对象存储列表
|
||||
*
|
||||
* @param bo OSS对象存储分页查询对象
|
||||
* @param pageQuery 分页查询实体类
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public TableDataInfo<SysOssVo> queryPageList(SysOssBo bo, PageQuery pageQuery) {
|
||||
LambdaQueryWrapper<SysOss> lqw = buildQueryWrapper(bo);
|
||||
Page<SysOssVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
|
||||
List<SysOssVo> filterResult = result.getRecords().stream().map(this::matchingUrl).collect(Collectors.toList());
|
||||
result.setRecords(filterResult);
|
||||
return TableDataInfo.build(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据一组 ossIds 获取对应的 SysOssVo 列表
|
||||
*
|
||||
* @param ossIds 一组文件在数据库中的唯一标识集合
|
||||
* @return 包含 SysOssVo 对象的列表
|
||||
*/
|
||||
@Override
|
||||
public List<SysOssVo> listByIds(Collection<Long> ossIds) {
|
||||
List<SysOssVo> list = new ArrayList<>();
|
||||
SysOssServiceImpl ossService = SpringUtils.getAopProxy(this);
|
||||
for (Long id : ossIds) {
|
||||
SysOssVo vo = ossService.getById(id);
|
||||
if (ObjectUtil.isNotNull(vo)) {
|
||||
try {
|
||||
list.add(this.matchingUrl(vo));
|
||||
} catch (Exception ignored) {
|
||||
// 如果oss异常无法连接则将数据直接返回
|
||||
list.add(vo);
|
||||
}
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据一组 ossIds 获取对应文件的 URL 列表
|
||||
*
|
||||
* @param ossIds 以逗号分隔的 ossId 字符串
|
||||
* @return 以逗号分隔的文件 URL 字符串
|
||||
*/
|
||||
@Override
|
||||
public String selectUrlByIds(String ossIds) {
|
||||
List<String> list = new ArrayList<>();
|
||||
SysOssServiceImpl ossService = SpringUtils.getAopProxy(this);
|
||||
for (Long id : StringUtils.splitTo(ossIds, Convert::toLong)) {
|
||||
SysOssVo vo = ossService.getById(id);
|
||||
if (ObjectUtil.isNotNull(vo)) {
|
||||
try {
|
||||
list.add(this.matchingUrl(vo).getUrl());
|
||||
} catch (Exception ignored) {
|
||||
// 如果oss异常无法连接则将数据直接返回
|
||||
list.add(vo.getUrl());
|
||||
}
|
||||
}
|
||||
}
|
||||
return String.join(StringUtils.SEPARATOR, list);
|
||||
}
|
||||
|
||||
private LambdaQueryWrapper<SysOss> buildQueryWrapper(SysOssBo bo) {
|
||||
Map<String, Object> params = bo.getParams();
|
||||
LambdaQueryWrapper<SysOss> lqw = Wrappers.lambdaQuery();
|
||||
lqw.like(StringUtils.isNotBlank(bo.getFileName()), SysOss::getFileName, bo.getFileName());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getOriginalName()), SysOss::getOriginalName, bo.getOriginalName());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getFileSuffix()), SysOss::getFileSuffix, bo.getFileSuffix());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getUrl()), SysOss::getUrl, bo.getUrl());
|
||||
lqw.between(params.get("beginCreateTime") != null && params.get("endCreateTime") != null,
|
||||
SysOss::getCreateTime, params.get("beginCreateTime"), params.get("endCreateTime"));
|
||||
lqw.eq(ObjectUtil.isNotNull(bo.getCreateBy()), SysOss::getCreateBy, bo.getCreateBy());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getService()), SysOss::getService, bo.getService());
|
||||
lqw.orderByAsc(SysOss::getOssId);
|
||||
return lqw;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 ossId 从缓存或数据库中获取 SysOssVo 对象
|
||||
*
|
||||
* @param ossId 文件在数据库中的唯一标识
|
||||
* @return SysOssVo 对象,包含文件信息
|
||||
*/
|
||||
@Cacheable(cacheNames = CacheNames.SYS_OSS, key = "#ossId")
|
||||
@Override
|
||||
public SysOssVo getById(Long ossId) {
|
||||
return baseMapper.selectVoById(ossId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 文件下载方法,支持一次性下载完整文件
|
||||
*
|
||||
* @param ossId OSS对象ID
|
||||
* @param response HttpServletResponse对象,用于设置响应头和向客户端发送文件内容
|
||||
*/
|
||||
@Override
|
||||
public void download(Long ossId, HttpServletResponse response) throws IOException {
|
||||
SysOssVo sysOss = SpringUtils.getAopProxy(this).getById(ossId);
|
||||
if (ObjectUtil.isNull(sysOss)) {
|
||||
throw new ServiceException("文件数据不存在!");
|
||||
}
|
||||
FileUtils.setAttachmentResponseHeader(response, sysOss.getOriginalName());
|
||||
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE + "; charset=UTF-8");
|
||||
OssClient storage = OssFactory.instance(sysOss.getService());
|
||||
storage.download(sysOss.getFileName(), response.getOutputStream(), response::setContentLengthLong);
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传 MultipartFile 到对象存储服务,并保存文件信息到数据库
|
||||
*
|
||||
* @param file 要上传的 MultipartFile 对象
|
||||
* @return 上传成功后的 SysOssVo 对象,包含文件信息
|
||||
* @throws ServiceException 如果上传过程中发生异常,则抛出 ServiceException 异常
|
||||
*/
|
||||
@Override
|
||||
public SysOssVo upload(MultipartFile file) {
|
||||
String originalfileName = file.getOriginalFilename();
|
||||
String suffix = StringUtils.substring(originalfileName, originalfileName.lastIndexOf("."), originalfileName.length());
|
||||
OssClient storage = OssFactory.instance();
|
||||
UploadResult uploadResult;
|
||||
try {
|
||||
uploadResult = storage.uploadSuffix(file.getBytes(), suffix, file.getContentType());
|
||||
} catch (IOException e) {
|
||||
throw new ServiceException(e.getMessage());
|
||||
}
|
||||
// 保存文件信息
|
||||
return buildResultEntity(originalfileName, suffix, storage.getConfigKey(), uploadResult);
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传文件到对象存储服务,并保存文件信息到数据库
|
||||
*
|
||||
* @param file 要上传的文件对象
|
||||
* @return 上传成功后的 SysOssVo 对象,包含文件信息
|
||||
*/
|
||||
@Override
|
||||
public SysOssVo upload(File file) {
|
||||
String originalfileName = file.getName();
|
||||
String suffix = StringUtils.substring(originalfileName, originalfileName.lastIndexOf("."), originalfileName.length());
|
||||
OssClient storage = OssFactory.instance();
|
||||
UploadResult uploadResult = storage.uploadSuffix(file, suffix);
|
||||
// 保存文件信息
|
||||
return buildResultEntity(originalfileName, suffix, storage.getConfigKey(), uploadResult);
|
||||
}
|
||||
|
||||
private SysOssVo buildResultEntity(String originalfileName, String suffix, String configKey, UploadResult uploadResult) {
|
||||
SysOss oss = new SysOss();
|
||||
oss.setUrl(uploadResult.getUrl());
|
||||
oss.setFileSuffix(suffix);
|
||||
oss.setFileName(uploadResult.getFilename());
|
||||
oss.setOriginalName(originalfileName);
|
||||
oss.setService(configKey);
|
||||
baseMapper.insert(oss);
|
||||
SysOssVo sysOssVo = MapstructUtils.convert(oss, SysOssVo.class);
|
||||
return this.matchingUrl(sysOssVo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增OSS对象存储
|
||||
*
|
||||
* @param bo SysOssBo 对象,包含待插入的数据
|
||||
* @return 插入操作是否成功的布尔值
|
||||
*/
|
||||
@Override
|
||||
public Boolean insertByBo(SysOssBo bo) {
|
||||
SysOss oss = BeanUtil.toBean(bo, SysOss.class);
|
||||
boolean flag = baseMapper.insert(oss) > 0;
|
||||
if (flag) {
|
||||
bo.setOssId(oss.getOssId());
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除OSS对象存储
|
||||
*
|
||||
* @param ids OSS对象ID串
|
||||
* @param isValid 判断是否需要校验
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
||||
if (isValid) {
|
||||
// 做一些业务上的校验,判断是否需要校验
|
||||
}
|
||||
List<SysOss> list = baseMapper.selectByIds(ids);
|
||||
for (SysOss sysOss : list) {
|
||||
OssClient storage = OssFactory.instance(sysOss.getService());
|
||||
storage.delete(sysOss.getUrl());
|
||||
}
|
||||
return baseMapper.deleteByIds(ids) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 桶类型为 private 的URL 修改为临时URL时长为120s
|
||||
*
|
||||
* @param oss OSS对象
|
||||
* @return oss 匹配Url的OSS对象
|
||||
*/
|
||||
private SysOssVo matchingUrl(SysOssVo oss) {
|
||||
OssClient storage = OssFactory.instance(oss.getService());
|
||||
// 仅修改桶类型为 private 的URL,临时URL时长为120s
|
||||
if (AccessPolicyType.PRIVATE == storage.getAccessPolicy()) {
|
||||
oss.setUrl(storage.getPrivateUrl(oss.getFileName(), Duration.ofSeconds(120)));
|
||||
}
|
||||
return oss;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,34 @@
|
||||
# Tomcat
|
||||
server:
|
||||
port: 9204
|
||||
|
||||
# Spring
|
||||
spring:
|
||||
application:
|
||||
# 应用名称
|
||||
name: ruoyi-resource
|
||||
profiles:
|
||||
# 环境配置
|
||||
active: @profiles.active@
|
||||
|
||||
--- # nacos 配置
|
||||
spring:
|
||||
cloud:
|
||||
nacos:
|
||||
# nacos 服务地址
|
||||
server-addr: @nacos.server@
|
||||
username: @nacos.username@
|
||||
password: @nacos.password@
|
||||
discovery:
|
||||
# 注册组
|
||||
group: @nacos.discovery.group@
|
||||
namespace: ${spring.profiles.active}
|
||||
config:
|
||||
# 配置组
|
||||
group: @nacos.config.group@
|
||||
namespace: ${spring.profiles.active}
|
||||
config:
|
||||
import:
|
||||
- optional:nacos:application-common.yml
|
||||
- optional:nacos:datasource.yml
|
||||
- optional:nacos:${spring.application.name}.yml
|
10
ruoyi-modules/ruoyi-resource/src/main/resources/banner.txt
Normal file
10
ruoyi-modules/ruoyi-resource/src/main/resources/banner.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
Spring Boot Version: ${spring-boot.version}
|
||||
Spring Application Name: ${spring.application.name}
|
||||
_
|
||||
(_)
|
||||
_ __ _ _ ___ _ _ _ ______ _ __ ___ ___ ___ _ _ _ __ ___ ___
|
||||
| '__| | | |/ _ \| | | | |______| '__/ _ \/ __|/ _ \| | | | '__/ __/ _ \
|
||||
| | | |_| | (_) | |_| | | | | | __/\__ \ (_) | |_| | | | (_| __/
|
||||
|_| \__,_|\___/ \__, |_| |_| \___||___/\___/ \__,_|_| \___\___|
|
||||
__/ |
|
||||
|___/
|
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration scan="true" scanPeriod="60 seconds" debug="false">
|
||||
<!-- 日志存放路径 -->
|
||||
<property name="log.path" value="logs/${project.artifactId}"/>
|
||||
<!-- 日志输出格式 -->
|
||||
<property name="console.log.pattern"
|
||||
value="%cyan(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{36}%n) - %msg%n"/>
|
||||
|
||||
<!-- 控制台输出 -->
|
||||
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>${console.log.pattern}</pattern>
|
||||
<charset>utf-8</charset>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<include resource="logback-common.xml" />
|
||||
|
||||
<include resource="logback-logstash.xml" />
|
||||
|
||||
<!-- 开启 skywalking 日志收集 -->
|
||||
<include resource="logback-skylog.xml" />
|
||||
|
||||
<!--系统操作日志-->
|
||||
<root level="info">
|
||||
<appender-ref ref="console"/>
|
||||
</root>
|
||||
</configuration>
|
@@ -0,0 +1,3 @@
|
||||
java包使用 `.` 分割 resource 目录使用 `/` 分割
|
||||
<br>
|
||||
此文件目的 防止文件夹粘连找不到 `xml` 文件
|
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="org.dromara.resource.mapper.SysOssConfigMapper">
|
||||
|
||||
</mapper>
|
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="org.dromara.resource.mapper.SysOssMapper">
|
||||
|
||||
</mapper>
|
Reference in New Issue
Block a user