Merge remote-tracking branch 'origin/5.X_bak' into 5.X_bak

This commit is contained in:
Github_lizhw 2025-11-30 12:08:01 +08:00
commit 61c6fb11f8
8 changed files with 336 additions and 0 deletions

View File

@ -84,6 +84,17 @@
<artifactId>dubbo-nacos-spring-boot-starter</artifactId> <artifactId>dubbo-nacos-spring-boot-starter</artifactId>
</dependency> </dependency>
<dependency>
<groupId>me.liuxp</groupId>
<artifactId>minio-plus-all-springboot-starter</artifactId>
<version>1.0.5</version>
</dependency>
<dependency>
<groupId>me.liuxp</groupId>
<artifactId>s3-api-minio</artifactId>
<version>1.0.5</version>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId> <artifactId>spring-boot-starter-test</artifactId>

View File

@ -1,7 +1,9 @@
package com.luban.api.config; package com.luban.api.config;
import com.luban.api.s3.config.S3LoginUserInterceptor;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@ -19,4 +21,14 @@ public class WebMvcConfig implements WebMvcConfigurer {
registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/"); registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/**").addResourceLocations("classpath:/META-INF/resources/").setCachePeriod(0); registry.addResourceHandler("/**").addResourceLocations("classpath:/META-INF/resources/").setCachePeriod(0);
} }
/**
* 前置拦截器
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 登录用户获取用户id
registry.addInterceptor(new S3LoginUserInterceptor()).addPathPatterns("/storage/**");
}
} }

View File

@ -0,0 +1,59 @@
package com.luban.api.s3.config;
import cn.hutool.core.text.CharSequenceUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.liuxp.minioplus.extension.context.UserHolder;
import org.springframework.lang.Nullable;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.annotation.Nonnull;
/**
* 登录用户拦截器
*
* @author contact@liuxp.me
* @since 2024/06/11
*/
@Slf4j
public class S3LoginUserInterceptor implements HandlerInterceptor {
/**
* 处理登录用户信息
*
* @param request 请求
* @param response 返回
* @param handler 要执行的处理程序
* @return 是否继续执行下一个拦截器
*/
@Override
public boolean preHandle(HttpServletRequest request, @Nonnull HttpServletResponse response, @Nonnull Object handler) {
String userId = request.getHeader("Authorization");
if (CharSequenceUtil.isBlank(userId)) {
UserHolder.set("");
} else {
//TODO 用户id还未生成
UserHolder.set(userId);
}
return true;
}
/**
* 清理资源
*
* @param request 请求
* @param response 返回
* @param handler 要执行的处理程序
* @param exception 异常信息
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception exception) {
log.debug("Project ThreadLocal 清理之前:{}", UserHolder.get());
UserHolder.clean();
log.debug("Project ThreadLocal 清理之之后:{}", UserHolder.get());
}
}

View File

@ -0,0 +1,9 @@
package com.luban.api.s3.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import com.luban.api.s3.entity.FileMetadataInfoEntity;
@Mapper
public interface FileMetadataInfoMapper extends BaseMapper<FileMetadataInfoEntity> {
}

View File

@ -0,0 +1,102 @@
package com.luban.api.s3.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import java.util.Date;
/**
* 文件元数据信息表Entity
*
* @author contact@liuxp.me
* @since 2024-05-22
**/
@Getter
@Setter
@ToString
@TableName(value = "file_metadata_info")
public class FileMetadataInfoEntity {
@TableId(value = "id", type = IdType.AUTO)
@Schema(description = "主键")
private Long id;
@Schema(description = "文件KEY")
@TableField(value = "file_key")
private String fileKey;
@Schema(description = "文件md5")
@TableField(value = "file_md5")
private String fileMd5;
@Schema(description = "文件名")
@TableField(value = "file_name")
private String fileName;
@Schema(description = "MIME类型")
@TableField(value = "file_mime_type")
private String fileMimeType;
@Schema(description = "文件后缀")
@TableField(value = "file_suffix")
private String fileSuffix;
@Schema(description = "文件长度")
@TableField(value = "file_size")
private Long fileSize;
@Schema(description = "预览图 0:无 1:有")
@TableField(value = "is_preview")
private Boolean isPreview;
@Schema(description = "是否私有 0:否 1:是")
@TableField(value = "is_private")
private Boolean isPrivate;
@Schema(description = "存储桶")
@TableField(value = "bucket")
private String storageBucket;
@Schema(description = "存储桶路径")
@TableField(value = "bucket_path")
private String storagePath;
@Schema(description = "上传任务id,用于合并切片")
@TableField(value = "upload_id")
private String uploadTaskId;
@Schema(description = "状态 0:未完成 1:已完成")
@TableField(value = "is_finished")
private Boolean isFinished;
@Schema(description = "是否分块 0:否 1:是")
@TableField(value = "is_part")
private Boolean isPart;
@Schema(description = "分块数量")
@TableField(value = "part_number")
private Integer partNumber;
@Schema(description = "创建人")
@TableField("create_user")
private String createUser;
@Schema(description = "创建时间")
@TableField("create_time")
private Date createTime;
@Schema(description = "修改人")
@TableField("update_user")
private String updateUser;
@Schema(description = "修改时间")
@TableField("update_time")
private Date updateTime;
}

View File

@ -0,0 +1,121 @@
package com.luban.api.s3.service;
import cn.hutool.core.text.CharSequenceUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.liuxp.minioplus.api.model.dto.FileMetadataInfoDTO;
import org.liuxp.minioplus.api.model.dto.FileMetadataInfoSaveDTO;
import org.liuxp.minioplus.api.model.dto.FileMetadataInfoUpdateDTO;
import org.liuxp.minioplus.api.model.vo.FileMetadataInfoVo;
import org.liuxp.minioplus.core.repository.MetadataRepository;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import com.luban.api.s3.dao.FileMetadataInfoMapper;
import com.luban.api.s3.entity.FileMetadataInfoEntity;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* 文件元数据接口实现类
*
* @author contact@liuxp.me
* @since 2024/05/22
*/
@Slf4j
@Service
public class MetadataRepositoryImpl extends ServiceImpl<FileMetadataInfoMapper, FileMetadataInfoEntity> implements MetadataRepository {
@Override
public List<FileMetadataInfoVo> list(FileMetadataInfoDTO searchDTO) {
// 组装查询参数
QueryWrapper<FileMetadataInfoEntity> queryWrapper = buildParams(searchDTO);
List<FileMetadataInfoEntity> fileMetadataInfoEntityList = super.list(queryWrapper);
List<FileMetadataInfoVo> fileMetadataInfoVoList = new ArrayList<>();
for (FileMetadataInfoEntity fileMetadataInfoEntity : fileMetadataInfoEntityList) {
FileMetadataInfoVo fileMetadataInfoVo = new FileMetadataInfoVo();
BeanUtils.copyProperties(fileMetadataInfoEntity, fileMetadataInfoVo);
fileMetadataInfoVoList.add(fileMetadataInfoVo);
}
return fileMetadataInfoVoList;
}
@Override
public FileMetadataInfoVo one(FileMetadataInfoDTO searchDTO) {
// 组装查询参数
QueryWrapper<FileMetadataInfoEntity> queryWrapper = buildParams(searchDTO);
queryWrapper.last("limit 1");
FileMetadataInfoEntity fileMetadataInfoEntity = super.getOne(queryWrapper);
FileMetadataInfoVo fileMetadataInfoVo = null;
if (null != fileMetadataInfoEntity) {
fileMetadataInfoVo = new FileMetadataInfoVo();
BeanUtils.copyProperties(fileMetadataInfoEntity, fileMetadataInfoVo);
}
return fileMetadataInfoVo;
}
@Override
public FileMetadataInfoVo save(FileMetadataInfoSaveDTO saveDTO) {
FileMetadataInfoEntity fileMetadataInfoEntity = new FileMetadataInfoEntity();
BeanUtils.copyProperties(saveDTO, fileMetadataInfoEntity);
fileMetadataInfoEntity.setCreateTime(new Date());
fileMetadataInfoEntity.setUpdateTime(new Date());
boolean result = super.save(fileMetadataInfoEntity);
FileMetadataInfoVo fileMetadataInfoVo = new FileMetadataInfoVo();
if (result) {
BeanUtils.copyProperties(fileMetadataInfoEntity, fileMetadataInfoVo);
}
return fileMetadataInfoVo;
}
@Override
public FileMetadataInfoVo update(FileMetadataInfoUpdateDTO updateDTO) {
FileMetadataInfoEntity fileMetadataInfoEntity = new FileMetadataInfoEntity();
BeanUtils.copyProperties(updateDTO, fileMetadataInfoEntity);
fileMetadataInfoEntity.setUpdateTime(new Date());
boolean result = super.updateById(fileMetadataInfoEntity);
FileMetadataInfoVo fileMetadataInfoVo = new FileMetadataInfoVo();
if (result) {
BeanUtils.copyProperties(fileMetadataInfoEntity, fileMetadataInfoVo);
}
return fileMetadataInfoVo;
}
@Override
public Boolean remove(Long id) {
return super.removeById(id);
}
private QueryWrapper<FileMetadataInfoEntity> buildParams(FileMetadataInfoDTO searchDTO) {
// 组装查询参数
QueryWrapper<FileMetadataInfoEntity> queryWrapper = new QueryWrapper<>();
queryWrapper.eq(CharSequenceUtil.isNotBlank(searchDTO.getFileKey()), "file_key", searchDTO.getFileKey());
queryWrapper.eq(CharSequenceUtil.isNotBlank(searchDTO.getFileMd5()), "file_md5", searchDTO.getFileMd5());
queryWrapper.eq(CharSequenceUtil.isNotBlank(searchDTO.getBucket()), "bucket", searchDTO.getBucket());
queryWrapper.eq(null != searchDTO.getIsPrivate(), "is_private", searchDTO.getIsPrivate());
queryWrapper.eq(CharSequenceUtil.isNotBlank(searchDTO.getCreateUser()), "create_user", searchDTO.getCreateUser());
return queryWrapper;
}
}

View File

@ -73,3 +73,10 @@ mybatis-plus:
# AUTO 自增 NONE 空 INPUT 用户输入 ASSIGN_ID 雪花 ASSIGN_UUID 唯一 UUID # AUTO 自增 NONE 空 INPUT 用户输入 ASSIGN_ID 雪花 ASSIGN_UUID 唯一 UUID
# 如需改为自增 需要将数据库表全部设置为自增 # 如需改为自增 需要将数据库表全部设置为自增
idType: ASSIGN_ID idType: ASSIGN_ID
minioplus:
# rustfs 部署地址
backend: http://localhost:9000
# 授权key
key: rustfsadmin
# 密钥
secret: rustfsadmin

View File

@ -7,3 +7,18 @@ services:
- /d/Program Files/docker/path/mall-swarm/mongo/db:/data/db #数据文件挂载 - /d/Program Files/docker/path/mall-swarm/mongo/db:/data/db #数据文件挂载
ports: ports:
- 27017:27017 - 27017:27017
rustfs:
image: registry.cn-shanghai.aliyuncs.com/study-03/rustfs:latest
container_name: rustfs
ports:
- "19000:9000" # 管理控制台
- "9090:9090" # API服务端口
volumes:
- rustfs_data_volume:/data
environment:
- RUSTFS_ROOT_USER=admin
- RUSTFS_ROOT_PASSWORD=admin123
restart: unless-stopped
volumes:
rustfs_data_volume: