把一个上传文件功能优化成一个starter
快速创建一个SpringBoot项目 pom.xml如下:
以下三个依赖必须的:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
提供一个上传文件接口IUploadService
public interface IUploadService {
/**
* 上传文件接口
* @param file
* @return
*/
Result upload(MultipartFile file);
...
}
properties 对应类:
/**
* 对应的是application文件的配置
*/
@Component
@ConfigurationProperties(prefix = "spring.upload")
public class UploadProperties {
// 文件的上传地址
private String dir;
// 文件前缀
private String prefix;
//getter and setter
}
默认实现方法:
public class DefaultUploadService implements IUploadService {
@Autowired
private UploadProperties uploadProperties;
public DefaultUploadService (UploadProperties uploadProperties){
this.uploadProperties=uploadProperties;
}
/**
* 文件上传方法
*/
@Override
public Result upload(MultipartFile file){
if(uploadProperties.getDir()==null || uploadProperties.getPrefix()==null){
return Result.error("请配置文件上传路径");
}
try {
if(file.isEmpty()){
return Result.error("文件为空");
}
String originalFilename=file.getOriginalFilename();
boolean blob = originalFilename.equals("blob");
String fileExt = blob?".jpg": originalFilename.substring(originalFilename.lastIndexOf(".") ).toLowerCase();
if(StringUtils.isBlank(fileExt)||fileExt.equals(".blob")){
fileExt=".jpg";
}
String month= DateUtil.formatDate(new Date(),"yyyyMMdd");
String uploadPathPrefix=uploadProperties.getPrefix()+month+"/";
SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
String newFileName = UUID.randomUUID() + fileExt;
String absuDir=uploadProperties.getDir()+uploadPathPrefix;
//是否有目录,没有就创建
File absuDirFile=new File(absuDir);
if(!absuDirFile.exists()){
absuDirFile.mkdirs();
}
//目录下写入文件
File uploadFile=new File(absuDir,newFileName);
Files.copy(file.getInputStream(), uploadFile.toPath());
NameUrlBean bean=new NameUrlBean();
bean.setName(originalFilename);
bean.setUrl(uploadPathPrefix+newFileName);
return Result.success(bean);
} catch (IOException e) {
e.printStackTrace();
return Result.error("上传文件失败"+e.getMessage());
}
}
...
}
UploadConfig 关键配置类:
/**
* @ConditionalOnProperty(name = "dir",prefix = "spring.upload")
* 当引入此jar的项目需要在配置文件中配置 spring.upload.dir
*/
@Configuration
@EnableConfigurationProperties(UploadProperties.class)
@ConditionalOnProperty(name = "dir",prefix = "spring.upload")
public class UploadConfig {
@Autowired
private UploadProperties uploadProperties;
@Bean
public DefaultUploadService defaultUploadService(){
return new DefaultUploadService(uploadProperties);
}
}
以上代码中注意 @ConditionalOnProperty(name = "dir",prefix = "spring.upload"),这里的意思是:当引入此上传文件jar 的项目,在application.yml中 配置 了上传文件地址 spring.upload.dir 时才把这个类注册到容器中。
在resource 目录下新建 /META-INF/spring.factories 文件添加配置如下:
#-------starter自动装配---------
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.it520.upload.config.UploadConfig
项目pom.xml 添加如下:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
默认的springBoot 项目是没有 这个节点的配置的,这里需要新增该配置不然 打包之后生成的jar 文件路径找不到。
完整的stater项目如下:
在这个springBoot 项目我们不需要启动类 和 原来的 application 文件、test 目录 的,在此删掉也无妨。
idea 点击 install,把项目打包并存到本地maven仓库中
使用测试:
随便找一个springBoot 项目引入我们自定义的stater 如下:
新增一个接口使用默认的DefalutUploadService,进行文件上传:如下
@RestController
public class UploadTestController {
@Autowired
private DefaultUploadService uploadService;
@PostMapping("/myUpload")
public Result upload(@RequestParam("file") MultipartFile file){
return uploadService.upload(file);
}
}
此时我们不在application 文件中配置上传文件的地址时启动项目:
启动项目时 @Autowired 在容器中找不到 DefaultUploadService 这个bean,所以启动失败了
我们在application.yml 中配置上传文件的地址:
#other setting
spring.upload.dir=D:/upload
spring.upload.prefix=/test/
#other setting
配置后重启项目,就不会报错了,测试访问刚刚定义的 上传文件接口,结果如下图显示:
至此我们自定义一个stater 完成了,可以上传到maven私服仓库,之后的项目中需要上传文件的功能时,引入这个jar 调用默认的实现方法即可。