mirror of
https://github.com/abcv7/sfbx-cloud.git
synced 2026-08-16 11:47:00 +00:00
功能:在保险、规则、交易、积分和短信模块中实现初始功能和基础组件。
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.itheima.sfbx</groupId>
|
||||
<artifactId>sfbx-file</artifactId>
|
||||
<version>2.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<!--文件处理接口模块-->
|
||||
<artifactId>file-interface</artifactId>
|
||||
<name>file-interface</name>
|
||||
<!-- FIXME change it to the project's website -->
|
||||
<url>http://www.example.com</url>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.itheima.sfbx</groupId>
|
||||
<artifactId>framework-feign</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package com.itheima.sfbx.file.config;
|
||||
|
||||
import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* @ClassName DictFenginConfig.java
|
||||
* @Description feign的最优化配置
|
||||
*/
|
||||
@EnableFeignClients(basePackages = "com.itheima.sfbx.file.feign")
|
||||
@Configuration
|
||||
public class FileFeignConfig {
|
||||
}
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
package com.itheima.sfbx.file.feign;
|
||||
|
||||
import com.itheima.sfbx.file.hystrix.FileBusinessHystrix;
|
||||
import com.itheima.sfbx.framework.commons.dto.file.FileVO;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @ClassName FileFeign.java
|
||||
* @Description 附件feign接口
|
||||
*/
|
||||
@FeignClient(value = "file-web",fallback = FileBusinessHystrix.class)
|
||||
public interface FileBusinessFeign {
|
||||
|
||||
/**
|
||||
* @Description 业务与文件绑定
|
||||
* @param fileVO 附件对象
|
||||
* @return com.itheima.travel.req.FileVO
|
||||
*/
|
||||
@PostMapping("file-feign/bind-file")
|
||||
List<FileVO> bindFile(@RequestBody FileVO fileVO);
|
||||
|
||||
/**
|
||||
* @Description 业务绑定多个附件
|
||||
* @param fileVOs 相同业务的多个附件对象
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("file-feign/bind-batch-file")
|
||||
List<FileVO> bindBatchFile(@RequestBody ArrayList<FileVO> fileVOs);
|
||||
|
||||
/**
|
||||
* @Description 移除业务原附件,并绑定新的附件到业务上
|
||||
* @param fileVO 附件对象
|
||||
* @return
|
||||
*/
|
||||
@PostMapping(value = "file-feign/replace-bind-file")
|
||||
Boolean replaceBindFile(@RequestBody FileVO fileVO);
|
||||
|
||||
/**
|
||||
* @Description 移除业务原附件,并批量绑定新的附件到业务上
|
||||
* @param fileVOs 附件对象
|
||||
* @return
|
||||
*/
|
||||
@PostMapping(value = "file-feign/replace-bind-batch-file")
|
||||
Boolean replaceBindBatchFile(@RequestBody ArrayList<FileVO> fileVOs);
|
||||
|
||||
|
||||
/**
|
||||
* @Description 按业务ID查询附件【对象传递参数方式】
|
||||
* @param businessIds 业务IDS
|
||||
* @return List<FileVO>
|
||||
*/
|
||||
@PostMapping("file-feign/find-in-business-ids")
|
||||
List<FileVO> findInBusinessIds(@RequestBody List<Long> businessIds);
|
||||
|
||||
|
||||
/**
|
||||
* @Description 删除业务相关附件
|
||||
* @param businessIds 业务IDS
|
||||
* @return Boolean
|
||||
*/
|
||||
@DeleteMapping("file-feign/delete-by-business-ids")
|
||||
Boolean deleteByBusinessIds(@RequestBody ArrayList<Long> businessIds);
|
||||
|
||||
/**
|
||||
* @Description 定时清理文件
|
||||
* @return
|
||||
*/
|
||||
@DeleteMapping("file-feign/clear-file")
|
||||
Boolean clearFile();
|
||||
|
||||
/**
|
||||
* @Description 延迟队列清理文件
|
||||
* @return
|
||||
*/
|
||||
@DeleteMapping("file-feign/clear-file-id/{id}")
|
||||
Boolean clearFileById(@PathVariable("id") Long id);
|
||||
|
||||
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
package com.itheima.sfbx.file.feign;
|
||||
|
||||
import com.itheima.sfbx.file.hystrix.FileBusinessHystrix;
|
||||
import com.itheima.sfbx.framework.commons.dto.file.FileVO;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
|
||||
/**
|
||||
* @ClassName FileFeign.java
|
||||
* @Description 文件下载feign接口
|
||||
*/
|
||||
@FeignClient(value = "file-web",fallback = FileBusinessHystrix.class)
|
||||
public interface FileDownLoadFeign {
|
||||
|
||||
/***
|
||||
* @description 文件下载-服务远程调用-base64方式返回
|
||||
* @param fileId 上传对象
|
||||
* @return: com.itheima.travel.req.FileVo
|
||||
*/
|
||||
@PostMapping("file-feign/down-load/{fileId}")
|
||||
FileVO downLoad(@PathVariable("fileId") Long fileId);
|
||||
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
package com.itheima.sfbx.file.hystrix;
|
||||
|
||||
import com.itheima.sfbx.framework.commons.dto.file.FileVO;
|
||||
import com.itheima.sfbx.file.feign.FileBusinessFeign;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @ClassName FileHystrix.java
|
||||
* @Description FileFeign的Hystrix
|
||||
*/
|
||||
@Component
|
||||
public class FileBusinessHystrix implements FileBusinessFeign {
|
||||
|
||||
|
||||
@Override
|
||||
public List<FileVO> bindFile(FileVO fileVO) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FileVO> bindBatchFile(ArrayList<FileVO> fileVOs) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean replaceBindFile(FileVO fileVO) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean replaceBindBatchFile(ArrayList<FileVO> fileVOs) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FileVO> findInBusinessIds(List<Long> businessIds) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean deleteByBusinessIds(ArrayList<Long> businessIds) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean clearFile() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean clearFileById(Long id) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
package com.itheima.sfbx.file.hystrix;
|
||||
|
||||
import com.itheima.sfbx.file.feign.FileDownLoadFeign;
|
||||
import com.itheima.sfbx.framework.commons.dto.file.FileVO;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @ClassName FileHystrix.java
|
||||
* @Description FileFeign的Hystrix
|
||||
*/
|
||||
@Component
|
||||
public class FileDownLoadHystrix implements FileDownLoadFeign {
|
||||
|
||||
|
||||
@Override
|
||||
public FileVO downLoad(Long fileId) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
FROM openjdk:11-jdk
|
||||
LABEL maintainer="研究院研发组 <research@itcast.cn>"
|
||||
|
||||
# 时区修改为东八区
|
||||
ENV TZ=Asia/Shanghai
|
||||
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
|
||||
|
||||
WORKDIR /file-web
|
||||
ARG PACKAGE_PATH=./target/file-web.jar
|
||||
ADD ${PACKAGE_PATH:-./} file-web.jar
|
||||
|
||||
EXPOSE 8080
|
||||
|
||||
ENV JAVA_OPTS="\
|
||||
-server \
|
||||
-Xms256m \
|
||||
-Xmx512m \
|
||||
-XX:MetaspaceSize=256m \
|
||||
-XX:MaxMetaspaceSize=512m\
|
||||
-Dspring.profiles.active=test"
|
||||
ENTRYPOINT ["sh","-c","java -Djava.security.egd=file:/dev/./urandom -jar $JAVA_OPTS file-web.jar"]
|
||||
@@ -0,0 +1,105 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.itheima.sfbx</groupId>
|
||||
<artifactId>sfbx-file</artifactId>
|
||||
<version>2.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<!--文件处理web模块-->
|
||||
<artifactId>file-web</artifactId>
|
||||
<name>file-web</name>
|
||||
<!-- FIXME change it to the project's website -->
|
||||
<url>http://www.example.com</url>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-bootstrap</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alicloud-oss</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.aliyun.oss</groupId>
|
||||
<artifactId>aliyun-sdk-oss</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.itheima.sfbx</groupId>
|
||||
<artifactId>framework-rabbitmq</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.itheima.sfbx</groupId>
|
||||
<artifactId>framework-seata</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.itheima.sfbx</groupId>
|
||||
<artifactId>framework-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.itheima.sfbx</groupId>
|
||||
<artifactId>framework-mybatis-plus</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.itheima.sfbx</groupId>
|
||||
<artifactId>framework-redis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.itheima.sfbx</groupId>
|
||||
<artifactId>framework-knife4j-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.qiniu</groupId>
|
||||
<artifactId>qiniu-java-sdk</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.xml.bind</groupId>
|
||||
<artifactId>jaxb-api</artifactId>
|
||||
<version>2.3.1</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<includes>
|
||||
<include>**/*.yml</include>
|
||||
<include>**/*.properties</include>
|
||||
<include>**/*.xml</include>
|
||||
<include>**/*.yaml</include>
|
||||
<include>**/*.txt</include>
|
||||
</includes>
|
||||
</resource>
|
||||
</resources>
|
||||
<finalName>file-web</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>repackage</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.itheima.sfbx.file;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
/**
|
||||
* 文件上传处理微服务
|
||||
*/
|
||||
@SpringBootApplication(scanBasePackages = "com.itheima.sfbx")
|
||||
public class FileWebStart {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(FileWebStart.class, args);
|
||||
}
|
||||
}
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
package com.itheima.sfbx.file.adapter;
|
||||
|
||||
import com.itheima.sfbx.file.pojo.File;
|
||||
import com.itheima.sfbx.framework.commons.dto.file.FilePartVO;
|
||||
import com.itheima.sfbx.framework.commons.dto.file.FileVO;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @ClassName FileStorageAdapter.java
|
||||
* @Description 文件存储适配处理
|
||||
*/
|
||||
public interface FileStorageAdapter {
|
||||
|
||||
/**
|
||||
* 文件上传
|
||||
* @param fileVO {@link FileVO} 文件信息对象
|
||||
* @param inputStream 文件流
|
||||
* @return pathUrl 全路径
|
||||
*/
|
||||
String uploadFile(FileVO fileVO, InputStream inputStream);
|
||||
|
||||
/***
|
||||
* @description 分片上传-初始化分片请求
|
||||
* @param fileVO {@link FileVO} 文件信息对象
|
||||
* @return uploadId 文件上传id
|
||||
*/
|
||||
File initiateMultipartUpload(FileVO fileVO);
|
||||
|
||||
/***
|
||||
* @description 分片上传-上传每个分片文件
|
||||
* @param filePartVo {@link FilePartVO} 文件信息对象
|
||||
* @param inputStream 当前分片文件流
|
||||
* @return PartETag json字符串
|
||||
*/
|
||||
String uploadPart(FilePartVO filePartVo, InputStream inputStream);
|
||||
|
||||
|
||||
/***
|
||||
* @description 分片上传-合并所有上传文件
|
||||
* @param fileVO {@link File} 文件信息对象
|
||||
* @return 合并结果
|
||||
*/
|
||||
String completeMultipartUpload(FileVO fileVO);
|
||||
|
||||
/**
|
||||
* @Description 下载文件
|
||||
* @param storeFlag 存储源标识
|
||||
* @param bucketName 资源存储区域名称
|
||||
* @param pathUrl 资源文件路径地址(其中包含文件名称)
|
||||
* @return
|
||||
*/
|
||||
InputStream downloadFile(String storeFlag,String bucketName,String pathUrl) throws IOException;
|
||||
|
||||
/**
|
||||
* @Description 文件删除
|
||||
* @param pathUrl 全路径
|
||||
* @throws Exception
|
||||
*/
|
||||
void delete(String storeFlag,String bucketName,String pathUrl);
|
||||
|
||||
|
||||
/**
|
||||
* @Description 批量文件删除
|
||||
* @param pathUrls 全路径集合
|
||||
* @throws Exception
|
||||
*/
|
||||
void deleteBatch(String storeFlag,String bucketName,List<String> pathUrls);
|
||||
|
||||
/**
|
||||
* @Description 获取文件文本内容
|
||||
* @param pathUrl 全路径
|
||||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
String getFileContent(String storeFlag,String bucketName,String pathUrl) throws IOException;
|
||||
}
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
package com.itheima.sfbx.file.adapter.impl;
|
||||
|
||||
import com.itheima.sfbx.file.adapter.FileStorageAdapter;
|
||||
import com.itheima.sfbx.file.handler.FileStorageHandler;
|
||||
import com.itheima.sfbx.framework.commons.constant.file.FileConstant;
|
||||
import com.itheima.sfbx.framework.commons.dto.file.FileVO;
|
||||
import com.itheima.sfbx.framework.commons.dto.file.FilePartVO;
|
||||
import com.itheima.sfbx.framework.commons.utils.EmptyUtil;
|
||||
import com.itheima.sfbx.framework.commons.utils.RegisterBeanHandler;
|
||||
import com.itheima.sfbx.file.pojo.File;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @ClassName FileStorageAdapterImpl.java
|
||||
* @Description 文件存储适配处理
|
||||
*/
|
||||
@Component
|
||||
public class FileStorageAdapterImpl implements FileStorageAdapter {
|
||||
|
||||
@Autowired
|
||||
RegisterBeanHandler registerBeanHandler;
|
||||
|
||||
private static Map<String,String> fileStorageHandlers =new HashMap<>();
|
||||
|
||||
static {
|
||||
fileStorageHandlers.put(FileConstant.ALIYUN_OSS,"ossFileStorageHandler");
|
||||
fileStorageHandlers.put(FileConstant.QINIU_KODO,"kodoFileStorageHandler");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String uploadFile(FileVO fileVO, InputStream inputStream) {
|
||||
String fileStorageHandlerString = EmptyUtil.isNullOrEmpty(fileVO.getStoreFlag())?
|
||||
fileStorageHandlers.get(FileConstant.ALIYUN_OSS):fileStorageHandlers.get(fileVO.getStoreFlag());
|
||||
FileStorageHandler fileStorageHandler = registerBeanHandler.getBean(fileStorageHandlerString, FileStorageHandler.class);
|
||||
return fileStorageHandler.uploadFile(fileVO.getSuffix(), fileVO.getFileName(), fileVO.getBucketName(), fileVO.getAutoCatalog(), inputStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public File initiateMultipartUpload(FileVO fileVO) {
|
||||
String fileStorageHandlerString = EmptyUtil.isNullOrEmpty(fileVO.getStoreFlag())?
|
||||
fileStorageHandlers.get(FileConstant.ALIYUN_OSS):fileStorageHandlers.get(fileVO.getStoreFlag());
|
||||
FileStorageHandler fileStorageHandler = registerBeanHandler.getBean(fileStorageHandlerString, FileStorageHandler.class);
|
||||
return fileStorageHandler.initiateMultipartUpload(fileVO.getSuffix(),fileVO.getFileName(),fileVO.getBucketName(),fileVO.getAutoCatalog());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String uploadPart(FilePartVO filePartVo, InputStream inputStream) {
|
||||
String fileStorageHandlerString = EmptyUtil.isNullOrEmpty(filePartVo.getStoreFlag())?
|
||||
fileStorageHandlers.get(FileConstant.ALIYUN_OSS):fileStorageHandlers.get(filePartVo.getStoreFlag());
|
||||
FileStorageHandler fileStorageHandler = registerBeanHandler.getBean(fileStorageHandlerString, FileStorageHandler.class);
|
||||
return fileStorageHandler.uploadPart(filePartVo.getUploadId(),filePartVo.getFileName(),filePartVo.getPartNumber(),filePartVo.getPartSize(),filePartVo.getBucketName(),inputStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String completeMultipartUpload(FileVO fileVO) {
|
||||
String fileStorageHandlerString = EmptyUtil.isNullOrEmpty(fileVO.getStoreFlag())?
|
||||
fileStorageHandlers.get(FileConstant.ALIYUN_OSS):fileStorageHandlers.get(fileVO.getStoreFlag());
|
||||
FileStorageHandler fileStorageHandler = registerBeanHandler.getBean(fileStorageHandlerString, FileStorageHandler.class);
|
||||
return fileStorageHandler.completeMultipartUpload(fileVO.getUploadId(),fileVO.getPartETags(),fileVO.getFileName(),fileVO.getBucketName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream downloadFile(String storeFlag,String bucketName,String pathUrl) throws IOException {
|
||||
String fileStorageHandlerString = EmptyUtil.isNullOrEmpty(storeFlag)?
|
||||
fileStorageHandlers.get(FileConstant.ALIYUN_OSS):fileStorageHandlers.get(storeFlag);
|
||||
FileStorageHandler fileStorageHandler = registerBeanHandler.getBean(fileStorageHandlerString, FileStorageHandler.class);
|
||||
return fileStorageHandler.downloadFile(bucketName,pathUrl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(String storeFlag,String bucketName,String pathUrl) {
|
||||
String fileStorageHandlerString = EmptyUtil.isNullOrEmpty(storeFlag)?
|
||||
fileStorageHandlers.get(FileConstant.ALIYUN_OSS):fileStorageHandlers.get(storeFlag);
|
||||
FileStorageHandler fileStorageHandler = registerBeanHandler.getBean(fileStorageHandlerString, FileStorageHandler.class);
|
||||
fileStorageHandler.delete(bucketName,pathUrl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteBatch(String storeFlag,String bucketName,List<String> pathUrls) {
|
||||
String fileStorageHandlerString = EmptyUtil.isNullOrEmpty(storeFlag)?
|
||||
fileStorageHandlers.get(FileConstant.ALIYUN_OSS):fileStorageHandlers.get(storeFlag);
|
||||
FileStorageHandler fileStorageHandler = registerBeanHandler.getBean(fileStorageHandlerString, FileStorageHandler.class);
|
||||
fileStorageHandler.deleteBatch(bucketName,pathUrls);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFileContent(String storeFlag,String bucketName,String pathUrl) throws IOException {
|
||||
String fileStorageHandlerString = EmptyUtil.isNullOrEmpty(storeFlag)?
|
||||
fileStorageHandlers.get(FileConstant.ALIYUN_OSS):fileStorageHandlers.get(storeFlag);
|
||||
FileStorageHandler fileStorageHandler = registerBeanHandler.getBean(fileStorageHandlerString, FileStorageHandler.class);
|
||||
return fileStorageHandler.getFileContent(bucketName,pathUrl);
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package com.itheima.sfbx.file.binding;
|
||||
|
||||
import com.itheima.sfbx.framework.rabbitmq.source.FileSource;
|
||||
import org.springframework.cloud.stream.annotation.EnableBinding;
|
||||
|
||||
/**
|
||||
* @ClassName Binding.java
|
||||
* @Description 绑定文件发送者声明
|
||||
*/
|
||||
@EnableBinding({FileSource.class})
|
||||
public class SourceBinding {
|
||||
}
|
||||
+123
@@ -0,0 +1,123 @@
|
||||
package com.itheima.sfbx.file.fegin;
|
||||
|
||||
import com.itheima.sfbx.file.service.IFileService;
|
||||
import com.itheima.sfbx.framework.commons.dto.file.FileVO;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @ClassName FileController.java
|
||||
* @Description 附件展示维护controller
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("file-feign")
|
||||
@Api(tags = "附件feign-controller")
|
||||
@Slf4j
|
||||
public class FileBusinessFeignController {
|
||||
|
||||
@Autowired
|
||||
IFileService fileService;
|
||||
|
||||
/**
|
||||
* @Description 业务绑定单个附件
|
||||
* @param fileVO 附件对象
|
||||
* @return
|
||||
*/
|
||||
@PostMapping(value = "bind-file")
|
||||
@ApiOperation(value = "业务绑定单文件",notes = "业务绑定单文件")
|
||||
@ApiImplicitParam(name = "fileVO",value = "附件对象",required = true,dataType = "FileVO")
|
||||
public FileVO bindFile(@RequestBody FileVO fileVO){
|
||||
return fileService.bindFile(fileVO);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Description 相同业务绑定多个附件
|
||||
* @param fileVOs 相同业务的多个附件对象
|
||||
* @return
|
||||
*/
|
||||
@PostMapping(value = "bind-batch-file")
|
||||
@ApiOperation(value = "业务绑定多文件",notes = "业务绑定多文件")
|
||||
@ApiImplicitParam(name = "fileVOs",value = "附件对象",required = true,dataType = "FileVO")
|
||||
public List<FileVO> bindBatchFile(@RequestBody ArrayList<FileVO> fileVOs){
|
||||
return fileService.bindBatchFile(fileVOs);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Description 移除业务原图片,并绑定新的图片到业务上
|
||||
* @param fileVO 附件对象
|
||||
* @return
|
||||
*/
|
||||
@PostMapping(value = "replace-bind-file")
|
||||
@ApiOperation(value = "移除业务原图片,并绑定新的图片到业务上",notes = "移除业务原图片,并绑定新的图片到业务上")
|
||||
@ApiImplicitParam(name = "fileVO",value = "附件对象",required = true,dataType = "FileVO")
|
||||
public Boolean replaceBindFile(@RequestBody FileVO fileVO){
|
||||
return fileService.replaceBindFile(fileVO);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Description 批量移除业务原图片,并批量绑定新的图片到业务上
|
||||
* @param fileVOs 附件对象
|
||||
* @return
|
||||
*/
|
||||
@PostMapping(value = "replace-bind-batch-file")
|
||||
@ApiOperation(value = "移除业务原图片,并绑定新的图片到业务上",notes = "移除业务原图片,并绑定新的图片到业务上")
|
||||
@ApiImplicitParam(name = "fileVOs",value = "附件对象",required = true,dataType = "FileVO")
|
||||
public Boolean replaceBindBatchFile(@RequestBody ArrayList<FileVO> fileVOs){
|
||||
return fileService.replaceBindBatchFile(fileVOs);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 按业务ID查询附件
|
||||
* @param businessIds 业务ids
|
||||
* @return java.util.List<com.itheima.travel.req.FileVO>
|
||||
*/
|
||||
@PostMapping("find-in-business-ids")
|
||||
@ApiOperation(value = "查询业务对应附件",notes = "查询业务对应附件")
|
||||
@ApiImplicitParam(name = "fileVO",value = "附件对象",required = true,dataType = "FileVO")
|
||||
public List<FileVO> findInBusinessIds(@RequestBody ArrayList<Long> businessIds) {
|
||||
return fileService.findInBusinessIds(businessIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Description 删除业务相关附件
|
||||
* @param businessIds 附件信息ids
|
||||
* @return
|
||||
*/
|
||||
@DeleteMapping("delete-by-business-ids")
|
||||
@ApiOperation(value = "删除业务对应附件",notes = "删除业务对应附件")
|
||||
@ApiImplicitParam(name = "fileVO",value = "附件对象",required = true,dataType = "FileVO")
|
||||
public Boolean deleteByBusinessIds(@RequestBody ArrayList<Long> businessIds) {
|
||||
return fileService.deleteInBusinessIds(businessIds);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @Description 定时清理文件
|
||||
* @return Boolean
|
||||
*/
|
||||
@DeleteMapping("clear-file")
|
||||
@ApiOperation(value = "删除业务对应附件",notes = "删除业务对应附件")
|
||||
public Boolean clearFile(){
|
||||
return fileService.clearFile();
|
||||
}
|
||||
|
||||
/**
|
||||
* @Description 延迟清理文件
|
||||
* @return Boolean
|
||||
*/
|
||||
@DeleteMapping("clear-file-id/{id}")
|
||||
@ApiOperation(value = "删除业务对应附件",notes = "删除业务对应附件")
|
||||
@ApiImplicitParam(name = "id",value = "业务id",required = true,dataType = "String")
|
||||
public Boolean clearFileById(@PathVariable("id")String id){
|
||||
return fileService.clearFileById(id);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
package com.itheima.sfbx.file.fegin;
|
||||
|
||||
import com.itheima.sfbx.file.service.IFileService;
|
||||
import com.itheima.sfbx.framework.commons.dto.file.FileVO;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* @ClassName FileUpLoadController.java
|
||||
* @Description 文件下载接口
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("file-feign")
|
||||
@Api(tags = "附件controller")
|
||||
@Slf4j
|
||||
public class FileDownLoadFeignController {
|
||||
|
||||
@Autowired
|
||||
IFileService fileService;
|
||||
|
||||
/***
|
||||
* @description 文件下载-简单下载-图片base64Image方式展示
|
||||
* @param fileId 上传对象
|
||||
* @return: com.itheima.travel.req.FileVo
|
||||
*/
|
||||
@PostMapping(value = "down-load/{fileId}")
|
||||
@ApiOperation(value = "文件下载",notes = "文件下载")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(paramType = "path", name = "fileId",value = "附件Id",dataType = "Long")
|
||||
})
|
||||
public FileVO downLoad(@PathVariable("fileId") Long fileId){
|
||||
FileVO fileVO = fileService.downLoad(fileId);
|
||||
return fileVO;
|
||||
}
|
||||
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
package com.itheima.sfbx.file.handler;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @ClassName AbsFileStorageHandler.java
|
||||
* @Description 文件存储处理抽象类
|
||||
*/
|
||||
public abstract class AbsFileStorageHandler {
|
||||
|
||||
public static Map<String,String> metaMimeTypeMap = new HashMap<>();
|
||||
|
||||
static {
|
||||
metaMimeTypeMap.put(".docx","application/vnd.openxmlformats-officedocument.wordprocessingml.document");
|
||||
metaMimeTypeMap.put(".doc","application/msword");
|
||||
metaMimeTypeMap.put(".ppt","application/x-ppt");
|
||||
metaMimeTypeMap.put(".xls","application/vnd.ms-excel");
|
||||
metaMimeTypeMap.put(".xhtml","text/html");
|
||||
metaMimeTypeMap.put(".htm","text/html");
|
||||
metaMimeTypeMap.put(".html","text/html");
|
||||
metaMimeTypeMap.put(".jpe","image/jpg");
|
||||
metaMimeTypeMap.put(".jpeg","image/jpg");
|
||||
metaMimeTypeMap.put(".jpg","image/jpg");
|
||||
metaMimeTypeMap.put(".png","image/jpg");
|
||||
metaMimeTypeMap.put(".mp4","video/mp4");
|
||||
metaMimeTypeMap.put(".wmv","video/x-ms-wmv");
|
||||
metaMimeTypeMap.put(".pdf","application/pdf");
|
||||
metaMimeTypeMap.put(".mp3","audio/mp3");
|
||||
}
|
||||
|
||||
/***
|
||||
* @description 文件路径生成策略
|
||||
*
|
||||
* @param filename
|
||||
* @return
|
||||
* @return: java.lang.String
|
||||
*/
|
||||
public String builderOssPath(String filename) {
|
||||
String separator = "/";
|
||||
StringBuilder stringBuilder = new StringBuilder(50);
|
||||
LocalDate localDate = LocalDate.now();
|
||||
String yeat = String.valueOf(localDate.getYear());
|
||||
stringBuilder.append(yeat).append(separator);
|
||||
String moth = String.valueOf(localDate.getMonthValue());
|
||||
stringBuilder.append(moth).append(separator);
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE;
|
||||
String day = formatter.format(localDate);
|
||||
stringBuilder.append(day).append(separator);
|
||||
stringBuilder.append(filename);
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
}
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
package com.itheima.sfbx.file.handler;
|
||||
|
||||
import com.itheima.sfbx.file.pojo.File;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @ClassName FileStorageHandler.java
|
||||
* @Description 文件存储处理接口类
|
||||
*/
|
||||
public interface FileStorageHandler {
|
||||
|
||||
/**
|
||||
* @Description 文件上传
|
||||
* @param suffix 文件后缀
|
||||
* @param filename 文件名称-可以指定存储空间下的目录,例如:a/b/c/filename
|
||||
* @param bucketName 存储空间的名称
|
||||
* @param autoCatalog 是否自动生成文件存储目录,如果在filename指定了目录,此值设置为false
|
||||
* @param inputStream 文件流
|
||||
* @return pathUrl 全路径
|
||||
*/
|
||||
String uploadFile(String suffix, String filename,String bucketName,boolean autoCatalog, InputStream inputStream);
|
||||
|
||||
/***
|
||||
* @description 分片上传-初始化分片请求
|
||||
* @param suffix 文件后缀
|
||||
* @param filename 文件名称-可以指定存储空间下的目录,例如:a/b/c/filename
|
||||
* @param bucketName 存储空间的名称
|
||||
* @param autoCatalog 是否自动生成文件存储目录,如果在filename指定了目录,此值设置为false
|
||||
* @return uploadId 文件上传id
|
||||
*/
|
||||
File initiateMultipartUpload(String suffix, String filename, String bucketName, boolean autoCatalog);
|
||||
|
||||
/***
|
||||
* @description 分片上传-上传每个分片文件
|
||||
* @param upLoadId 文件上传id
|
||||
* @param filename 文件名称-可以指定存储空间下的目录,例如:a/b/c/filename
|
||||
* @param partNumber 当前分片
|
||||
* @param partSize 分片数
|
||||
* @param bucketName 存储空间的名称
|
||||
* @param inputStream 当前分片文件流
|
||||
* @return PartETag json字符串
|
||||
*/
|
||||
String uploadPart(String upLoadId,String filename,int partNumber,long partSize,String bucketName,InputStream inputStream);
|
||||
|
||||
|
||||
/***
|
||||
* @description 分片上传-合并所有上传文件
|
||||
*
|
||||
* @param upLoadId 文件上传id
|
||||
* @param partETags json字符串
|
||||
* @param filename 文件名称-可以指定存储空间下的目录,例如:a/b/c/filename
|
||||
* @param bucketName 存储空间的名称
|
||||
* @return 合并结果
|
||||
*/
|
||||
String completeMultipartUpload(String upLoadId,List<String> partETags,String filename,String bucketName);
|
||||
|
||||
/**
|
||||
* @Description 下载文件
|
||||
* @param bucketName 存储空间名称
|
||||
* @param pathUrl 全路径
|
||||
* @return
|
||||
*/
|
||||
InputStream downloadFile(String bucketName,String pathUrl) throws IOException;
|
||||
|
||||
/**
|
||||
* @Description 文件删除
|
||||
* @param bucketName 存储空间名称
|
||||
* @param pathUrl 全路径
|
||||
* @throws Exception
|
||||
*/
|
||||
void delete(String bucketName,String pathUrl);
|
||||
|
||||
/**
|
||||
* @Description 批量文件删除
|
||||
* @param bucketName 存储空间名称
|
||||
* @param pathUrls 全路径集合
|
||||
* @throws Exception
|
||||
*/
|
||||
void deleteBatch(String bucketName,List<String> pathUrls);
|
||||
|
||||
/**
|
||||
* @Description 获取文件文本内容
|
||||
* @param bucketName 存储空间名称
|
||||
* @param pathUrl 全路径
|
||||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
String getFileContent(String bucketName,String pathUrl) throws IOException;
|
||||
|
||||
}
|
||||
+179
@@ -0,0 +1,179 @@
|
||||
package com.itheima.sfbx.file.handler.aliyun.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.aliyun.oss.ClientException;
|
||||
import com.aliyun.oss.OSS;
|
||||
import com.aliyun.oss.OSSException;
|
||||
import com.aliyun.oss.internal.OSSConstants;
|
||||
import com.aliyun.oss.internal.OSSHeaders;
|
||||
import com.aliyun.oss.model.*;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.io.ByteStreams;
|
||||
import com.itheima.sfbx.framework.commons.enums.file.FileEnum;
|
||||
import com.itheima.sfbx.framework.commons.exception.ProjectException;
|
||||
import com.itheima.sfbx.file.handler.AbsFileStorageHandler;
|
||||
import com.itheima.sfbx.file.handler.FileStorageHandler;
|
||||
import com.itheima.sfbx.file.handler.aliyun.properties.OssAliyunConfigProperties;
|
||||
import com.itheima.sfbx.file.pojo.File;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StopWatch;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @ClassName OssFileStorageHandlerImpl.java
|
||||
* @Description 阿里云文件上传
|
||||
*/
|
||||
@Slf4j
|
||||
@Service("ossFileStorageHandler")
|
||||
@EnableConfigurationProperties(OssAliyunConfigProperties.class)
|
||||
public class OssFileStorageHandlerImpl extends AbsFileStorageHandler implements FileStorageHandler {
|
||||
|
||||
@Autowired
|
||||
OSS ossClient;
|
||||
|
||||
@Autowired
|
||||
OssAliyunConfigProperties ossAliyunConfigProperties;
|
||||
/***
|
||||
* @description 文件元数据处理
|
||||
* @param prefix 文件后缀
|
||||
* @return
|
||||
*/
|
||||
public ObjectMetadata fileMetaHandler(String prefix){
|
||||
//元数据对象
|
||||
ObjectMetadata objectMeta = new ObjectMetadata();
|
||||
//文件字符集
|
||||
objectMeta.setContentEncoding("UTF-8");
|
||||
//文件类型匹配
|
||||
objectMeta.setContentType(metaMimeTypeMap.get(prefix.toLowerCase()));
|
||||
return objectMeta;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String uploadFile(String suffix, String filename, String bucketName,boolean autoCatalog, InputStream inputStream) {
|
||||
// 是否自动生成存储路径并设置文件路径和名称(Key)
|
||||
String key = autoCatalog?builderOssPath(filename):filename;
|
||||
log.info("OSS文件上传开始:{}" ,key);
|
||||
try {
|
||||
//上传文件元数据处理
|
||||
ObjectMetadata objectMeta = fileMetaHandler(suffix);
|
||||
//文件上传请求对象
|
||||
PutObjectRequest request = new PutObjectRequest(bucketName, key, inputStream,objectMeta);
|
||||
//上传限流
|
||||
if (ossAliyunConfigProperties.getIslimitSpeed()){
|
||||
request.setTrafficLimit(ossAliyunConfigProperties.getUplimitSpeed());
|
||||
}
|
||||
//文件上传
|
||||
PutObjectResult result = ossClient.putObject(request);
|
||||
// 设置权限(公开读)
|
||||
ossClient.setBucketAcl(bucketName, CannedAccessControlList.PublicRead);
|
||||
} catch (OSSException oe) {
|
||||
log.error("OSS文件上传错误:{}", oe);
|
||||
throw new ProjectException(FileEnum.UPLOAD_FAIL);
|
||||
} catch (ClientException ce) {
|
||||
log.error("OSS文件上传客户端错误:{}",ce);
|
||||
throw new ProjectException(FileEnum.UPLOAD_FAIL);
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File initiateMultipartUpload(String suffix, String filename, String bucketName, boolean autoCatalog) {
|
||||
// 是否自动生成存储路径并设置文件路径和名称(Key)
|
||||
String key = filename;
|
||||
InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(bucketName, key);
|
||||
// 如果需要在初始化分片时设置请求头,请参考以下示例代码。
|
||||
ObjectMetadata metadata = fileMetaHandler(suffix);
|
||||
metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard.toString());
|
||||
// 指定该Object的网页缓存行为。
|
||||
metadata.setCacheControl("no-cache");
|
||||
// 指定该Object被下载时的名称。
|
||||
metadata.setContentDisposition("inline;filename="+key);
|
||||
// 指定该Object的内容编码格式。
|
||||
metadata.setContentEncoding(OSSConstants.DEFAULT_CHARSET_NAME);
|
||||
//指定请求
|
||||
request.setObjectMetadata(metadata);
|
||||
// 初始化分片。
|
||||
InitiateMultipartUploadResult upresult = ossClient.initiateMultipartUpload(request);
|
||||
// 设置权限(公开读)
|
||||
ossClient.setBucketAcl(bucketName, CannedAccessControlList.PublicRead);
|
||||
// 返回uploadId,它是分片上传事件的唯一标识。您可以根据该uploadId发起相关的操作,例如取消分片上传、查询分片上传等。
|
||||
return File.builder().bucketName(bucketName).pathUrl(key).fileName(key).uploadId(upresult.getUploadId()).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String uploadPart(String upLoadId, String filename, int partNumber, long partSize, String bucketName, InputStream inputStream) {
|
||||
//封装分片上传请求
|
||||
UploadPartRequest uploadPartRequest = new UploadPartRequest();
|
||||
uploadPartRequest.setUploadId(upLoadId);
|
||||
//part大小 1-10000
|
||||
uploadPartRequest.setPartNumber(partNumber);
|
||||
uploadPartRequest.setPartSize(partSize);
|
||||
//文件上传的bucketName
|
||||
uploadPartRequest.setBucketName(bucketName);
|
||||
//分片文件
|
||||
uploadPartRequest.setInputStream(inputStream);
|
||||
uploadPartRequest.setKey(filename);
|
||||
// 每个分片不需要按顺序上传,甚至可以在不同客户端上传,OSS会按照分片号排序组成完整的文件。
|
||||
UploadPartResult uploadPartResult = ossClient.uploadPart(uploadPartRequest);
|
||||
log.info("{}文件第 {} 片上传成功,上传结果:{}", upLoadId, uploadPartRequest.getPartNumber(),JSON.toJSON(uploadPartResult));
|
||||
return JSONObject.toJSONString(uploadPartResult.getPartETag());
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String completeMultipartUpload(String upLoadId, List<String> partETags, String filename, String bucketName) {
|
||||
StopWatch st = new StopWatch();
|
||||
st.start();
|
||||
//转换jsonarray为list
|
||||
List<PartETag> partETagList =Lists.newArrayList();
|
||||
partETags.forEach(n->{
|
||||
partETagList.add(JSONObject.parseObject(n,PartETag.class));
|
||||
});
|
||||
CompleteMultipartUploadRequest completeMultipartUploadRequest =
|
||||
new CompleteMultipartUploadRequest(bucketName, filename, upLoadId, partETagList);
|
||||
log.info("{}文件上传完成,开始合并,partList:{}", upLoadId, partETags);
|
||||
// 完成分片上传。
|
||||
CompleteMultipartUploadResult completeMultipartUploadResult = ossClient.completeMultipartUpload(completeMultipartUploadRequest);
|
||||
st.stop();
|
||||
log.info("{}文件上传完成,上传结果:{},耗时:{}", upLoadId, JSON.toJSON(completeMultipartUploadResult), st.getTotalTimeMillis());
|
||||
return completeMultipartUploadResult.getETag();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public InputStream downloadFile(String bucketName,String pathUrl) throws IOException {
|
||||
GetObjectRequest request = new GetObjectRequest(bucketName, pathUrl);
|
||||
//下载传限流
|
||||
if (ossAliyunConfigProperties.getIslimitSpeed()){
|
||||
request.setTrafficLimit(ossAliyunConfigProperties.getDownlimitSpeed());
|
||||
}
|
||||
//ossObject包含文件所在的存储空间名称、文件名称、文件元信息以及一个输入流。
|
||||
InputStream inputStream = ossClient.getObject(request).getObjectContent();
|
||||
return inputStream;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(String bucketName,String pathUrl) {
|
||||
// 删除Objects
|
||||
ossClient.deleteObject(bucketName,pathUrl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteBatch(String bucketName,List<String> pathUrls) {
|
||||
// 删除Objects
|
||||
ossClient.deleteObjects(new DeleteObjectsRequest(bucketName).withKeys(pathUrls));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFileContent(String bucketName,String pathUrl) throws IOException {
|
||||
InputStream inputStream = downloadFile(bucketName,pathUrl);
|
||||
return new String(ByteStreams.toByteArray(inputStream));
|
||||
}
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
package com.itheima.sfbx.file.handler.aliyun.properties;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* @Description 阿里云OSS上传配置类
|
||||
*/
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@ConfigurationProperties("spring.cloud.alicloud.oss")
|
||||
public class OssAliyunConfigProperties {
|
||||
|
||||
//区域
|
||||
String region;
|
||||
|
||||
//秘钥ID
|
||||
String accessKeyId;
|
||||
|
||||
//秘钥
|
||||
String accessKeySecret;
|
||||
|
||||
//角色
|
||||
String roleArn;
|
||||
|
||||
//桶名称
|
||||
private String bucketName ;
|
||||
|
||||
//访问终端域名地址
|
||||
private String endpoint;
|
||||
|
||||
//是否限流
|
||||
private Boolean islimitSpeed = true;
|
||||
|
||||
//上传限流
|
||||
private int uplimitSpeed = 100 * 1024 * 1024 * 2;
|
||||
|
||||
//下载限流
|
||||
private int downlimitSpeed = 100 * 1024 * 8;
|
||||
|
||||
}
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
package com.itheima.sfbx.file.handler.qiniu.config;
|
||||
|
||||
import com.itheima.sfbx.file.handler.qiniu.properties.QiniuProperties;
|
||||
import com.qiniu.storage.BucketManager;
|
||||
import com.qiniu.storage.Region;
|
||||
import com.qiniu.util.Auth;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Qiniu服务配置类
|
||||
* </p>
|
||||
* 声明创建Qiniu核心配置对象
|
||||
*/
|
||||
@Slf4j
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(QiniuProperties.class)
|
||||
public class QiniuConfig {
|
||||
|
||||
@Autowired
|
||||
private QiniuProperties qiniuConfigProperties;
|
||||
|
||||
private static Map<String, Region> regions =new HashMap<>();
|
||||
|
||||
static {
|
||||
regions.put(QiniuRegion.REGION_HUADONG,Region.huadong());
|
||||
regions.put(QiniuRegion.REGION_HUABEI,Region.huabei());
|
||||
regions.put(QiniuRegion.REGION_HUANAN,Region.huanan());
|
||||
regions.put(QiniuRegion.REGION_BEIMEI,Region.beimei());
|
||||
regions.put(QiniuRegion.REGION_DONGNANYA,Region.xinjiapo());
|
||||
}
|
||||
|
||||
@Bean("qiniuConfiguration")
|
||||
public com.qiniu.storage.Configuration qiniuConfiguration() {
|
||||
|
||||
// 设置存储区域
|
||||
String regionString = qiniuConfigProperties.getKodo().getRegion();
|
||||
|
||||
Region region = regions.get(regionString);
|
||||
|
||||
com.qiniu.storage.Configuration configuration = new com.qiniu.storage.Configuration(region);
|
||||
// 使用http协议
|
||||
configuration.useHttpsDomains = false;
|
||||
|
||||
//上传限流,超过后上传会自动转为分片上传
|
||||
configuration.resumableUploadAPIV2BlockSize = qiniuConfigProperties.getUplimitSpeed();
|
||||
|
||||
return configuration;
|
||||
}
|
||||
|
||||
@Bean("qiniuAuth")
|
||||
public Auth qiniuAuth() {
|
||||
Auth auth = Auth.create(qiniuConfigProperties.getAccessKey(),
|
||||
qiniuConfigProperties.getSecretKey());
|
||||
return auth;
|
||||
}
|
||||
|
||||
@Bean("bucketManager")
|
||||
public BucketManager bucketManager(@Qualifier("qiniuConfiguration") com.qiniu.storage.Configuration configuration,
|
||||
@Qualifier("qiniuAuth") Auth auth
|
||||
) {
|
||||
BucketManager bucketManager = new BucketManager(auth, configuration);
|
||||
return bucketManager;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 七牛服务区域标识
|
||||
* </p>
|
||||
* 此标识是由七牛的kodo对象存储中定义,参考 {@link Region}
|
||||
*/
|
||||
public interface QiniuRegion {
|
||||
|
||||
/**
|
||||
* z0 华东
|
||||
*/
|
||||
String REGION_HUADONG = "z0";
|
||||
/**
|
||||
* z1 华北
|
||||
*/
|
||||
String REGION_HUABEI = "z1";
|
||||
/**
|
||||
* z2 华南
|
||||
*/
|
||||
String REGION_HUANAN = "z2";
|
||||
/**
|
||||
* na0 北美
|
||||
*/
|
||||
String REGION_BEIMEI = "na0";
|
||||
/**
|
||||
* as0 东南亚
|
||||
*/
|
||||
String REGION_DONGNANYA = "as0";
|
||||
}
|
||||
|
||||
}
|
||||
+169
@@ -0,0 +1,169 @@
|
||||
package com.itheima.sfbx.file.handler.qiniu.impl;
|
||||
|
||||
import com.aliyun.oss.ClientException;
|
||||
import com.google.common.io.ByteStreams;
|
||||
import com.google.gson.Gson;
|
||||
import com.itheima.sfbx.file.handler.qiniu.properties.QiniuProperties;
|
||||
import com.itheima.sfbx.framework.commons.enums.file.FileEnum;
|
||||
import com.itheima.sfbx.framework.commons.exception.ProjectException;
|
||||
import com.itheima.sfbx.framework.commons.utils.EmptyUtil;
|
||||
import com.itheima.sfbx.file.handler.AbsFileStorageHandler;
|
||||
import com.itheima.sfbx.file.handler.FileStorageHandler;
|
||||
import com.itheima.sfbx.file.pojo.File;
|
||||
import com.qiniu.common.QiniuException;
|
||||
import com.qiniu.http.Response;
|
||||
import com.qiniu.storage.BucketManager;
|
||||
import com.qiniu.storage.Configuration;
|
||||
import com.qiniu.storage.DownloadUrl;
|
||||
import com.qiniu.storage.UploadManager;
|
||||
import com.qiniu.storage.model.BatchStatus;
|
||||
import com.qiniu.storage.model.DefaultPutRet;
|
||||
import com.qiniu.util.Auth;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @ClassName OssFileStorageHandlerImpl.java
|
||||
* @Description 七牛云文件上传
|
||||
*/
|
||||
@Slf4j
|
||||
@Service("kodoFileStorageHandler")
|
||||
public class KodoFileStorageHandlerImpl extends AbsFileStorageHandler implements FileStorageHandler {
|
||||
|
||||
@Autowired
|
||||
private Auth qiniuAuth;
|
||||
|
||||
@Autowired
|
||||
private Configuration qiniuConfiguration;
|
||||
|
||||
@Autowired
|
||||
private BucketManager bucketManager;
|
||||
|
||||
@Autowired
|
||||
QiniuProperties qiniuConfigProperties;
|
||||
|
||||
@Override
|
||||
public String uploadFile(String suffix, String filename, String bucketName, boolean autoCatalog, InputStream inputStream) {
|
||||
if (EmptyUtil.isNullOrEmpty(bucketName)){
|
||||
bucketName=qiniuConfigProperties.getKodo().getBucketName();
|
||||
}
|
||||
String pathUrl = null;
|
||||
// 是否自动生成存储路径并设置文件路径和名称(Key)
|
||||
String key = autoCatalog?builderOssPath(filename):filename;
|
||||
log.info("七牛Kodo文件上传开始:{}", key);
|
||||
try {
|
||||
String upToken = qiniuAuth.uploadToken(bucketName);
|
||||
String mimeType = metaMimeTypeMap.get(suffix);
|
||||
UploadManager uploadManager = new UploadManager(qiniuConfiguration);
|
||||
Response response = uploadManager.put(inputStream, key, upToken, null, mimeType);
|
||||
//解析上传成功的结果
|
||||
DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
|
||||
if (!(StringUtils.isEmpty(putRet.key))) {
|
||||
log.info("七牛Kodo文件上传成功:{}", putRet.key);
|
||||
pathUrl = putRet.key;
|
||||
}
|
||||
} catch (QiniuException oe) {
|
||||
log.error("七牛Kodo文件上传错误:{}", oe);
|
||||
throw new ProjectException(FileEnum.UPLOAD_FAIL);
|
||||
} catch (ClientException ce) {
|
||||
log.error("七牛Kodo文件上传客户端错误:{}", ce);
|
||||
throw new ProjectException(FileEnum.UPLOAD_FAIL);
|
||||
}
|
||||
return pathUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File initiateMultipartUpload(String suffix, String filename, String bucketName, boolean autoCatalog) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String uploadPart(String uploadId, String filename, int partNumber, long partSize, String bucketName, InputStream inputStream) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String completeMultipartUpload(String uploadId, List<String> partETags, String filename, String bucketName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* 七牛获得文件的inputStream
|
||||
* 1.官方文档只有获得文件的URL路径地址的接口,没有直接获得Inputstream
|
||||
* 2.URL地址需要获得bucket所属于域名
|
||||
* 3.通过域名来获得文件的URL
|
||||
* 4.通过URL转为InputStream
|
||||
* */
|
||||
@Override
|
||||
public InputStream downloadFile(String bucketName, String pathUrl) throws IOException {
|
||||
|
||||
InputStream inputStream = null;
|
||||
try {
|
||||
// 默认获得指定Bucket第一个域名
|
||||
String[] domainList = bucketManager.domainList(bucketName);
|
||||
String domain = domainList[0];
|
||||
// 获得文件的路径并转为URL对象
|
||||
DownloadUrl downloadUrl = new DownloadUrl(domain, false, pathUrl);
|
||||
String buildURL = downloadUrl.buildURL();
|
||||
URL url = new URL(buildURL);
|
||||
// URL转为InputStream
|
||||
inputStream = url.openStream();
|
||||
|
||||
} catch (IOException e) {
|
||||
log.error("七牛Kodo获得文件输入流失败:{}", e);
|
||||
throw new ProjectException(FileEnum.UPLOAD_FAIL);
|
||||
}
|
||||
|
||||
return inputStream;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(String bucketName, String pathUrl) {
|
||||
try {
|
||||
bucketManager.delete(bucketName, pathUrl);
|
||||
} catch (QiniuException e) {
|
||||
//如果遇到异常,说明删除失败
|
||||
log.error("七牛Kodo获得文件输入流失败:{}", e);
|
||||
throw new ProjectException(FileEnum.DELETE_FAIL);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteBatch(String bucketName, List<String> pathUrls) {
|
||||
|
||||
try {
|
||||
BucketManager.BatchOperations batchOperations = new BucketManager.BatchOperations();
|
||||
batchOperations.addDeleteOp(bucketName, pathUrls.toArray(new String[0]));
|
||||
Response response = bucketManager.batch(batchOperations);
|
||||
BatchStatus[] batchStatusList = response.jsonToObject(BatchStatus[].class);
|
||||
|
||||
for (int i = 0; i < pathUrls.size(); i++) {
|
||||
BatchStatus status = batchStatusList[i];
|
||||
String key = pathUrls.get(i);
|
||||
if (status.code != 200) {
|
||||
log.error(status.data.error);
|
||||
log.error("七牛Kodo批量删除文件失败:key 为 {}", key);
|
||||
throw new ProjectException(FileEnum.DELETE_FAIL);
|
||||
}
|
||||
}
|
||||
} catch (QiniuException e) {
|
||||
//如果遇到异常,说明删除失败
|
||||
log.error("七牛Kodo批量删除文件失败:{}", e);
|
||||
throw new ProjectException(FileEnum.DELETE_FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFileContent(String bucketName, String pathUrl) throws IOException {
|
||||
InputStream inputStream = downloadFile(bucketName, pathUrl);
|
||||
return new String(ByteStreams.toByteArray(inputStream));
|
||||
}
|
||||
}
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
package com.itheima.sfbx.file.handler.qiniu.properties;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* @Description 阿里云OSS上传配置类
|
||||
*/
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@ConfigurationProperties("spring.cloud.qiniu")
|
||||
public class QiniuProperties {
|
||||
|
||||
//访问key
|
||||
private String accessKey ;
|
||||
|
||||
//密钥key
|
||||
private String secretKey ;
|
||||
|
||||
//是否限流
|
||||
private Boolean islimitSpeed = true;
|
||||
|
||||
//上传限流,超过后上传会自动转为分片上传
|
||||
private int uplimitSpeed = 1024 * 1024 * 8;
|
||||
|
||||
|
||||
private KodoProperties kodo;
|
||||
|
||||
|
||||
public static class KodoProperties {
|
||||
|
||||
/**
|
||||
* 存款空间区域标识,参考 {@link com.qiniu.storage.Region} 中的region属性值
|
||||
*/
|
||||
private String region;
|
||||
|
||||
/**
|
||||
* 存储空间的名称
|
||||
*/
|
||||
private String bucketName;
|
||||
|
||||
/**
|
||||
* 存款空间访问域名
|
||||
*/
|
||||
private String endpoint;
|
||||
|
||||
public KodoProperties() {
|
||||
}
|
||||
|
||||
public KodoProperties(String region, String bucketName) {
|
||||
this.region = region;
|
||||
this.bucketName = bucketName;
|
||||
}
|
||||
public KodoProperties(String region, String bucketName, String endpoint) {
|
||||
this.region = region;
|
||||
this.bucketName = bucketName;
|
||||
this.endpoint = endpoint;
|
||||
}
|
||||
|
||||
public String getEndpoint() {
|
||||
return endpoint;
|
||||
}
|
||||
|
||||
public void setEndpoint(String endpoint) {
|
||||
this.endpoint = endpoint;
|
||||
}
|
||||
|
||||
public String getRegion() {
|
||||
return region;
|
||||
}
|
||||
|
||||
public void setRegion(String region) {
|
||||
this.region = region;
|
||||
}
|
||||
|
||||
public String getBucketName() {
|
||||
return bucketName;
|
||||
}
|
||||
|
||||
public void setBucketName(String bucketName) {
|
||||
this.bucketName = bucketName;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.itheima.sfbx.file.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.itheima.sfbx.file.pojo.File;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* @Description:附件Mapper接口
|
||||
*/
|
||||
@Mapper
|
||||
public interface FileMapper extends BaseMapper<File> {
|
||||
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package com.itheima.sfbx.file.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.itheima.sfbx.file.pojo.FilePart;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* @Description:Mapper接口
|
||||
*/
|
||||
@Mapper
|
||||
public interface FilePartMapper extends BaseMapper<FilePart> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package com.itheima.sfbx.file.pojo;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.itheima.sfbx.framework.mybatisplus.basic.BasePojo;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @Description:附件
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("tab_file")
|
||||
@ApiModel(value="File对象", description="附件")
|
||||
public class File extends BasePojo {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Builder
|
||||
public File(Long id, String dataState, Long businessId, String businessType, String suffix, String fileName, String pathUrl, String storeFlag, String bucketName, String uploadId, String md5, String status, String companyNo) {
|
||||
super(id, dataState);
|
||||
this.businessId = businessId;
|
||||
this.businessType = businessType;
|
||||
this.suffix = suffix;
|
||||
this.fileName = fileName;
|
||||
this.pathUrl = pathUrl;
|
||||
this.storeFlag = storeFlag;
|
||||
this.bucketName = bucketName;
|
||||
this.uploadId = uploadId;
|
||||
this.md5 = md5;
|
||||
this.status = status;
|
||||
this.companyNo = companyNo;
|
||||
}
|
||||
|
||||
@ApiModelProperty(value = "业务ID")
|
||||
private Long businessId;
|
||||
|
||||
@ApiModelProperty(value = "业务类型")
|
||||
private String businessType;
|
||||
|
||||
@ApiModelProperty(value = "后缀名")
|
||||
private String suffix;
|
||||
|
||||
@ApiModelProperty(value = "文件名")
|
||||
private String fileName;
|
||||
|
||||
@ApiModelProperty(value = "访问路径")
|
||||
private String pathUrl;
|
||||
|
||||
@ApiModelProperty(value = "存储源标识,参考FileConstant")
|
||||
private String storeFlag;
|
||||
|
||||
@ApiModelProperty(value = "存储空间名称")
|
||||
private String bucketName;
|
||||
|
||||
@ApiModelProperty(value = "分片上传文件Id")
|
||||
private String uploadId;
|
||||
|
||||
@ApiModelProperty(value = "md5值")
|
||||
private String md5;
|
||||
|
||||
@ApiModelProperty(value = "状态:上传中【sending】,完成【succeed】,失败【failed】")
|
||||
private String status;
|
||||
|
||||
@ApiModelProperty(value = "企业号")
|
||||
private String companyNo;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.itheima.sfbx.file.pojo;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.itheima.sfbx.framework.mybatisplus.basic.BasePojo;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @Description:
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("tab_file_part")
|
||||
@ApiModel(value="FilePart对象", description="分片上传")
|
||||
public class FilePart extends BasePojo {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Builder
|
||||
public FilePart(Long id, String dataState, String uploadId, Integer partNumber, String uploadResult, String md5, String bucketName, String fileName, String storeFlag, String companyNo) {
|
||||
super(id, dataState);
|
||||
this.uploadId = uploadId;
|
||||
this.partNumber = partNumber;
|
||||
this.uploadResult = uploadResult;
|
||||
this.md5 = md5;
|
||||
this.bucketName = bucketName;
|
||||
this.fileName = fileName;
|
||||
this.storeFlag = storeFlag;
|
||||
this.companyNo = companyNo;
|
||||
}
|
||||
|
||||
@ApiModelProperty(value = "唯一上传id")
|
||||
private String uploadId;
|
||||
|
||||
@ApiModelProperty(value = "当前片数")
|
||||
private Integer partNumber;
|
||||
|
||||
@ApiModelProperty(value = "分片上传结果(json)")
|
||||
private String uploadResult;
|
||||
|
||||
@ApiModelProperty(value = "md5值")
|
||||
private String md5;
|
||||
|
||||
@ApiModelProperty(value = "存储空间名称")
|
||||
private String bucketName;
|
||||
|
||||
@ApiModelProperty(value = "文件名")
|
||||
private String fileName;
|
||||
|
||||
@ApiModelProperty(value = "存储源标识,参考FileConstant")
|
||||
private String storeFlag;
|
||||
|
||||
@ApiModelProperty(value = "企业号")
|
||||
private String companyNo;
|
||||
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
package com.itheima.sfbx.file.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.itheima.sfbx.file.pojo.FilePart;
|
||||
import com.itheima.sfbx.framework.commons.dto.file.FilePartVO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Description:服务类
|
||||
*/
|
||||
public interface IFilePartService extends IService<FilePart> {
|
||||
|
||||
/**
|
||||
* @Description 多条件查询分页列表
|
||||
* @param filePartVo 查询条件
|
||||
* @param pageNum 页码
|
||||
* @param pageSize 每页条数
|
||||
* @return Page<FilePart>
|
||||
*/
|
||||
Page<FilePart> findFilePartPage(FilePartVO filePartVo, int pageNum, int pageSize);
|
||||
|
||||
/**
|
||||
* @Description 创建
|
||||
* @param filePartVo 对象信息
|
||||
* @return FilePart
|
||||
*/
|
||||
FilePart createFilePart(FilePartVO filePartVo);
|
||||
|
||||
/**
|
||||
* @Description 修改
|
||||
* @param filePartVo 对象信息
|
||||
* @return Boolean
|
||||
*/
|
||||
Boolean updateFilePart(FilePartVO filePartVo);
|
||||
|
||||
/**
|
||||
* @Description 删除
|
||||
* @param checkedIds 选择中对象Ids
|
||||
* @return Boolean
|
||||
*/
|
||||
Boolean deleteFilePart(String[] checkedIds);
|
||||
|
||||
/**
|
||||
* @description 多条件查询列表
|
||||
* @param filePartVo 查询条件
|
||||
* @return: List<FilePart>
|
||||
*/
|
||||
List<FilePart> findFilePartList(FilePartVO filePartVo);
|
||||
|
||||
/**
|
||||
* @description 按upLoadId删除记录
|
||||
* @param upLoadId 上传ID
|
||||
* @return: List<FilePart>
|
||||
*/
|
||||
Boolean deleteFilePartByUpLoadId(String upLoadId);
|
||||
}
|
||||
+149
@@ -0,0 +1,149 @@
|
||||
package com.itheima.sfbx.file.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.itheima.sfbx.framework.commons.dto.file.FilePartVO;
|
||||
import com.itheima.sfbx.framework.commons.dto.file.UploadMultipartFile;
|
||||
import com.itheima.sfbx.file.pojo.File;
|
||||
import com.itheima.sfbx.framework.commons.dto.file.FileVO;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @Description:附件 服务类
|
||||
*/
|
||||
public interface IFileService extends IService<File> {
|
||||
|
||||
/**
|
||||
* @Description 按业务ID查询附件
|
||||
* @param businessId 附件对象业务Id
|
||||
* @return
|
||||
*/
|
||||
List<FileVO> findFileVoByBusinessId(Long businessId) ;
|
||||
|
||||
/**
|
||||
* @Description 附件列表
|
||||
* @param fileVO 查询条件
|
||||
* @return
|
||||
*/
|
||||
Page<FileVO> findFileVOPage(FileVO fileVO, int pageNum, int pageSize);
|
||||
|
||||
/***
|
||||
* @description 定时清理文件
|
||||
* @return
|
||||
*/
|
||||
List<FileVO> needClearFile();
|
||||
|
||||
/***
|
||||
* @description 延迟队列清理文件
|
||||
* @return
|
||||
*/
|
||||
FileVO needClearFileById(String id);
|
||||
|
||||
/**
|
||||
* @Description 业务绑定单个附件
|
||||
* @param fileVO 附件对象
|
||||
* @return
|
||||
*/
|
||||
FileVO bindFile(FileVO fileVO);
|
||||
|
||||
/**
|
||||
* @Description 相同业务绑定多个附件
|
||||
* @param fileVOs 相同业务的多个附件对象
|
||||
* @return
|
||||
*/
|
||||
List<FileVO> bindBatchFile(List<FileVO> fileVOs);
|
||||
|
||||
/**
|
||||
* @Description 移除业务原图片,并绑定新的图片到业务上
|
||||
* @param fileVO 附件对象
|
||||
* @return
|
||||
*/
|
||||
Boolean replaceBindFile(FileVO fileVO);
|
||||
|
||||
/**
|
||||
* @Description 移除业务原图片,并批量绑定新的图片到业务上
|
||||
* @param fileVOs 附件对象
|
||||
* @return
|
||||
*/
|
||||
Boolean replaceBindBatchFile(List<FileVO> fileVOs);
|
||||
|
||||
/**
|
||||
* @description 按业务ID查询附件
|
||||
* @param businessIds 业务ids
|
||||
* @return java.util.List<com.itheima.travel.req.FileVO>
|
||||
*/
|
||||
List<FileVO> findInBusinessIds(List<Long> businessIds);
|
||||
|
||||
/**
|
||||
* @Description 删除业务相关附件
|
||||
* @param businessIds 附件信息ids
|
||||
* @return
|
||||
*/
|
||||
Boolean deleteInBusinessIds(List<Long> businessIds);
|
||||
|
||||
/**
|
||||
* @Description 删除业务相关附件
|
||||
* @param ids 附件信息ids
|
||||
* @return
|
||||
*/
|
||||
Boolean deleteInIds(List<Long> ids);
|
||||
|
||||
/**
|
||||
* @Description 定时清理文件
|
||||
* @return Boolean
|
||||
*/
|
||||
Boolean clearFile();
|
||||
|
||||
/**
|
||||
* @Description 定时清理文件
|
||||
* @return Boolean
|
||||
*/
|
||||
Boolean clearFileById(String fileId);
|
||||
|
||||
/**
|
||||
* @Description 查询所有业务对应附件
|
||||
* @return Set<Long>
|
||||
*/
|
||||
Set<Long> findBusinessIdAll();
|
||||
|
||||
/***
|
||||
* @description 文件简单上传
|
||||
*
|
||||
* @param uploadMultipartFile
|
||||
* @param fileVO
|
||||
* @return FileVO
|
||||
*/
|
||||
FileVO upLoad(UploadMultipartFile uploadMultipartFile, FileVO fileVO);
|
||||
|
||||
/***
|
||||
* @description 初始化分片上传
|
||||
*
|
||||
* @param fileVO
|
||||
* @return FileVO
|
||||
*/
|
||||
FileVO initiateMultipartUpload(FileVO fileVO);
|
||||
|
||||
/***
|
||||
* @description 分片每个分片
|
||||
* @param uploadMultipartFile
|
||||
* @param filePartVo
|
||||
* @return String
|
||||
*/
|
||||
String uploadPart(UploadMultipartFile uploadMultipartFile, FilePartVO filePartVo);
|
||||
|
||||
/***
|
||||
* @description 合并所有分片
|
||||
* @param fileVO
|
||||
* @return String
|
||||
*/
|
||||
String completeMultipartUpload(FileVO fileVO);
|
||||
|
||||
/***
|
||||
* @description 文件下载
|
||||
* @param fileId
|
||||
* @return FileVO
|
||||
*/
|
||||
FileVO downLoad(Long fileId);
|
||||
}
|
||||
+115
@@ -0,0 +1,115 @@
|
||||
package com.itheima.sfbx.file.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.itheima.sfbx.framework.commons.dto.file.FilePartVO;
|
||||
import com.itheima.sfbx.framework.commons.utils.BeanConv;
|
||||
import com.itheima.sfbx.framework.commons.utils.EmptyUtil;
|
||||
import com.itheima.sfbx.file.mapper.FilePartMapper;
|
||||
import com.itheima.sfbx.file.pojo.FilePart;
|
||||
import com.itheima.sfbx.file.service.IFilePartService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Description:服务实现类
|
||||
*/
|
||||
@Service
|
||||
public class FilePartServiceImpl extends ServiceImpl<FilePartMapper, FilePart> implements IFilePartService {
|
||||
|
||||
@Override
|
||||
public Page<FilePart> findFilePartPage(FilePartVO filePartVo, int pageNum, int pageSize) {
|
||||
//构建分页对象
|
||||
Page<FilePart> page = new Page<>(pageNum,pageSize);
|
||||
//构建查询条件
|
||||
QueryWrapper<FilePart> queryWrapper = new QueryWrapper<>();
|
||||
//构建多条件查询,代码生成后自己可自行调整
|
||||
//唯一上传id查询
|
||||
if (!EmptyUtil.isNullOrEmpty(filePartVo.getUploadId())) {
|
||||
queryWrapper.lambda().eq(FilePart::getUploadId,filePartVo.getUploadId());
|
||||
}
|
||||
//当前片数查询
|
||||
if (!EmptyUtil.isNullOrEmpty(filePartVo.getPartNumber())) {
|
||||
queryWrapper.lambda().eq(FilePart::getPartNumber,filePartVo.getPartNumber());
|
||||
}
|
||||
//分片上传结果(json)查询
|
||||
if (!EmptyUtil.isNullOrEmpty(filePartVo.getUploadResult())) {
|
||||
queryWrapper.lambda().eq(FilePart::getUploadResult,filePartVo.getUploadResult());
|
||||
}
|
||||
//状态查询
|
||||
if (!EmptyUtil.isNullOrEmpty(filePartVo.getDataState())) {
|
||||
queryWrapper.lambda().eq(FilePart::getDataState,filePartVo.getDataState());
|
||||
}
|
||||
//按创建时间降序
|
||||
queryWrapper.lambda().orderByDesc(FilePart::getCreateTime);
|
||||
//执行分页查询
|
||||
return page(page, queryWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FilePart createFilePart(FilePartVO filePartVo) {
|
||||
//转换FilePartVO为FilePart
|
||||
FilePart filePart = BeanConv.toBean(filePartVo, FilePart.class);
|
||||
boolean flag = save(filePart);
|
||||
if (flag){
|
||||
return filePart;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean updateFilePart(FilePartVO filePartVo) {
|
||||
//转换FilePartVO为FilePart
|
||||
FilePart filePart = BeanConv.toBean(filePartVo, FilePart.class);
|
||||
return updateById(filePart);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean deleteFilePart(String[] checkedIds) {
|
||||
//转换数组为集合
|
||||
List<String> ids = Arrays.asList(checkedIds);
|
||||
List<Long> idsLong = new ArrayList<>();
|
||||
ids.forEach(n->{
|
||||
idsLong.add(Long.valueOf(n));
|
||||
});
|
||||
return removeByIds(idsLong);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FilePart> findFilePartList(FilePartVO filePartVo) {
|
||||
//构建查询条件
|
||||
QueryWrapper<FilePart> queryWrapper = new QueryWrapper<>();
|
||||
if (!EmptyUtil.isNullOrEmpty(filePartVo.getId())) {
|
||||
queryWrapper.lambda().eq(FilePart::getId,filePartVo.getId());
|
||||
}
|
||||
//唯一上传id查询
|
||||
if (!EmptyUtil.isNullOrEmpty(filePartVo.getUploadId())) {
|
||||
queryWrapper.lambda().eq(FilePart::getUploadId,filePartVo.getUploadId());
|
||||
}
|
||||
//当前片数查询
|
||||
if (!EmptyUtil.isNullOrEmpty(filePartVo.getPartNumber())) {
|
||||
queryWrapper.lambda().eq(FilePart::getPartNumber,filePartVo.getPartNumber());
|
||||
}
|
||||
//当前片数查询
|
||||
if (!EmptyUtil.isNullOrEmpty(filePartVo.getMd5())) {
|
||||
queryWrapper.lambda().eq(FilePart::getMd5,filePartVo.getMd5());
|
||||
}
|
||||
//状态查询
|
||||
if (!EmptyUtil.isNullOrEmpty(filePartVo.getDataState())) {
|
||||
queryWrapper.lambda().eq(FilePart::getDataState,filePartVo.getDataState());
|
||||
}
|
||||
return list(queryWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean deleteFilePartByUpLoadId(String upLoadId) {
|
||||
UpdateWrapper<FilePart> updateWrapperp = new UpdateWrapper<>();
|
||||
updateWrapperp.lambda().eq(FilePart::getUploadId,upLoadId);
|
||||
return remove(updateWrapperp);
|
||||
}
|
||||
}
|
||||
+593
@@ -0,0 +1,593 @@
|
||||
package com.itheima.sfbx.file.service.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.aliyun.oss.model.UploadPartResult;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.itheima.sfbx.file.adapter.FileStorageAdapter;
|
||||
import com.itheima.sfbx.file.mapper.FileMapper;
|
||||
import com.itheima.sfbx.file.pojo.File;
|
||||
import com.itheima.sfbx.file.pojo.FilePart;
|
||||
import com.itheima.sfbx.file.service.IFilePartService;
|
||||
import com.itheima.sfbx.file.service.IFileService;
|
||||
import com.itheima.sfbx.file.utils.FileUrlContext;
|
||||
import com.itheima.sfbx.framework.commons.constant.basic.SuperConstant;
|
||||
import com.itheima.sfbx.framework.commons.constant.file.FileCacheConstant;
|
||||
import com.itheima.sfbx.framework.commons.constant.file.FileConstant;
|
||||
import com.itheima.sfbx.framework.commons.dto.file.FileVO;
|
||||
import com.itheima.sfbx.framework.commons.dto.file.FilePartVO;
|
||||
import com.itheima.sfbx.framework.commons.dto.file.UploadMultipartFile;
|
||||
import com.itheima.sfbx.framework.commons.enums.file.FileEnum;
|
||||
import com.itheima.sfbx.framework.commons.exception.ProjectException;
|
||||
import com.itheima.sfbx.framework.commons.utils.BeanConv;
|
||||
import com.itheima.sfbx.framework.commons.utils.EmptyUtil;
|
||||
import com.itheima.sfbx.framework.commons.utils.EncodesUtil;
|
||||
import com.itheima.sfbx.framework.commons.utils.ExceptionsUtil;
|
||||
import com.itheima.sfbx.framework.rabbitmq.pojo.MqMessage;
|
||||
import com.itheima.sfbx.framework.rabbitmq.source.FileSource;
|
||||
import lombok.Cleanup;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.redisson.api.RLock;
|
||||
import org.redisson.api.RedissonClient;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.CachePut;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.cache.annotation.Caching;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.support.MessageBuilder;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.sql.Timestamp;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @Description:附件 服务实现类
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class FileServiceImpl extends ServiceImpl<FileMapper, File> implements IFileService {
|
||||
|
||||
@Value("${file-delay-time}")
|
||||
Integer fileDelayTime;
|
||||
|
||||
@Autowired
|
||||
private FileUrlContext fileUrlContext;
|
||||
|
||||
@Autowired
|
||||
FileStorageAdapter fileStorageAdapter;
|
||||
|
||||
@Autowired
|
||||
IdentifierGenerator identifierGenerator;
|
||||
|
||||
@Autowired
|
||||
FileSource fileSource;
|
||||
|
||||
@Autowired
|
||||
RedissonClient redissonClient;
|
||||
|
||||
@Autowired
|
||||
IFilePartService filePartService;
|
||||
|
||||
private QueryWrapper<File> queryWrapper(FileVO fileVO){
|
||||
QueryWrapper<File> queryWrapper = new QueryWrapper<>();
|
||||
if (!EmptyUtil.isNullOrEmpty(fileVO.getBusinessType())) {
|
||||
queryWrapper.lambda().eq(File::getBusinessType,fileVO.getBusinessType());
|
||||
}
|
||||
if (!EmptyUtil.isNullOrEmpty(fileVO.getFileName())) {
|
||||
queryWrapper.lambda().likeRight(File::getFileName,fileVO.getFileName());
|
||||
}
|
||||
if (!EmptyUtil.isNullOrEmpty(fileVO.getPathUrl())) {
|
||||
queryWrapper.lambda().likeRight(File::getPathUrl,fileVO.getPathUrl());
|
||||
}
|
||||
if (!EmptyUtil.isNullOrEmpty(fileVO.getDataState())) {
|
||||
queryWrapper.lambda().likeRight(File::getDataState,fileVO.getDataState());
|
||||
}
|
||||
if (!EmptyUtil.isNullOrEmpty(fileVO.getStatus())) {
|
||||
queryWrapper.lambda().likeRight(File::getStatus,fileVO.getStatus());
|
||||
}
|
||||
queryWrapper.lambda().orderByDesc(File::getCreateTime);
|
||||
return queryWrapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Cacheable(value = FileCacheConstant.BUSINESS_KEY,key = "#businessId")
|
||||
public List<FileVO> findFileVoByBusinessId(Long businessId) {
|
||||
try {
|
||||
QueryWrapper<File> queryWrapper = new QueryWrapper();
|
||||
queryWrapper.lambda().eq(File::getBusinessId,businessId);
|
||||
List<File> files = list(queryWrapper);
|
||||
if (!EmptyUtil.isNullOrEmpty(files)){
|
||||
files.forEach(n->{
|
||||
String fileUrl = fileUrlContext.getFileUrl(n.getStoreFlag(), n.getPathUrl());
|
||||
n.setPathUrl(fileUrl);
|
||||
});
|
||||
}
|
||||
return BeanConv.toBeanList(files,FileVO.class);
|
||||
}catch (Exception e){
|
||||
log.error("查询业务对应附件:{}异常:{}", businessId,ExceptionsUtil.getStackTraceAsString(e));
|
||||
throw new ProjectException(FileEnum.SELECT_FILE_BUSINESSID_FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Cacheable(value = FileCacheConstant.PAGE,key ="#pageNum+'-'+#pageSize+'-'+#fileVO.hashCode()")
|
||||
public Page<FileVO> findFileVOPage(FileVO fileVO, int pageNum , int pageSize) {
|
||||
try {
|
||||
Page<File> page = new Page<>(pageNum,pageSize);
|
||||
QueryWrapper<File> queryWrapper = queryWrapper(fileVO);
|
||||
Page<FileVO> fileVOPage = BeanConv.toPage(page(page, queryWrapper), FileVO.class);
|
||||
if (!EmptyUtil.isNullOrEmpty(fileVOPage)&&!EmptyUtil.isNullOrEmpty(fileVOPage.getRecords())){
|
||||
fileVOPage.getRecords().forEach(n->{
|
||||
n.setPathUrl(fileUrlContext.getFileUrl(n.getStoreFlag(), n.getPathUrl()));
|
||||
});
|
||||
}
|
||||
return fileVOPage;
|
||||
}catch (Exception e){
|
||||
log.error("查询文件分页异常:{}", ExceptionsUtil.getStackTraceAsString(e));
|
||||
throw new ProjectException(FileEnum.PAGE_FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FileVO> needClearFile() {
|
||||
try {
|
||||
QueryWrapper<File> queryWrapper = new QueryWrapper<>();
|
||||
LocalDateTime localDateTime = LocalDateTime.now().minusSeconds(fileDelayTime/1000);
|
||||
queryWrapper.lambda().isNull(File::getBusinessId).lt(File::getCreateTime,localDateTime);
|
||||
return BeanConv.toBeanList(list(queryWrapper), FileVO.class);
|
||||
}catch (Exception e){
|
||||
log.error("查询文件分页异常:{}", ExceptionsUtil.getStackTraceAsString(e));
|
||||
throw new ProjectException(FileEnum.SELECT_FILE_BUSINESSID_FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileVO needClearFileById(String id) {
|
||||
try {
|
||||
QueryWrapper<File> queryWrapper = new QueryWrapper<>();
|
||||
LocalDateTime localDateTime = LocalDateTime.now().minusSeconds(fileDelayTime/1000);
|
||||
queryWrapper.lambda().isNull(File::getBusinessId).lt(File::getCreateTime,localDateTime).eq(File::getId,id);
|
||||
return BeanConv.toBean(getOne(queryWrapper),FileVO.class);
|
||||
}catch (Exception e){
|
||||
log.error("查询文件分页异常:{}", ExceptionsUtil.getStackTraceAsString(e));
|
||||
throw new ProjectException(FileEnum.SELECT_FILE_BUSINESSID_FAIL);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@Caching(evict = {@CacheEvict(value = FileCacheConstant.PAGE,allEntries = true),
|
||||
@CacheEvict(value = FileCacheConstant.BASIC,key = "#fileVO.id"),
|
||||
@CacheEvict(value = FileCacheConstant.BUSINESS_KEY,key = "#fileVO.businessId")})
|
||||
public FileVO bindFile(FileVO fileVO) {
|
||||
try {
|
||||
//修改file表中的businessId
|
||||
File file = BeanConv.toBean(fileVO, File.class);
|
||||
boolean flag = updateById(file);
|
||||
//构建完整返回对象
|
||||
if (flag){
|
||||
QueryWrapper<File> queryWrapper = new QueryWrapper();
|
||||
queryWrapper.lambda().eq(File::getBusinessId,fileVO.getBusinessId());
|
||||
File fileResult = getOne(queryWrapper);
|
||||
if (!EmptyUtil.isNullOrEmpty(file)){
|
||||
fileResult.setPathUrl(fileUrlContext.getFileUrl(fileResult.getStoreFlag(), fileResult.getPathUrl()));
|
||||
}
|
||||
return BeanConv.toBean(fileResult,FileVO.class);
|
||||
}
|
||||
return null;
|
||||
}catch (Exception e){
|
||||
log.error("查询文件分页异常:{}", ExceptionsUtil.getStackTraceAsString(e));
|
||||
throw new ProjectException(FileEnum.SELECT_FILE_BUSINESSID_FAIL);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@Caching(evict = {@CacheEvict(value = FileCacheConstant.PAGE,allEntries = true),
|
||||
@CacheEvict(value = FileCacheConstant.BASIC,allEntries = true),
|
||||
@CacheEvict(value = FileCacheConstant.BUSINESS_KEY,key = "#fileVOs.get(0).getBusinessId()")})
|
||||
public List<FileVO> bindBatchFile(List<FileVO> fileVOs) {
|
||||
Long businessId = fileVOs.get(0).getBusinessId();
|
||||
if (EmptyUtil.isNullOrEmpty(businessId)) {
|
||||
throw new ProjectException(FileEnum.SELECT_BUSUBBESSID_FAIL);
|
||||
}
|
||||
try {
|
||||
//修改file表中的businessId
|
||||
updateBatchById(BeanConv.toBeanList(fileVOs, File.class));
|
||||
QueryWrapper<File> queryWrapper = new QueryWrapper();
|
||||
queryWrapper.lambda().eq(File::getBusinessId,businessId);
|
||||
List<File> files = list(queryWrapper);
|
||||
//构建完整返回对象
|
||||
if (!EmptyUtil.isNullOrEmpty(files)){
|
||||
files.forEach(n->{
|
||||
String fileUrl = fileUrlContext.getFileUrl(n.getStoreFlag(), n.getPathUrl());
|
||||
n.setPathUrl(fileUrl);
|
||||
});
|
||||
}
|
||||
return BeanConv.toBeanList(files,FileVO.class);
|
||||
} catch (Exception e) {
|
||||
log.error("绑定业务:{}异常:{}", fileVOs.toString(),ExceptionsUtil.getStackTraceAsString(e));
|
||||
throw new ProjectException(FileEnum.BIND_FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
@Caching(evict = {@CacheEvict(value = FileCacheConstant.PAGE,allEntries = true),
|
||||
@CacheEvict(value = FileCacheConstant.BASIC,allEntries = true),
|
||||
@CacheEvict(value = FileCacheConstant.LIST,allEntries = true),
|
||||
@CacheEvict(value = FileCacheConstant.BUSINESS_KEY,key = "#fileVO.getBusinessId()")})
|
||||
public Boolean replaceBindFile(FileVO fileVO) {
|
||||
try {
|
||||
//删除老图片
|
||||
ArrayList<Long> ids = Lists.newArrayList();
|
||||
ids.add(fileVO.getId());
|
||||
deleteInIds(ids);
|
||||
//绑定新图片
|
||||
FileVO fileVOResult = bindFile(fileVO);
|
||||
return !EmptyUtil.isNullOrEmpty(fileVOResult);
|
||||
}catch (Exception e){
|
||||
log.error("查询文件分页异常:{}", ExceptionsUtil.getStackTraceAsString(e));
|
||||
throw new ProjectException(FileEnum.BIND_FAIL);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
@Caching(evict = {@CacheEvict(value = FileCacheConstant.PAGE,allEntries = true),
|
||||
@CacheEvict(value = FileCacheConstant.BASIC,allEntries = true),
|
||||
@CacheEvict(value = FileCacheConstant.LIST,allEntries = true),
|
||||
@CacheEvict(value = FileCacheConstant.BUSINESS_KEY,key = "#fileVOs.get(0).getBusinessId()")})
|
||||
public Boolean replaceBindBatchFile(List<FileVO> fileVOs) {
|
||||
try {
|
||||
//查询当前业务图片
|
||||
QueryWrapper<File> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.lambda().eq(File::getBusinessId,fileVOs.get(0).getBusinessId());
|
||||
List<File> oldList = list(queryWrapper);
|
||||
List<Long> oldIds = oldList.stream().map(File::getId).collect(Collectors.toList());
|
||||
List<Long> newIds = fileVOs.stream().map(FileVO::getId).collect(Collectors.toList());
|
||||
//删除:老图片对新图片的差集
|
||||
List<Long> delIds = oldIds.stream().filter(n -> {
|
||||
return !newIds.contains(n);
|
||||
}).collect(Collectors.toList());
|
||||
if (!EmptyUtil.isNullOrEmpty(delIds)){
|
||||
deleteInIds(delIds);
|
||||
}
|
||||
//绑定新图片
|
||||
List<FileVO> newFiles = fileVOs.stream().filter(n -> {
|
||||
return !oldIds.contains(n.getId());
|
||||
}).collect(Collectors.toList());
|
||||
if (!EmptyUtil.isNullOrEmpty(newFiles)){
|
||||
List<FileVO> fileVOsResult = bindBatchFile(newFiles);
|
||||
return !EmptyUtil.isNullOrEmpty(fileVOsResult);
|
||||
}
|
||||
return true;
|
||||
}catch (Exception e){
|
||||
log.error("查询文件分页异常:{}", ExceptionsUtil.getStackTraceAsString(e));
|
||||
throw new ProjectException(FileEnum.BIND_FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Cacheable(value = FileCacheConstant.LIST,key ="#businessIds.hashCode()")
|
||||
public List<FileVO> findInBusinessIds(List<Long> businessIds) {
|
||||
try {
|
||||
QueryWrapper<File> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.lambda().in(File::getBusinessId,businessIds);
|
||||
List<FileVO> fileVOList = BeanConv.toBeanList(list(queryWrapper), FileVO.class);
|
||||
for (FileVO fileVO : fileVOList) {
|
||||
fileVO.setPathUrl(fileUrlContext.getFileUrl(fileVO.getStoreFlag(), fileVO.getPathUrl()));
|
||||
}
|
||||
return fileVOList;
|
||||
}catch (Exception e){
|
||||
log.error("查询文件分页异常:{}", ExceptionsUtil.getStackTraceAsString(e));
|
||||
throw new ProjectException(FileEnum.BIND_FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Caching(evict = {@CacheEvict(value = FileCacheConstant.PAGE,allEntries = true),
|
||||
@CacheEvict(value = FileCacheConstant.BUSINESS_KEY,allEntries = true),
|
||||
@CacheEvict(value = FileCacheConstant.LIST,key ="#businessIds.hashCode()"),
|
||||
@CacheEvict(value = FileCacheConstant.BASIC,allEntries = true)})
|
||||
@Transactional
|
||||
public Boolean deleteInBusinessIds(List<Long> businessIds) {
|
||||
try {
|
||||
//删除数据库
|
||||
List<FileVO> files = findInBusinessIds(businessIds);
|
||||
UpdateWrapper<File> updateWrapper = new UpdateWrapper<>();
|
||||
updateWrapper.lambda().in(File::getBusinessId,businessIds);
|
||||
Boolean flag = remove(updateWrapper);
|
||||
if (!flag){
|
||||
throw new ProjectException(FileEnum.DELETE_FAIL);
|
||||
}
|
||||
//删除OSS中的图片
|
||||
if (!EmptyUtil.isNullOrEmpty(files)){
|
||||
List<String> getPathUrls = files.stream().map(FileVO::getPathUrl).collect(Collectors.toList());
|
||||
FileVO fileVO = files.get(0);
|
||||
String bucketName = fileVO.getBucketName();
|
||||
String storeFlag = fileVO.getStoreFlag();
|
||||
fileStorageAdapter.deleteBatch(storeFlag,bucketName,getPathUrls);
|
||||
}
|
||||
return flag;
|
||||
}catch (Exception e){
|
||||
log.error("删除业务对应附件:{}失败",businessIds);
|
||||
throw new ProjectException(FileEnum.DELETE_FILE_BUSINESSID_FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Caching(evict = {@CacheEvict(value = FileCacheConstant.PAGE,allEntries = true),
|
||||
@CacheEvict(value = FileCacheConstant.BUSINESS_KEY,allEntries = true),
|
||||
@CacheEvict(value = FileCacheConstant.LIST,allEntries = true),
|
||||
@CacheEvict(value = FileCacheConstant.BASIC,allEntries = true)})
|
||||
public Boolean deleteInIds(List<Long> ids) {
|
||||
try {
|
||||
QueryWrapper<File> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.lambda().in(File::getId,ids);
|
||||
List<File> files = list(queryWrapper);
|
||||
boolean flag = removeByIds(ids);
|
||||
if (!flag){
|
||||
throw new ProjectException(FileEnum.DELETE_FAIL);
|
||||
}
|
||||
//移除对象存储数据
|
||||
for (File file : files) {
|
||||
fileStorageAdapter.delete(file.getStoreFlag(),file.getBucketName(),file.getPathUrl());
|
||||
}
|
||||
return flag;
|
||||
}catch (Exception e){
|
||||
log.error("删除文件异常:{}", ExceptionsUtil.getStackTraceAsString(e));
|
||||
throw new ProjectException(FileEnum.DELETE_FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Caching(evict = {@CacheEvict(value = FileCacheConstant.PAGE,allEntries = true),
|
||||
@CacheEvict(value = FileCacheConstant.BUSINESS_KEY,allEntries = true),
|
||||
@CacheEvict(value = FileCacheConstant.BASIC,allEntries = true)})
|
||||
@Transactional
|
||||
public Boolean clearFile() {
|
||||
try {
|
||||
//查询需要清理的文件
|
||||
List<FileVO> fileList = needClearFile();
|
||||
if (EmptyUtil.isNullOrEmpty(fileList)){
|
||||
return true;
|
||||
}
|
||||
List<Long> fileListIds = fileList.stream().map(FileVO::getId).collect(Collectors.toList());
|
||||
//移除数据库信息
|
||||
Boolean flag = removeByIds(fileListIds);
|
||||
//移除对象存储数据
|
||||
for (FileVO fileVO : fileList) {
|
||||
fileStorageAdapter.delete(fileVO.getStoreFlag(),fileVO.getBucketName(),fileVO.getPathUrl());
|
||||
}
|
||||
return flag;
|
||||
}catch (Exception e){
|
||||
log.error("定时清理文件异常:{}", ExceptionsUtil.getStackTraceAsString(e));
|
||||
throw new ProjectException(FileEnum.CLEAR_FILE_TASK_FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Caching(evict = {@CacheEvict(value = FileCacheConstant.PAGE,allEntries = true),
|
||||
@CacheEvict(value = FileCacheConstant.BASIC,key = "#id"),
|
||||
@CacheEvict(value = FileCacheConstant.BUSINESS_KEY,allEntries = true)})
|
||||
@Transactional
|
||||
public Boolean clearFileById(String id) {
|
||||
try {
|
||||
FileVO fileVO = needClearFileById(id);
|
||||
if (EmptyUtil.isNullOrEmpty(fileVO)){
|
||||
return true;
|
||||
}
|
||||
Boolean flag = removeById(fileVO.getId());
|
||||
if (!flag){
|
||||
throw new ProjectException(FileEnum.DELETE_FAIL);
|
||||
}
|
||||
//删除OSS中的图片
|
||||
if (!EmptyUtil.isNullOrEmpty(fileVO)){
|
||||
fileStorageAdapter.delete(fileVO.getStoreFlag(),fileVO.getBucketName(),fileVO.getPathUrl());
|
||||
}
|
||||
return flag;
|
||||
}catch (Exception e){
|
||||
log.error("定时清理文件异常:{}", ExceptionsUtil.getStackTraceAsString(e));
|
||||
throw new ProjectException(FileEnum.CLEAR_FILE_TASK_FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Long> findBusinessIdAll() {
|
||||
try {
|
||||
QueryWrapper<File> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.lambda().eq(File::getDataState, SuperConstant.DATA_STATE_0).isNotNull(File::getBusinessId);
|
||||
List<File> list = list(queryWrapper);
|
||||
if (!EmptyUtil.isNullOrEmpty(list)){
|
||||
return list.stream().map(File::getBusinessId).collect(Collectors.toSet());
|
||||
}
|
||||
return null;
|
||||
}catch (Exception e){
|
||||
log.error("查询附件列表异常:{}", ExceptionsUtil.getStackTraceAsString(e));
|
||||
throw new ProjectException(FileEnum.SELECT_BUSUBBESSID_FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Caching(
|
||||
evict = {
|
||||
@CacheEvict(value = FileCacheConstant.PAGE,allEntries = true),
|
||||
@CacheEvict(value = FileCacheConstant.BUSINESS_KEY,allEntries = true)},
|
||||
put={@CachePut(value =FileCacheConstant.BASIC,key = "#result.id")})
|
||||
@Transactional
|
||||
public FileVO upLoad(UploadMultipartFile multipartFile, FileVO fileVO) throws ProjectException {
|
||||
//获得文件ByteArrayInputStream
|
||||
ByteArrayInputStream byteArrayInputStream =new ByteArrayInputStream(multipartFile.getFileByte());
|
||||
try {
|
||||
//文件重命名
|
||||
String filename = identifierGenerator.nextId(fileVO)+"-"+multipartFile.getOriginalFilename();;
|
||||
fileVO.setFileName(filename);
|
||||
//文件后缀名
|
||||
String suffix = fileVO.getFileName().substring(fileVO.getFileName().lastIndexOf("."));
|
||||
fileVO.setSuffix(suffix);
|
||||
//调用简单上传
|
||||
String pathUrl = fileStorageAdapter.uploadFile(fileVO, byteArrayInputStream);
|
||||
//保存数据库
|
||||
File file = BeanConv.toBean(fileVO, File.class);
|
||||
file.setStatus(FileConstant.STATUS_SUCCEED);
|
||||
file.setPathUrl(pathUrl);
|
||||
boolean flag = save(file);
|
||||
if (!flag){
|
||||
throw new ProjectException(FileEnum.UPLOAD_FAIL);
|
||||
}
|
||||
//补全完整路径
|
||||
pathUrl = fileUrlContext.getFileUrl(fileVO.getStoreFlag(), pathUrl);
|
||||
fileVO.setId(file.getId());
|
||||
fileVO.setPathUrl(pathUrl);
|
||||
//发送延迟信息:上传如果超过10分钟不进行文件业务绑定则会被消息队列清空
|
||||
Long messageId = (Long) identifierGenerator.nextId(fileVO);
|
||||
MqMessage mqMessage = MqMessage.builder()
|
||||
.id(messageId)
|
||||
.title("file-message")
|
||||
.content(JSONObject.toJSONString(fileVO))
|
||||
.messageType("file-request")
|
||||
.produceTime(Timestamp.valueOf(LocalDateTime.now()))
|
||||
.sender("system")
|
||||
.build();
|
||||
Message<MqMessage> message = MessageBuilder.withPayload(mqMessage).setHeader("x-delay", fileDelayTime).build();
|
||||
fileSource.fileOutput().send(message);
|
||||
return fileVO;
|
||||
}catch (Exception e) {
|
||||
log.error("文件上传异常:{}", ExceptionsUtil.getStackTraceAsString(e));
|
||||
throw new ProjectException(FileEnum.UPLOAD_FAIL);
|
||||
}finally {
|
||||
if (byteArrayInputStream != null) {
|
||||
try {
|
||||
byteArrayInputStream.close();
|
||||
} catch (Exception e) {
|
||||
log.error("文件上传操作失败:{}", ExceptionsUtil.getStackTraceAsString(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Caching(evict = {
|
||||
@CacheEvict(value = FileCacheConstant.PAGE,allEntries = true),
|
||||
@CacheEvict(value = FileCacheConstant.BUSINESS_KEY,allEntries = true)},
|
||||
put={@CachePut(value =FileCacheConstant.BASIC,key = "#result.id")})
|
||||
@Transactional
|
||||
public FileVO initiateMultipartUpload(FileVO fileVO) {
|
||||
try {
|
||||
//文件重命名
|
||||
String filename = identifierGenerator.nextId(fileVO)+"-"+fileVO.getFileName();
|
||||
fileVO.setFileName(filename);
|
||||
//文件后缀名
|
||||
String suffix = fileVO.getFileName().substring(fileVO.getFileName().lastIndexOf("."));
|
||||
fileVO.setSuffix(suffix);
|
||||
//分片上传-初始化
|
||||
File file = fileStorageAdapter.initiateMultipartUpload(fileVO);
|
||||
//保存数据库
|
||||
file.setBusinessType(fileVO.getBusinessType());
|
||||
file.setSuffix(suffix);
|
||||
file.setStoreFlag(fileVO.getStoreFlag());
|
||||
file.setMd5(fileVO.getMd5());
|
||||
file.setCompanyNo(fileVO.getCompanyNo());
|
||||
file.setStatus(FileConstant.STATUS_SENDING);
|
||||
boolean flag = save(file);
|
||||
if (!flag){
|
||||
throw new ProjectException(FileEnum.UPLOAD_FAIL);
|
||||
}
|
||||
//补全完整路径
|
||||
FileVO fileVOResult = BeanConv.toBean(file, FileVO.class);
|
||||
String pathUrl = fileUrlContext.getFileUrl(fileVOResult.getStoreFlag(), fileVOResult.getPathUrl());
|
||||
fileVOResult.setPathUrl(pathUrl);
|
||||
//发送队列信息:上传如果超过10分钟不进行文件业务绑定则会被消息队列清空
|
||||
Long messageId = (Long) identifierGenerator.nextId(fileVOResult);
|
||||
MqMessage mqMessage = MqMessage.builder()
|
||||
.id(messageId)
|
||||
.title("file-message")
|
||||
.content(JSONObject.toJSONString(fileVOResult))
|
||||
.messageType("file-request")
|
||||
.produceTime(Timestamp.valueOf(LocalDateTime.now()))
|
||||
.sender("system")
|
||||
.build();
|
||||
Message<MqMessage> message = MessageBuilder.withPayload(mqMessage).setHeader("x-delay", fileDelayTime).build();
|
||||
fileSource.fileOutput().send(message);
|
||||
return fileVOResult;
|
||||
} catch (Exception e) {
|
||||
log.error("文件上传初始化异常:{}", ExceptionsUtil.getStackTraceAsString(e));
|
||||
throw new ProjectException(FileEnum.INIT_UPLOAD_FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public String uploadPart(UploadMultipartFile multipartFile, FilePartVO filePartVO) {
|
||||
try {
|
||||
//上传分片数据
|
||||
String partETagString = fileStorageAdapter.uploadPart(filePartVO, new ByteArrayInputStream(multipartFile.getFileByte()));
|
||||
//保存分片信息
|
||||
FilePart filePart = BeanConv.toBean(filePartVO, FilePart.class);
|
||||
filePart.setUploadResult(partETagString);
|
||||
filePartService.save(filePart);
|
||||
return partETagString;
|
||||
}catch (Exception e) {
|
||||
log.error("文件分片上传异常:{}", ExceptionsUtil.getStackTraceAsString(e));
|
||||
throw new ProjectException(FileEnum.UPLOAD_PART_FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public String completeMultipartUpload(FileVO fileVO) {
|
||||
try {
|
||||
//移除分片记录
|
||||
Boolean flag = filePartService.deleteFilePartByUpLoadId(fileVO.getUploadId());
|
||||
if (!flag){
|
||||
throw new ProjectException(FileEnum.COMPLETE_PART_FAIL);
|
||||
}
|
||||
//修改文件记录状态
|
||||
fileVO.setStatus(FileConstant.STATUS_SUCCEED);
|
||||
flag = updateById(BeanConv.toBean(fileVO,File.class));
|
||||
if (!flag){
|
||||
throw new ProjectException(FileEnum.COMPLETE_PART_FAIL);
|
||||
}
|
||||
//合并结果
|
||||
return fileStorageAdapter.completeMultipartUpload(fileVO);
|
||||
} catch (Exception e) {
|
||||
log.error("文件分片上传异常:{}", ExceptionsUtil.getStackTraceAsString(e));
|
||||
throw new ProjectException(FileEnum.COMPLETE_PART_FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Cacheable(value = FileCacheConstant.BASIC,key = "#fileId")
|
||||
public FileVO downLoad(Long fileId) {
|
||||
try {
|
||||
File file = getById(fileId);
|
||||
InputStream inputStream = fileStorageAdapter
|
||||
.downloadFile(file.getStoreFlag(), file.getBucketName(), file.getPathUrl());
|
||||
byte[] bytes = IOUtils.toByteArray(inputStream);
|
||||
String base64Image = EncodesUtil.encodeBase64(bytes);
|
||||
FileVO fileVO = BeanConv.toBean(file, FileVO.class);
|
||||
fileVO.setBase64Image(base64Image);
|
||||
return fileVO;
|
||||
} catch (Exception e) {
|
||||
log.error("文件下载传异常:{}", ExceptionsUtil.getStackTraceAsString(e));
|
||||
throw new ProjectException(FileEnum.DOWNLOAD_FAIL);
|
||||
}
|
||||
}
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
package com.itheima.sfbx.file.utils;
|
||||
|
||||
import com.itheima.sfbx.file.handler.aliyun.properties.OssAliyunConfigProperties;
|
||||
import com.itheima.sfbx.file.handler.qiniu.properties.QiniuProperties;
|
||||
import com.itheima.sfbx.framework.commons.constant.file.FileConstant;
|
||||
import com.itheima.sfbx.framework.commons.enums.file.FileEnum;
|
||||
import com.itheima.sfbx.framework.commons.exception.ProjectException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 获得资源文件完整路径地址上下文对象
|
||||
* 如果添加了新的对象存储资源,需要在此类中对 initMap 方法添加新的路径前缀
|
||||
* </p>
|
||||
*
|
||||
* @Description:
|
||||
*/
|
||||
@Component
|
||||
public class FileUrlContext {
|
||||
|
||||
@Autowired
|
||||
private OssAliyunConfigProperties ossAliyunConfigProperties;
|
||||
|
||||
@Autowired
|
||||
private QiniuProperties qiniuProperties;
|
||||
|
||||
private static Map<String,String> fileStoreUrlHandler =new HashMap<>();
|
||||
|
||||
@PostConstruct
|
||||
public void initMap() {
|
||||
// 初始化各个对象存储的文件访问路径地址
|
||||
String ossPrefixUrl = "https://" + ossAliyunConfigProperties.getBucketName() + "." +
|
||||
ossAliyunConfigProperties.getEndpoint() + "/";
|
||||
String kodoPrefixUrl = "http://" + qiniuProperties.getKodo().getEndpoint() + "/";
|
||||
|
||||
fileStoreUrlHandler.put(FileConstant.ALIYUN_OSS,ossPrefixUrl);
|
||||
fileStoreUrlHandler.put(FileConstant.QINIU_KODO,kodoPrefixUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得资源文件的访问地址
|
||||
* @param storeFlag String 对象存储标识
|
||||
* @param pathUrl String 相对路径
|
||||
* @return String 资源文件对应的完整路径地址
|
||||
*/
|
||||
public String getFileUrl(String storeFlag, String pathUrl) {
|
||||
String prefix = fileStoreUrlHandler.get(storeFlag);
|
||||
if (StringUtils.isEmpty(prefix)) {
|
||||
throw new ProjectException(FileEnum.FILE_PREFIX_NOT_FOUND);
|
||||
}
|
||||
return prefix + pathUrl;
|
||||
}
|
||||
|
||||
}
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
package com.itheima.sfbx.file.web;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
|
||||
import com.itheima.sfbx.file.service.IFileService;
|
||||
import com.itheima.sfbx.framework.commons.basic.ResponseResult;
|
||||
import com.itheima.sfbx.framework.commons.dto.file.FileVO;
|
||||
import com.itheima.sfbx.framework.commons.utils.ResponseResultBuild;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @ClassName FileController.java
|
||||
* @Description 附件展示维护controller
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("file")
|
||||
@Api(tags = "附件controller")
|
||||
@Slf4j
|
||||
public class FileBusinessController {
|
||||
|
||||
@Autowired
|
||||
IFileService fileService;
|
||||
|
||||
/***
|
||||
* @description 附件分页列表
|
||||
* @param fileVO 查询条件
|
||||
* @param pageNum 页码
|
||||
* @param pageSize 每页条数
|
||||
* @return: Page<FileVO>
|
||||
*/
|
||||
@PostMapping("page/{pageNum}/{pageSize}")
|
||||
@ApiOperation(value = "查询附件分页",notes = "查询附件分页")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "fileVO",value = "附件查询对象",required = false,dataType = "FileVO"),
|
||||
@ApiImplicitParam(paramType = "path",name = "pageNum",value = "页码",example = "1",dataType = "Integer"),
|
||||
@ApiImplicitParam(paramType = "path",name = "pageSize",value = "每页条数",example = "10",dataType = "Integer")
|
||||
})
|
||||
@ApiOperationSupport(includeParameters ={"fileVO.businessType","","fileVO.pathUrl",
|
||||
"fileVO.dataState","fileVO.status"} )
|
||||
public ResponseResult<Page<FileVO>> findFileVOPage(
|
||||
@RequestBody FileVO fileVO,
|
||||
@PathVariable("pageNum") int pageNum,
|
||||
@PathVariable("pageSize") int pageSize) {
|
||||
//查询附件分页信息
|
||||
Page<FileVO> fileVOPage = fileService.findFileVOPage(fileVO, pageNum, pageSize);
|
||||
return ResponseResultBuild.successBuild(fileVOPage);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Description 移除业务原图片,并批量绑定新的图片到业务上
|
||||
* @param fileVOs 附件对象
|
||||
* @return
|
||||
*/
|
||||
@PutMapping(value = "replace-bind-batch-file")
|
||||
@ApiOperation(value = "移除业务原图片,并绑定新的图片到业务上",notes = "移除业务原图片,并绑定新的图片到业务上")
|
||||
@ApiImplicitParam(name = "fileVOs",value = "附件对象",required = true,dataType = "FileVO")
|
||||
public ResponseResult<Boolean> replaceBindBatchFile(@RequestBody List<FileVO> fileVOs){
|
||||
Boolean flag = fileService.replaceBindBatchFile(fileVOs);
|
||||
return ResponseResultBuild.successBuild(flag);
|
||||
}
|
||||
}
|
||||
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
package com.itheima.sfbx.file.web;
|
||||
|
||||
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
|
||||
import com.itheima.sfbx.file.service.IFileService;
|
||||
import com.itheima.sfbx.framework.commons.basic.ResponseResult;
|
||||
import com.itheima.sfbx.framework.commons.dto.file.FileVO;
|
||||
import com.itheima.sfbx.framework.commons.dto.file.FilePartVO;
|
||||
import com.itheima.sfbx.framework.commons.dto.file.UploadMultipartFile;
|
||||
import com.itheima.sfbx.framework.commons.utils.ResponseResultBuild;
|
||||
import com.itheima.sfbx.framework.commons.utils.SubjectContent;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @ClassName FileUpLoadController.java
|
||||
* @Description 文件上传接口
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("file")
|
||||
@Api(tags = "附件controller")
|
||||
@Slf4j
|
||||
public class FileUpLoadController {
|
||||
|
||||
@Autowired
|
||||
IFileService fileService;
|
||||
|
||||
/***
|
||||
* @description 文件上传-简单上传-前端直接调用
|
||||
* @param file 上传对象
|
||||
* @return: com.itheima.travel.req.FileVO
|
||||
*/
|
||||
@PostMapping(value = "up-load")
|
||||
@ApiOperation(value = "文件上传-简单上传",notes = "文件上传-简单上传")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(paramType = "form", name = "file", value = "文件对象", required = true, dataTypeClass = MultipartFile.class)
|
||||
})
|
||||
@ApiOperationSupport(includeParameters = {"fileVO.businessType","fileVO.bucketName","fileVO.storeFlag","fileVO.autoCatalog"})
|
||||
public ResponseResult<FileVO> upLoad(
|
||||
@RequestParam("file") MultipartFile file,
|
||||
FileVO fileVO) throws IOException {
|
||||
fileVO.setCompanyNo(SubjectContent.getCompanyNo());
|
||||
//构建文件上传对象
|
||||
UploadMultipartFile uploadMultipartFile = UploadMultipartFile
|
||||
.builder()
|
||||
.originalFilename(file.getOriginalFilename())
|
||||
.fileByte(IOUtils.toByteArray(file.getInputStream()))
|
||||
.build();
|
||||
//执行文件上传
|
||||
FileVO fileVOResult = fileService.upLoad(uploadMultipartFile, fileVO);
|
||||
return ResponseResultBuild.successBuild(fileVOResult);
|
||||
|
||||
}
|
||||
|
||||
@PostMapping(value = "initiate-multipart-up-load")
|
||||
@ApiOperation(value = "文件分片上传-初始化",notes = "文件分片上传-初始化")
|
||||
@ApiImplicitParam(name = "fileVO",value = "文件对象",required = true,dataType = "FileVO")
|
||||
public ResponseResult<FileVO> initiateMultipartUpload(
|
||||
@RequestBody FileVO fileVO){
|
||||
fileVO.setCompanyNo(SubjectContent.getCompanyNo());
|
||||
//初始化上传Id
|
||||
FileVO fileVOResult = fileService.initiateMultipartUpload(fileVO);
|
||||
return ResponseResultBuild.successBuild(fileVOResult);
|
||||
}
|
||||
|
||||
@PostMapping(value = "up-load-part")
|
||||
@ApiOperation(value = "文件分片上传-上传分片",notes = "文件分片上传-上传分片")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(paramType = "form", name = "file", value = "文件对象", required = true, dataTypeClass = MultipartFile.class)
|
||||
})
|
||||
public ResponseResult<String> uploadPart(
|
||||
@RequestParam("file") MultipartFile file,
|
||||
FilePartVO filePartVO)throws IOException {
|
||||
filePartVO.setCompanyNo(SubjectContent.getCompanyNo());
|
||||
//构建文件上次对象
|
||||
UploadMultipartFile uploadMultipartFile = UploadMultipartFile
|
||||
.builder()
|
||||
.originalFilename(file.getOriginalFilename())
|
||||
.fileByte(IOUtils.toByteArray(file.getInputStream()))
|
||||
.build();
|
||||
//上传分片返回partETagJson
|
||||
String partETagJson = fileService.uploadPart(uploadMultipartFile,filePartVO);
|
||||
return ResponseResultBuild.successBuild(partETagJson);
|
||||
}
|
||||
|
||||
@PostMapping(value = "complete-multipart-up-load")
|
||||
@ApiOperation(value = "文件分片上传-合并分片",notes = "文件分片上传-合并分片")
|
||||
@ApiImplicitParam(name = "fileVO",value = "文件对象",required = true,dataType = "FileVO")
|
||||
public ResponseResult<String> completeMultipartUpload(
|
||||
@RequestBody FileVO fileVO)throws IOException {
|
||||
//问上传分片返回partETagJson
|
||||
String eTagJson = fileService.completeMultipartUpload(fileVO);
|
||||
return ResponseResultBuild.successBuild(eTagJson);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
_ __ __
|
||||
(_) /__________ ______/ /_
|
||||
/ / __/ ___/ __ `/ ___/ __/
|
||||
/ / /_/ /__/ /_/ (__ ) /_
|
||||
/_/\__/\___/\__,_/____/\__/
|
||||
:: Spring Boot :: (v-2.7.10)
|
||||
:: Spring Cloud :: (v-2021.0.6)
|
||||
:: Spring Cloud Alibaba :: (v-2021.0.1.0)
|
||||
:: sfbx Cloud :: (v-2.0-SNAPSHOT)
|
||||
:: 献给可爱的传智人 ::
|
||||
@@ -0,0 +1,54 @@
|
||||
#服务配置
|
||||
server:
|
||||
#端口
|
||||
port: 7075
|
||||
#服务编码
|
||||
tomcat:
|
||||
uri-encoding: UTF-8
|
||||
spring:
|
||||
config:
|
||||
activate:
|
||||
on-profile:
|
||||
- test
|
||||
main:
|
||||
allow-circular-references: true
|
||||
allow-bean-definition-overriding: true
|
||||
mvc:
|
||||
pathmatch:
|
||||
matching-strategy: ant_path_matcher
|
||||
#应用配置
|
||||
application:
|
||||
#应用名称
|
||||
name: file-web
|
||||
cloud:
|
||||
nacos:
|
||||
discovery:
|
||||
server-addr: ${NACOS_ADDRESS:nacos-service.yjy-public-sfbx-java.svc.cluster.local:20015} # nacos注册中心
|
||||
group: SEATA_GROUP
|
||||
service: ${spring.application.name}
|
||||
username: ${NACOS_USERNAME:nacos}
|
||||
password: ${NACOS_PASSWORD:PKsf*bxQ4;yP3a+}
|
||||
config:
|
||||
server-addr: ${NACOS_ADDRESS:nacos-service.yjy-public-sfbx-java.svc.cluster.local:20015} # nacos注册中心
|
||||
group: SEATA_GROUP
|
||||
file-extension: yml
|
||||
shared-configs: # 共享配置
|
||||
- data-id: shared-spring-seata.yml #配置文件名-DataId
|
||||
group: SEATA_GROUP
|
||||
refresh: false
|
||||
- data-id: shared-redisson.yml #配置文件名-DataId
|
||||
group: SEATA_GROUP
|
||||
refresh: false
|
||||
- data-id: shared-mybatis-plus.yml #配置文件名-DataId
|
||||
group: SEATA_GROUP
|
||||
refresh: false
|
||||
- data-id: shared-stream-rabbit-basic.yml #配置文件名-DataId
|
||||
group: SEATA_GROUP
|
||||
refresh: false
|
||||
- data-id: shared-stream-rabbit-source-file.yml #配置文件名-DataId
|
||||
group: SEATA_GROUP
|
||||
refresh: false
|
||||
username: ${NACOS_USERNAME:nacos}
|
||||
password: ${NACOS_PASSWORD:PKsf*bxQ4;yP3a+}
|
||||
logging:
|
||||
config: classpath:logback.xml
|
||||
@@ -0,0 +1,53 @@
|
||||
#服务配置
|
||||
server:
|
||||
#端口
|
||||
port: 7075
|
||||
#服务编码
|
||||
tomcat:
|
||||
uri-encoding: UTF-8
|
||||
spring:
|
||||
servlet:
|
||||
multipart:
|
||||
enabled: true
|
||||
max-file-size: 10MB
|
||||
max-request-size: 20MB
|
||||
profiles:
|
||||
active: dev
|
||||
main:
|
||||
allow-circular-references: true
|
||||
allow-bean-definition-overriding: true
|
||||
mvc:
|
||||
pathmatch:
|
||||
matching-strategy: ant_path_matcher
|
||||
#应用配置
|
||||
application:
|
||||
#应用名称
|
||||
name: file-web
|
||||
cloud:
|
||||
nacos:
|
||||
discovery:
|
||||
server-addr: 192.168.12.129:8848 # nacos注册中心
|
||||
group: SEATA_GROUP
|
||||
service: ${spring.application.name}
|
||||
config:
|
||||
server-addr: 192.168.12.129:8848 # nacos配置中心地址
|
||||
group: SEATA_GROUP
|
||||
file-extension: yml
|
||||
shared-configs: # 共享配置
|
||||
- data-id: shared-spring-seata.yml #配置文件名-DataId
|
||||
group: SEATA_GROUP
|
||||
refresh: false
|
||||
- data-id: shared-redisson.yml #配置文件名-DataId
|
||||
group: SEATA_GROUP
|
||||
refresh: false
|
||||
- data-id: shared-mybatis-plus.yml #配置文件名-DataId
|
||||
group: SEATA_GROUP
|
||||
refresh: false
|
||||
- data-id: shared-stream-rabbit-basic.yml #配置文件名-DataId
|
||||
group: SEATA_GROUP
|
||||
refresh: false
|
||||
- data-id: shared-stream-rabbit-source-file.yml #配置文件名-DataId
|
||||
group: SEATA_GROUP
|
||||
refresh: false
|
||||
logging:
|
||||
config: classpath:logback.xml
|
||||
@@ -0,0 +1,47 @@
|
||||
#\u6570\u636E\u5E93\u5730\u5740
|
||||
url=jdbc:mysql://192.168.12.129:3306/restkeeper-file?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&tinyInt1isBit=false
|
||||
#\u6570\u636E\u5E93\u8D26\u53F7
|
||||
userName=root
|
||||
#\u6570\u636E\u5E93\u5BC6\u7801
|
||||
password=pass
|
||||
#services\u7684src\u8DEF\u5F84
|
||||
serviceProjectPath=E:/itheima-project-parent/itheima-project-cloud/itheima-module-file/module-file-web
|
||||
#VO\u7684src\u8DEF\u5F84
|
||||
voProjectPath=E:/itheima-project-parent/itheima-project-cloud/itheima-component/component-vo
|
||||
#\u4F5C\u8005
|
||||
author=Admin
|
||||
#\u5305\u540D\u79F0
|
||||
parent=com.itheima
|
||||
#\u6A21\u5757\u540D\u79F0
|
||||
moduleName=project
|
||||
#\u6570\u636E\u5E93\u8868\u524D\u7F00
|
||||
tablePrefix =tab_
|
||||
#\u9700\u8981\u751F\u6210\u7684\u8868\u540D\uFF0C\u4F7F\u7528\uFF0C\u5206\u5272
|
||||
tableName= tab_file_part
|
||||
#\u9700\u8981\u751F\u6210\u9644\u4EF6\u76F8\u5173\u7684\u8868
|
||||
tablesFile=
|
||||
#pojo\u7684\u7236\u7C7B
|
||||
SuperEntityClass = com.itheima.easy.basic.BasicPojo
|
||||
#pojo\u7684\u901A\u7528\u5B57\u6BB5
|
||||
superEntityColumns = id,created_time,updated_time,sharding_id,enable_flag
|
||||
#\u751F\u6210\u89C4\u5219
|
||||
constant=true
|
||||
constant.ftl.path=/templates/constant.java
|
||||
enums=true
|
||||
enums.ftl.path=/templates/enums.java
|
||||
vo=true
|
||||
vo.ftl.path=/templates/vo.java
|
||||
entity=true
|
||||
entity.ftl.path=/templates/entity.java
|
||||
mapper=true
|
||||
mapper.ftl.path=/templates/mapper.java
|
||||
service=true
|
||||
service.ftl.path=/templates/service.java
|
||||
serviceImpl=true
|
||||
serviceImpl.ftl.path=/templates/serviceImpl.java
|
||||
face=false
|
||||
face.ftl.path=/templates/face.java
|
||||
faceImpl=false
|
||||
faceImpl.ftl.path=/templates/faceImpl.java
|
||||
controller=false
|
||||
controller.ftl.path=/templates/controller.java
|
||||
@@ -0,0 +1,53 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration debug="false">
|
||||
<!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径 -->
|
||||
<property name="LOG_HOME" value="/data/logs/file-web" />
|
||||
<!-- 控制台输出 -->
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
|
||||
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 -->
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}-%msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
<!-- 按照每天生成日志文件 -->
|
||||
<appender name="FILE"
|
||||
class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<!--日志文件输出的文件名 -->
|
||||
<FileNamePattern>${LOG_HOME}/file-web-01.log.%d{yyyy-MM-dd}.log
|
||||
</FileNamePattern>
|
||||
<!--日志文件保留天数 -->
|
||||
<MaxHistory>30</MaxHistory>
|
||||
</rollingPolicy>
|
||||
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
|
||||
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 -->
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}-%msg%n</pattern>
|
||||
</encoder>
|
||||
<!--日志文件最大的大小 -->
|
||||
<triggeringPolicy
|
||||
class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
|
||||
<MaxFileSize>10MB</MaxFileSize>
|
||||
</triggeringPolicy>
|
||||
</appender>
|
||||
<!-- show parameters for hibernate sql 专为 Hibernate 定制 -->
|
||||
<logger name="org.hibernate.type.descriptor.sql.BasicBinder"
|
||||
level="TRACE" />
|
||||
<logger name="org.hibernate.type.descriptor.sql.BasicExtractor"
|
||||
level="DEBUG" />
|
||||
<logger name="org.hibernate.SQL" level="DEBUG" />
|
||||
<logger name="org.hibernate.engine.QueryParameters" level="DEBUG" />
|
||||
<logger name="org.hibernate.engine.query.HQLQueryPlan" level="DEBUG" />
|
||||
|
||||
<!--myibatis log configure -->
|
||||
<logger name="com.apache.ibatis" level="TRACE" />
|
||||
<logger name="java.sql.Connection" level="DEBUG" />
|
||||
<logger name="java.sql.Statement" level="DEBUG" />
|
||||
<logger name="java.sql.PreparedStatement" level="DEBUG" />
|
||||
|
||||
<!-- 日志输出级别 -->
|
||||
<root level="INFO">
|
||||
<appender-ref ref="STDOUT" />
|
||||
<appender-ref ref="FILE" />
|
||||
</root>
|
||||
<!--日志异步到数据库 -->
|
||||
</configuration>
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.itheima.easy.constant;
|
||||
|
||||
/**
|
||||
* @Description:${table.comment!}缓存常量
|
||||
*/
|
||||
public class ${entity}CacheConstant extends CacheConstant {
|
||||
|
||||
//缓存父包
|
||||
public static final String PREFIX= "${controllerMappingHyphen}:";
|
||||
|
||||
//缓存父包
|
||||
public static final String BASIC= PREFIX+"basic";
|
||||
|
||||
//分布式锁前缀
|
||||
public static final String LOCK_PREFIX = PREFIX+"lock:";
|
||||
|
||||
//page分页
|
||||
public static final String PAGE= PREFIX+"page";
|
||||
|
||||
//list下拉框
|
||||
public static final String LIST= PREFIX+"list";
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
package ${package.Controller};
|
||||
|
||||
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.itheima.sfbx.framework.commons.basic.ResponseResult;
|
||||
import com.itheima.sfbx.framework.commons.enums.trade.${entity}Enum;
|
||||
import com.itheima.easy.face.${entity}Face;
|
||||
import com.itheima.sfbx.framework.commons.utils.ResponseResultBuild;
|
||||
import com.itheima.sfbx.framework.commons.dto.trade.${entity}Vo;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
<#if restControllerStyle>
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
<#else>
|
||||
import org.springframework.stereotype.Controller;
|
||||
</#if>
|
||||
<#if superControllerClassPackage??>
|
||||
import ${superControllerClassPackage};
|
||||
</#if>
|
||||
|
||||
/**
|
||||
* @Description:${table.comment!}前端控制器
|
||||
*/
|
||||
@Slf4j
|
||||
@Api(tags = "${table.comment!}controller")
|
||||
<#if restControllerStyle>
|
||||
@RestController
|
||||
<#else>
|
||||
@Controller
|
||||
</#if>
|
||||
@RequestMapping("<#if controllerMappingHyphenStyle??>${controllerMappingHyphen}<#else>${table.entityPath}</#if>")
|
||||
<#if kotlin>
|
||||
class ${table.controllerName}<#if superControllerClass??> : ${superControllerClass}()</#if>
|
||||
<#else>
|
||||
<#if superControllerClass??>
|
||||
public class ${table.controllerName} extends ${superControllerClass} {
|
||||
<#else>
|
||||
public class ${table.controllerName} {
|
||||
</#if>
|
||||
|
||||
@Autowired
|
||||
${entity}Face ${entity?uncap_first}Face;
|
||||
|
||||
/***
|
||||
* @description 多条件查询${table.comment!}分页列表
|
||||
* @param ${entity?uncap_first}Vo ${table.comment!}Vo查询条件
|
||||
* @param pageNum 页码
|
||||
* @param pageSize 每页条数
|
||||
* @return: Page<${entity}Vo>
|
||||
*/
|
||||
@PostMapping("page/{pageNum}/{pageSize}")
|
||||
@ApiOperation(value = "${table.comment!}分页",notes = "${table.comment!}分页")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "${entity?uncap_first}Vo",value = "${table.comment!}Vo对象",required = true,dataType = "${entity}Vo"),
|
||||
@ApiImplicitParam(paramType = "path",name = "pageNum",value = "页码",example = "1",dataType = "Integer"),
|
||||
@ApiImplicitParam(paramType = "path",name = "pageSize",value = "每页条数",example = "10",dataType = "Integer")
|
||||
})
|
||||
public ResponseResult<Page<${entity}Vo>> find${entity}VoPage(
|
||||
@RequestBody ${entity}Vo ${entity?uncap_first}Vo,
|
||||
@PathVariable("pageNum") int pageNum,
|
||||
@PathVariable("pageSize") int pageSize) {
|
||||
Page<${entity}Vo> ${entity?uncap_first}VoPage = ${entity?uncap_first}Face.find${entity}VoPage(${entity?uncap_first}Vo, pageNum, pageSize);
|
||||
return ResponseResultBuild.build(${entity}Enum.SUCCEED,${entity?uncap_first}VoPage);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Description 保存${table.comment!}
|
||||
* @param ${entity?uncap_first}Vo ${table.comment!}Vo对象
|
||||
* @return ${entity}Vo
|
||||
*/
|
||||
@PutMapping
|
||||
@ApiOperation(value = "添加${entity}",notes = "添加${entity}")
|
||||
@ApiImplicitParam(name = "${entity?uncap_first}Vo",value = "${table.comment!}Vo对象",required = true,dataType = "${entity}Vo")
|
||||
public ResponseResult<${entity}Vo> create${entity}(@RequestBody ${entity}Vo ${entity?uncap_first}Vo) {
|
||||
${entity}Vo ${entity?uncap_first}VoResult = ${entity?uncap_first}Face.create${entity}Vo(${entity?uncap_first}Vo);
|
||||
return ResponseResultBuild.build(${entity}Enum.SUCCEED,${entity?uncap_first}VoResult);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Description 修改${table.comment!}
|
||||
* @param ${entity?uncap_first}Vo ${table.comment!}Vo对象
|
||||
* @return Boolean 是否修改成功
|
||||
*/
|
||||
@PatchMapping
|
||||
@ApiOperation(value = "修改${table.comment!}",notes = "修改${table.comment!}")
|
||||
@ApiImplicitParam(name = "${entity?uncap_first}Vo",value = "${table.comment!}Vo对象",required = true,dataType = "${entity}Vo")
|
||||
public ResponseResult<Boolean> update${entity}(@RequestBody ${entity}Vo ${entity?uncap_first}Vo) {
|
||||
Boolean flag = ${entity?uncap_first}Face.update${entity}Vo(${entity?uncap_first}Vo);
|
||||
return ResponseResultBuild.build(${entity}Enum.SUCCEED,flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Description 删除${table.comment!}
|
||||
* @param ${entity?uncap_first}Vo 刪除条件:checkedIds 不可为空
|
||||
* @return
|
||||
*/
|
||||
@DeleteMapping
|
||||
@ApiOperation(value = "删除${table.comment!}",notes = "删除${table.comment!}")
|
||||
@ApiImplicitParam(name = "${entity?uncap_first}Vo",value = "${table.comment!}Vo对象",required = true,dataType = "${entity}Vo")
|
||||
public ResponseResult<Boolean> delete${entity}(@RequestBody ${entity}Vo ${entity?uncap_first}Vo) {
|
||||
Boolean flag = ${entity?uncap_first}Face.delete${entity}Vo(${entity?uncap_first}Vo.getCheckedIds());
|
||||
return ResponseResultBuild.build(${entity}Enum.SUCCEED,flag);
|
||||
}
|
||||
|
||||
/***
|
||||
* @description 多条件查询${table.comment!}列表
|
||||
* @param ${entity?uncap_first}Vo ${table.comment!}Vo对象
|
||||
* @return List<${entity}Vo>
|
||||
*/
|
||||
@PostMapping("list")
|
||||
@ApiOperation(value = "多条件查询${table.comment!}列表",notes = "多条件查询${table.comment!}列表")
|
||||
@ApiImplicitParam(name = "${entity?uncap_first}Vo",value = "${table.comment!}Vo对象",required = true,dataType = "${entity}Vo")
|
||||
public ResponseResult<List<${entity}Vo>> ${entity?uncap_first}List(@RequestBody ${entity}Vo ${entity?uncap_first}Vo) {
|
||||
List<${entity}Vo> ${entity?uncap_first}VoList = ${entity?uncap_first}Face.find${entity}VoList(${entity?uncap_first}Vo);
|
||||
return ResponseResultBuild.build(${entity}Enum.SUCCEED,${entity?uncap_first}VoList);
|
||||
}
|
||||
|
||||
}
|
||||
</#if>
|
||||
@@ -0,0 +1,156 @@
|
||||
package ${package.Entity};
|
||||
|
||||
<#list table.importPackages as pkg>
|
||||
import ${pkg};
|
||||
</#list>
|
||||
<#if swagger2>
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
</#if>
|
||||
<#if entityLombokModel>
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.EqualsAndHashCode;
|
||||
</#if>
|
||||
|
||||
/**
|
||||
* @Description:${table.comment!}
|
||||
*/
|
||||
<#if entityLombokModel>
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
<#if superEntityClass??>
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
<#else>
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
</#if>
|
||||
</#if>
|
||||
<#if table.convert>
|
||||
@TableName("${table.name}")
|
||||
</#if>
|
||||
<#if swagger2>
|
||||
@ApiModel(value="${entity}对象", description="${table.comment!}")
|
||||
</#if>
|
||||
<#if superEntityClass??>
|
||||
public class ${entity} extends ${superEntityClass}<#if activeRecord><${entity}></#if> {
|
||||
<#elseif activeRecord>
|
||||
public class ${entity} extends Model<${entity}> {
|
||||
<#else>
|
||||
public class ${entity} implements Serializable {
|
||||
</#if>
|
||||
|
||||
<#if entitySerialVersionUID>
|
||||
private static final long serialVersionUID = 1L;
|
||||
</#if>
|
||||
|
||||
@Builder
|
||||
public ${entity}(Long id,<#list table.fields as field>${field.propertyType} ${field.propertyName}<#if field_has_next>,</#if></#list>){
|
||||
super(id);
|
||||
<#list table.fields as field>
|
||||
this.${field.propertyName}=${field.propertyName};
|
||||
</#list>
|
||||
}
|
||||
<#-- ---------- BEGIN 字段循环遍历 ---------->
|
||||
<#list table.fields as field>
|
||||
<#if field.keyFlag>
|
||||
<#assign keyPropertyName="${field.propertyName}"/>
|
||||
</#if>
|
||||
|
||||
<#if field.comment!?length gt 0>
|
||||
<#if swagger2>
|
||||
@ApiModelProperty(value = "${field.comment}")
|
||||
<#else>
|
||||
/**
|
||||
* ${field.comment}
|
||||
*/
|
||||
</#if>
|
||||
</#if>
|
||||
<#if field.keyFlag>
|
||||
<#-- 主键 -->
|
||||
<#if field.keyIdentityFlag>
|
||||
@TableId(value = "${field.name}", type = IdType.AUTO)
|
||||
<#elseif idType??>
|
||||
@TableId(value = "${field.name}", type = IdType.${idType})
|
||||
<#elseif field.convert>
|
||||
@TableId("${field.name}")
|
||||
</#if>
|
||||
<#-- 普通字段 -->
|
||||
<#elseif field.fill??>
|
||||
<#-- ----- 存在字段填充设置 ----->
|
||||
<#if field.convert>
|
||||
@TableField(value = "${field.name}", fill = FieldFill.${field.fill})
|
||||
<#else>
|
||||
@TableField(fill = FieldFill.${field.fill})
|
||||
</#if>
|
||||
<#elseif field.convert>
|
||||
@TableField("${field.name}")
|
||||
</#if>
|
||||
<#-- 乐观锁注解 -->
|
||||
<#if (versionFieldName!"") == field.name>
|
||||
@Version
|
||||
</#if>
|
||||
<#-- 逻辑删除注解 -->
|
||||
<#if (logicDeleteFieldName!"") == field.name>
|
||||
@TableLogic
|
||||
</#if>
|
||||
private ${field.propertyType} ${field.propertyName};
|
||||
</#list>
|
||||
<#------------ END 字段循环遍历 ---------->
|
||||
|
||||
<#if !entityLombokModel>
|
||||
<#list table.fields as field>
|
||||
<#if field.propertyType == "boolean">
|
||||
<#assign getprefix="is"/>
|
||||
<#else>
|
||||
<#assign getprefix="get"/>
|
||||
</#if>
|
||||
public ${field.propertyType} ${getprefix}${field.capitalName}() {
|
||||
return ${field.propertyName};
|
||||
}
|
||||
|
||||
<#if entityBuilderModel>
|
||||
public ${entity} set${field.capitalName}(${field.propertyType} ${field.propertyName}) {
|
||||
<#else>
|
||||
public void set${field.capitalName}(${field.propertyType} ${field.propertyName}) {
|
||||
</#if>
|
||||
this.${field.propertyName} = ${field.propertyName};
|
||||
<#if entityBuilderModel>
|
||||
return this;
|
||||
</#if>
|
||||
}
|
||||
</#list>
|
||||
</#if>
|
||||
|
||||
<#if entityColumnConstant>
|
||||
<#list table.fields as field>
|
||||
public static final String ${field.name?upper_case} = "${field.name}";
|
||||
|
||||
</#list>
|
||||
</#if>
|
||||
<#if activeRecord>
|
||||
@Override
|
||||
protected Serializable pkVal() {
|
||||
<#if keyPropertyName??>
|
||||
return this.${keyPropertyName};
|
||||
<#else>
|
||||
return null;
|
||||
</#if>
|
||||
}
|
||||
|
||||
</#if>
|
||||
<#if !entityLombokModel>
|
||||
@Override
|
||||
public String toString() {
|
||||
return "${entity}{" +
|
||||
<#list table.fields as field>
|
||||
<#if field_index==0>
|
||||
"${field.propertyName}=" + ${field.propertyName} +
|
||||
<#else>
|
||||
", ${field.propertyName}=" + ${field.propertyName} +
|
||||
</#if>
|
||||
</#list>
|
||||
"}";
|
||||
}
|
||||
</#if>
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.itheima.easy.enums;
|
||||
|
||||
import com.itheima.easy.basic.IBasicEnum;
|
||||
|
||||
/**
|
||||
* @ClassName ${entity}Enum.java
|
||||
* @Description ${table.comment!}枚举
|
||||
*/
|
||||
|
||||
public enum ${entity}Enum implements IBasicEnum {
|
||||
|
||||
SUCCEED("200","操作成功"),
|
||||
FAIL("1000","操作失败"),
|
||||
PAGE_FAIL("53001", "查询${table.comment!}列表失败"),
|
||||
SAVE_FAIL("53002", "保存${table.comment!}失败"),
|
||||
UPDATE_FAIL("53003", "修改${table.comment!}失败"),
|
||||
DEL_FAIL("53004", "删除${table.comment!}失败"),
|
||||
LIST_FAIL("53005", "查询${table.comment!}失败")
|
||||
;
|
||||
|
||||
private String code;
|
||||
|
||||
private String msg;
|
||||
|
||||
${entity}Enum(String code, String msg) {
|
||||
this.code = code;
|
||||
this.msg = msg;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getMsg() {
|
||||
return msg;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.itheima.easy.face;
|
||||
|
||||
import com.itheima.sfbx.framework.commons.dto.trade.${entity}Vo;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Description:${table.comment!}Face服务类
|
||||
*/
|
||||
<#if kotlin>
|
||||
interface ${entity}Face
|
||||
<#else>
|
||||
public interface ${entity}Face {
|
||||
|
||||
/**
|
||||
* @Description 多条件查询${table.comment!}分页列表
|
||||
* @param ${entity?uncap_first}Vo 查询条件
|
||||
* @param pageNum 页码
|
||||
* @param pageSize 每页条数
|
||||
* @return Page<${entity}>
|
||||
*/
|
||||
Page<${entity}Vo> find${entity}VoPage(${entity}Vo ${entity?uncap_first}Vo, int pageNum, int pageSize);
|
||||
|
||||
/**
|
||||
* @Description 创建${table.comment!}
|
||||
* @param ${entity?uncap_first}Vo 对象信息
|
||||
* @return ${entity}
|
||||
*/
|
||||
${entity}Vo create${entity}Vo(${entity}Vo ${entity?uncap_first}Vo);
|
||||
|
||||
/**
|
||||
* @Description 修改${table.comment!}
|
||||
* @param ${entity?uncap_first}Vo 对象信息
|
||||
* @return Boolean
|
||||
*/
|
||||
Boolean update${entity}Vo(${entity}Vo ${entity?uncap_first}Vo);
|
||||
|
||||
/**
|
||||
* @Description 删除${table.comment!}
|
||||
* @param checkedIds 选择中对象Ids
|
||||
* @return Boolean
|
||||
*/
|
||||
Boolean delete${entity}Vo(String[] checkedIds);
|
||||
|
||||
/**
|
||||
* @description 多条件查询${table.comment!}列表
|
||||
* @param ${entity?uncap_first}Vo 查询条件
|
||||
* @return: List<${entity}>
|
||||
*/
|
||||
List<${entity}Vo> find${entity}VoList(${entity}Vo ${entity?uncap_first}Vo);
|
||||
}
|
||||
</#if>
|
||||
@@ -0,0 +1,188 @@
|
||||
package com.itheima.easy.face.impl;
|
||||
|
||||
import ${package.Entity}.${entity};
|
||||
import ${package.Service}.${table.serviceName};
|
||||
import com.itheima.sfbx.framework.commons.dto.trade.${entity}Vo;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.itheima.sfbx.framework.commons.utils.BeanConv;
|
||||
import com.itheima.easy.face.${entity}Face;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.CachePut;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.cache.annotation.Caching;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
import com.itheima.sfbx.framework.commons.utils.ExceptionsUtil;
|
||||
import com.itheima.sfbx.framework.commons.exception.ProjectException;
|
||||
import com.itheima.sfbx.framework.commons.constant.trade.${entity}CacheConstant;
|
||||
import com.itheima.sfbx.framework.commons.enums.trade.${entity}Enum;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
<#list cfg.tablesFile as tableFiile>
|
||||
<#if tableFiile==table.name>
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import com.itheima.sfbx.framework.commons.dto.file.FileVO;
|
||||
import com.itheima.sfbx.framework.commons.utils.EmptyUtil;
|
||||
import com.itheima.sfbx.framework.commons.basic.ResponseResult;
|
||||
import com.itheima.easy.feign.FileFeign;
|
||||
</#if>
|
||||
</#list>
|
||||
import java.util.List;
|
||||
/**
|
||||
* @Description:${table.comment!}Face服务实现类
|
||||
*/
|
||||
<#if kotlin>
|
||||
open class ${entity}FaceImpl : ${entity}Face {
|
||||
|
||||
}
|
||||
<#else>
|
||||
@Slf4j
|
||||
@Component
|
||||
public class ${entity}FaceImpl implements ${entity}Face {
|
||||
|
||||
@Autowired
|
||||
I${entity}Service ${entity?uncap_first}Service;
|
||||
|
||||
<#list cfg.tablesFile as tableFiile>
|
||||
<#if tableFiile==table.name>
|
||||
@Autowired
|
||||
FileFeign fileFeign;
|
||||
</#if>
|
||||
</#list>
|
||||
|
||||
@Override
|
||||
@Cacheable(value = ${entity}CacheConstant.PAGE,key ="#pageNum+'-'+#pageSize+'-'+#${entity?uncap_first}Vo.hashCode()")
|
||||
public Page<${entity}Vo> find${entity}VoPage(${entity}Vo ${entity?uncap_first}Vo, int pageNum, int pageSize) {
|
||||
try {
|
||||
Page<${entity}> page = ${entity?uncap_first}Service.find${entity}Page(${entity?uncap_first}Vo, pageNum, pageSize);
|
||||
Page<${entity}Vo> pageVo =BeanConv.toPage(page,${entity}Vo.class);
|
||||
<#list cfg.tablesFile as tableFiile>
|
||||
<#if tableFiile==table.name>
|
||||
//查询记录结果
|
||||
List<${entity}Vo> records = pageVo.getRecords();
|
||||
//处理图片
|
||||
if (!EmptyUtil.isNullOrEmpty(records)){
|
||||
records.forEach(n->{
|
||||
ResponseResult<List<FileVO>> responseWrap = fileFeign
|
||||
.findFileVOByBusinessId(FileVO.builder().businessId(n.getId()).build());
|
||||
if (!EmptyUtil.isNullOrEmpty(responseWrap.getDatas())){
|
||||
n.setFileVOs(responseWrap.getDatas());
|
||||
}else {
|
||||
n.setFileVOs(new ArrayList<>());
|
||||
}
|
||||
});
|
||||
}
|
||||
</#if>
|
||||
</#list>
|
||||
return pageVo;
|
||||
}catch (Exception e){
|
||||
log.error("${table.comment!}列表异常:{}", ExceptionsUtil.getStackTraceAsString(e));
|
||||
throw new ProjectException(${entity}Enum.PAGE_FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Caching(evict = {@CacheEvict(value = ${entity}CacheConstant.PAGE,allEntries = true),
|
||||
@CacheEvict(value = ${entity}CacheConstant.LIST,allEntries = true)},
|
||||
put={@CachePut(value =${entity}CacheConstant.BASIC,key = "#result.id")})
|
||||
@Override
|
||||
public ${entity}Vo create${entity}Vo(${entity}Vo ${entity?uncap_first}Vo) {
|
||||
try {
|
||||
${entity}Vo ${entity?uncap_first}VoResult = BeanConv.toBean(${entity?uncap_first}Service.create${entity}(${entity?uncap_first}Vo), ${entity}Vo.class);
|
||||
<#list cfg.tablesFile as tableFiile>
|
||||
<#if tableFiile==table.name>
|
||||
//绑定附件
|
||||
if (!EmptyUtil.isNullOrEmpty(${entity?uncap_first}VoResult)&&!EmptyUtil.isNullOrEmpty(${entity?uncap_first}Vo.getFileVOs())){
|
||||
${entity?uncap_first}Vo.getFileVOs().forEach(n->{n.setBusinessId(${entity?uncap_first}VoResult.getId());});
|
||||
//绑定图片
|
||||
ResponseResult<List<FileVO>> listResponseResult = fileFeign.bindBatchBusinessId(${entity?uncap_first}Vo.getFileVOs());
|
||||
${entity?uncap_first}VoResult.setFileVOs(listResponseResult.getDatas());
|
||||
}
|
||||
</#if>
|
||||
</#list>
|
||||
return ${entity?uncap_first}VoResult;
|
||||
} catch (Exception e) {
|
||||
log.error("保存${table.comment!}异常:{}", ExceptionsUtil.getStackTraceAsString(e));
|
||||
throw new ProjectException(${entity}Enum.SAVE_FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Caching(evict = {@CacheEvict(value = ${entity}CacheConstant.PAGE,allEntries = true),
|
||||
@CacheEvict(value = ${entity}CacheConstant.LIST,allEntries = true),
|
||||
@CacheEvict(value =${entity}CacheConstant.BASIC,key = "#${entity?uncap_first}Vo.id")})
|
||||
@Override
|
||||
public Boolean update${entity}Vo(${entity}Vo ${entity?uncap_first}Vo) {
|
||||
try {
|
||||
Boolean flag = ${entity?uncap_first}Service.update${entity}(${entity?uncap_first}Vo);
|
||||
<#list cfg.tablesFile as tableFiile>
|
||||
<#if tableFiile==table.name>
|
||||
if (flag){
|
||||
//移除业务原图片,并绑定新的图片到业务上
|
||||
fileFeign.replaceBindBatchBusinessId(${entity?uncap_first}Vo.getFileVOs());
|
||||
}
|
||||
</#if>
|
||||
</#list>
|
||||
return flag;
|
||||
} catch (Exception e) {
|
||||
log.error("修改${table.comment!}异常:{}", ExceptionsUtil.getStackTraceAsString(e));
|
||||
throw new ProjectException(${entity}Enum.UPDATE_FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Caching(evict = {@CacheEvict(value = ${entity}CacheConstant.PAGE,allEntries = true),
|
||||
@CacheEvict(value = ${entity}CacheConstant.LIST,allEntries = true)})
|
||||
@Override
|
||||
public Boolean delete${entity}Vo(String[] checkedIds) {
|
||||
try {
|
||||
Boolean flag = ${entity?uncap_first}Service.delete${entity}(checkedIds);
|
||||
<#list cfg.tablesFile as tableFiile>
|
||||
<#if tableFiile==table.name>
|
||||
if (flag){
|
||||
//删除图片
|
||||
for (String checkedId : checkedIds) {
|
||||
fileFeign.deleteFileVOByBusinessId(FileVO.builder()
|
||||
.businessId(Long.valueOf(checkedId))
|
||||
.build());
|
||||
}
|
||||
}
|
||||
</#if>
|
||||
</#list>
|
||||
return flag;
|
||||
} catch (Exception e) {
|
||||
log.error("删除${table.comment!}异常:{}", ExceptionsUtil.getStackTraceAsString(e));
|
||||
throw new ProjectException(${entity}Enum.DEL_FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Cacheable(value = ${entity}CacheConstant.LIST,key ="#${entity?uncap_first}Vo.hashCode()")
|
||||
public List<${entity}Vo> find${entity}VoList(${entity}Vo ${entity?uncap_first}Vo) {
|
||||
try {
|
||||
List<${entity}Vo> records = BeanConv.toBeanList(${entity?uncap_first}Service.find${entity}List(${entity?uncap_first}Vo),${entity}Vo.class);
|
||||
<#list cfg.tablesFile as tableFiile>
|
||||
<#if tableFiile==table.name>
|
||||
//处理图片
|
||||
if (!EmptyUtil.isNullOrEmpty(records)){
|
||||
records.forEach(n->{
|
||||
ResponseResult<List<FileVO>> responseWrap = fileFeign
|
||||
.findFileVOByBusinessId(FileVO.builder().businessId(n.getId()).build());
|
||||
if (!EmptyUtil.isNullOrEmpty(responseWrap.getDatas())){
|
||||
n.setFileVOs(responseWrap.getDatas());
|
||||
}else {
|
||||
n.setFileVOs(new ArrayList<>());
|
||||
}
|
||||
});
|
||||
}
|
||||
</#if>
|
||||
</#list>
|
||||
return records;
|
||||
} catch (Exception e) {
|
||||
log.error("删除${table.comment!}异常:{}", ExceptionsUtil.getStackTraceAsString(e));
|
||||
throw new ProjectException(${entity}Enum.LIST_FAIL);
|
||||
}
|
||||
}
|
||||
}
|
||||
</#if>
|
||||
@@ -0,0 +1,15 @@
|
||||
package ${package.Mapper};
|
||||
|
||||
import ${package.Entity}.${entity};
|
||||
import ${superMapperClassPackage};
|
||||
|
||||
/**
|
||||
* @Description:${table.comment!}Mapper接口
|
||||
*/
|
||||
<#if kotlin>
|
||||
interface ${table.mapperName} : ${superMapperClass}<${entity}>
|
||||
<#else>
|
||||
public interface ${table.mapperName} extends ${superMapperClass}<${entity}> {
|
||||
|
||||
}
|
||||
</#if>
|
||||
@@ -0,0 +1,39 @@
|
||||
<?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="${package.Mapper}.${table.mapperName}">
|
||||
|
||||
<#if enableCache>
|
||||
<!-- 开启二级缓存 -->
|
||||
<cache type="org.mybatis.caches.ehcache.LoggingEhcache"/>
|
||||
|
||||
</#if>
|
||||
<#if baseResultMap>
|
||||
<!-- 通用查询映射结果 -->
|
||||
<resultMap id="BaseResultMap" type="${package.Entity}.${entity}">
|
||||
<#list table.fields as field>
|
||||
<#if field.keyFlag><#--生成主键排在第一位-->
|
||||
<id column="${field.name}" property="${field.propertyName}" />
|
||||
</#if>
|
||||
</#list>
|
||||
<#list table.commonFields as field><#--生成公共字段 -->
|
||||
<result column="${field.name}" property="${field.propertyName}" />
|
||||
</#list>
|
||||
<#list table.fields as field>
|
||||
<#if !field.keyFlag><#--生成普通字段 -->
|
||||
<result column="${field.name}" property="${field.propertyName}" />
|
||||
</#if>
|
||||
</#list>
|
||||
</resultMap>
|
||||
|
||||
</#if>
|
||||
<#if baseColumnList>
|
||||
<!-- 通用查询结果列 -->
|
||||
<sql id="Base_Column_List">
|
||||
<#list table.commonFields as field>
|
||||
${field.name},
|
||||
</#list>
|
||||
${table.fieldNames}
|
||||
</sql>
|
||||
|
||||
</#if>
|
||||
</mapper>
|
||||
@@ -0,0 +1,55 @@
|
||||
package ${package.Service};
|
||||
|
||||
import ${package.Entity}.${entity};
|
||||
import ${superServiceClassPackage};
|
||||
import com.itheima.sfbx.framework.commons.dto.trade.${entity}Vo;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Description:${table.comment!}服务类
|
||||
*/
|
||||
<#if kotlin>
|
||||
interface ${table.serviceName} : ${superServiceClass}<${entity}>
|
||||
<#else>
|
||||
public interface ${table.serviceName} extends ${superServiceClass}<${entity}> {
|
||||
|
||||
/**
|
||||
* @Description 多条件查询${table.comment!}分页列表
|
||||
* @param ${entity?uncap_first}Vo 查询条件
|
||||
* @param pageNum 页码
|
||||
* @param pageSize 每页条数
|
||||
* @return Page<${entity}>
|
||||
*/
|
||||
Page<${entity}> find${entity}Page(${entity}Vo ${entity?uncap_first}Vo, int pageNum, int pageSize);
|
||||
|
||||
/**
|
||||
* @Description 创建${table.comment!}
|
||||
* @param ${entity?uncap_first}Vo 对象信息
|
||||
* @return ${entity}
|
||||
*/
|
||||
${entity} create${entity}(${entity}Vo ${entity?uncap_first}Vo);
|
||||
|
||||
/**
|
||||
* @Description 修改${table.comment!}
|
||||
* @param ${entity?uncap_first}Vo 对象信息
|
||||
* @return Boolean
|
||||
*/
|
||||
Boolean update${entity}(${entity}Vo ${entity?uncap_first}Vo);
|
||||
|
||||
/**
|
||||
* @Description 删除${table.comment!}
|
||||
* @param checkedIds 选择中对象Ids
|
||||
* @return Boolean
|
||||
*/
|
||||
Boolean delete${entity}(String[] checkedIds);
|
||||
|
||||
/**
|
||||
* @description 多条件查询${table.comment!}列表
|
||||
* @param ${entity?uncap_first}Vo 查询条件
|
||||
* @return: List<${entity}>
|
||||
*/
|
||||
List<${entity}> find${entity}List(${entity}Vo ${entity?uncap_first}Vo);
|
||||
}
|
||||
</#if>
|
||||
@@ -0,0 +1,100 @@
|
||||
package ${package.ServiceImpl};
|
||||
|
||||
import ${package.Entity}.${entity};
|
||||
import ${package.Mapper}.${table.mapperName};
|
||||
import ${package.Service}.${table.serviceName};
|
||||
import ${superServiceImplClassPackage};
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.itheima.sfbx.framework.commons.dto.trade.${entity}Vo;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.itheima.sfbx.framework.commons.utils.BeanConv;
|
||||
import com.itheima.sfbx.framework.commons.utils.EmptyUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
/**
|
||||
* @Description:${table.comment!}服务实现类
|
||||
*/
|
||||
@Service
|
||||
<#if kotlin>
|
||||
open class ${table.serviceImplName} : ${superServiceImplClass}<${table.mapperName}, ${entity}>(), ${table.serviceName} {
|
||||
|
||||
}
|
||||
<#else>
|
||||
public class ${table.serviceImplName} extends ${superServiceImplClass}<${table.mapperName}, ${entity}> implements ${table.serviceName} {
|
||||
|
||||
@Override
|
||||
public Page<${entity}> find${entity}Page(${entity}Vo ${entity?uncap_first}Vo, int pageNum, int pageSize) {
|
||||
//构建分页对象
|
||||
Page<${entity}> page = new Page<>(pageNum,pageSize);
|
||||
//构建查询条件
|
||||
QueryWrapper<${entity}> queryWrapper = new QueryWrapper<>();
|
||||
//构建多条件查询,代码生成后自己可自行调整
|
||||
<#list table.fields as field>
|
||||
//${field.comment}查询
|
||||
if (!EmptyUtil.isNullOrEmpty(${entity?uncap_first}Vo.get${field.propertyName?cap_first}())) {
|
||||
queryWrapper.lambda().eq(${entity}::get${field.propertyName?cap_first},${entity?uncap_first}Vo.get${field.propertyName?cap_first}());
|
||||
}
|
||||
</#list>
|
||||
//状态查询
|
||||
if (!EmptyUtil.isNullOrEmpty(${entity?uncap_first}Vo.getEnableFlag())) {
|
||||
queryWrapper.lambda().eq(${entity}::getEnableFlag,${entity?uncap_first}Vo.getEnableFlag());
|
||||
}
|
||||
//按创建时间降序
|
||||
queryWrapper.lambda().orderByDesc(${entity}::getCreatedTime);
|
||||
//执行分页查询
|
||||
return page(page, queryWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ${entity} create${entity}(${entity}Vo ${entity?uncap_first}Vo) {
|
||||
//转换${entity}Vo为${entity}
|
||||
${entity} ${entity?uncap_first} = BeanConv.toBean(${entity?uncap_first}Vo, ${entity}.class);
|
||||
boolean flag = save(${entity?uncap_first});
|
||||
if (flag){
|
||||
return ${entity?uncap_first};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean update${entity}(${entity}Vo ${entity?uncap_first}Vo) {
|
||||
//转换${entity}Vo为${entity}
|
||||
${entity} ${entity?uncap_first} = BeanConv.toBean(${entity?uncap_first}Vo, ${entity}.class);
|
||||
return updateById(${entity?uncap_first});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean delete${entity}(String[] checkedIds) {
|
||||
//转换数组为集合
|
||||
List<String> ids = Arrays.asList(checkedIds);
|
||||
List<Long> idsLong = new ArrayList<>();
|
||||
ids.forEach(n->{
|
||||
idsLong.add(Long.valueOf(n));
|
||||
});
|
||||
return removeByIds(idsLong);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<${entity}> find${entity}List(${entity}Vo ${entity?uncap_first}Vo) {
|
||||
//构建查询条件
|
||||
QueryWrapper<${entity}> queryWrapper = new QueryWrapper<>();
|
||||
if (!EmptyUtil.isNullOrEmpty(${entity?uncap_first}Vo.getId())) {
|
||||
queryWrapper.lambda().eq(${entity}::getId,${entity?uncap_first}Vo.getId());
|
||||
}
|
||||
<#list table.fields as field>
|
||||
//${field.comment}查询
|
||||
if (!EmptyUtil.isNullOrEmpty(${entity?uncap_first}Vo.get${field.propertyName?cap_first}())) {
|
||||
queryWrapper.lambda().eq(${entity}::get${field.propertyName?cap_first},${entity?uncap_first}Vo.get${field.propertyName?cap_first}());
|
||||
}
|
||||
</#list>
|
||||
//状态查询
|
||||
if (!EmptyUtil.isNullOrEmpty(${entity?uncap_first}Vo.getEnableFlag())) {
|
||||
queryWrapper.lambda().eq(${entity}::getEnableFlag,${entity?uncap_first}Vo.getEnableFlag());
|
||||
}
|
||||
return list(queryWrapper);
|
||||
}
|
||||
}
|
||||
</#if>
|
||||
@@ -0,0 +1,54 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport"
|
||||
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, viewport-fit=cover">
|
||||
<title>店铺商品详情</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app">
|
||||
<h1>商品信息json</h1>
|
||||
<div>
|
||||
${shopGoods}
|
||||
</div>
|
||||
<#-- <div>-->
|
||||
<#-- <h1>-->
|
||||
<#-- 封面图片列表-->
|
||||
<#-- </h1>-->
|
||||
<#-- <ul>-->
|
||||
<#-- <li>路径: <a href=""> </a></li>-->
|
||||
<#-- </ul>-->
|
||||
<#-- </div>-->
|
||||
<#-- <div>-->
|
||||
<#-- <h1>-->
|
||||
<#-- 商品基本信息-->
|
||||
<#-- </h1>-->
|
||||
<#-- <p> 优惠价: <span> </span> 原价: <span> </span> </p>-->
|
||||
<#-- -->
|
||||
<#-- <p>标题: <span> </span></p>-->
|
||||
|
||||
<#-- <p>当前规格: </p>-->
|
||||
<#-- -->
|
||||
<#-- <p>所有规格: </p>-->
|
||||
|
||||
<#-- <p>服务规则列表: </p>-->
|
||||
|
||||
<#-- </div>-->
|
||||
<#-- <div>-->
|
||||
<#-- <h1>-->
|
||||
<#-- 商品详情图片列表-->
|
||||
<#-- </h1>-->
|
||||
<#-- <ul>-->
|
||||
<#-- <li>路径: <a href=""> </a></li>-->
|
||||
<#-- </ul>-->
|
||||
<#-- </div>-->
|
||||
|
||||
<p>参数列表: 未提供</p>
|
||||
<p>评价列表: 异步ajax查询</p>
|
||||
<p>优惠券: 异步查询</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,75 @@
|
||||
package com.itheima.easy.vo;
|
||||
|
||||
import com.itheima.easy.basic.BasicVo;
|
||||
<#if swagger2>
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
</#if>
|
||||
<#if entityLombokModel>
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
</#if>
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
<#list cfg.tablesFile as tableFiile>
|
||||
<#if tableFiile==table.name>
|
||||
import java.util.List;
|
||||
import com.itheima.sfbx.framework.commons.dto.file.FileVO;
|
||||
</#if>
|
||||
</#list>
|
||||
/**
|
||||
* @Description:${table.comment!}
|
||||
*/
|
||||
<#if entityLombokModel>
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
</#if>
|
||||
public class ${entity}Vo extends BasicVo {
|
||||
|
||||
@Builder
|
||||
public ${entity}Vo(Long id,<#list table.fields as field>${field.propertyType} ${field.propertyName}<#if field_has_next>,</#if></#list>){
|
||||
super(id);
|
||||
<#list table.fields as field>
|
||||
this.${field.propertyName}=${field.propertyName};
|
||||
</#list>
|
||||
}
|
||||
<#-- ---------- BEGIN 字段循环遍历 ---------->
|
||||
<#list table.fields as field>
|
||||
<#if field.keyFlag>
|
||||
<#assign keyPropertyName="${field.propertyName}"/>
|
||||
</#if>
|
||||
|
||||
<#if field.comment!?length gt 0>
|
||||
<#if swagger2>
|
||||
@ApiModelProperty(value = "${field.comment}")
|
||||
<#else>
|
||||
/**
|
||||
* ${field.comment}
|
||||
*/
|
||||
</#if>
|
||||
</#if>
|
||||
<#if field.propertyType=='Long'>
|
||||
@JsonFormat(shape = JsonFormat.Shape.STRING)
|
||||
</#if>
|
||||
<#if field.propertyType=='Date'>
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
</#if>
|
||||
private ${field.propertyType} ${field.propertyName};
|
||||
</#list>
|
||||
<#------------ END 字段循环遍历 ---------->
|
||||
|
||||
@ApiModelProperty(value = "选中节点")
|
||||
private String[] checkedIds;
|
||||
|
||||
<#list cfg.tablesFile as tableFiile>
|
||||
<#if tableFiile==table.name>
|
||||
<#if swagger2>
|
||||
@ApiModelProperty(value = "文件Vo对象")
|
||||
</#if>
|
||||
private List<FileVO> fileVOs;
|
||||
</#if>
|
||||
</#list>
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<artifactId>sfbx-cloud</artifactId>
|
||||
<groupId>com.itheima.sfbx</groupId>
|
||||
<version>2.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<!--文件处理模块-->
|
||||
<artifactId>sfbx-file</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<name>sfbx-file</name>
|
||||
<modules>
|
||||
<module>file-interface</module>
|
||||
<module>file-web</module>
|
||||
</modules>
|
||||
<!-- FIXME change it to the project's website -->
|
||||
<url>http://www.example.com</url>
|
||||
|
||||
</project>
|
||||
Reference in New Issue
Block a user