将上传文件功能优化成一个starter

389 阅读2分钟

把一个上传文件功能优化成一个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项目如下:

1.png

在这个springBoot 项目我们不需要启动类 和 原来的 application 文件、test 目录 的,在此删掉也无妨。

idea 点击 install,把项目打包并存到本地maven仓库中

使用测试:

随便找一个springBoot 项目引入我们自定义的stater 如下:

2.png

新增一个接口使用默认的DefalutUploadService,进行文件上传:如下

@RestController
public class UploadTestController {
    @Autowired
    private DefaultUploadService uploadService;

    
    @PostMapping("/myUpload")
    public Result upload(@RequestParam("file") MultipartFile file){
        return uploadService.upload(file);
    }
}

此时我们不在application 文件中配置上传文件的地址时启动项目:

3.png

启动项目时 @Autowired 在容器中找不到 DefaultUploadService 这个bean,所以启动失败了

我们在application.yml 中配置上传文件的地址:

#other setting

spring.upload.dir=D:/upload
spring.upload.prefix=/test/

#other setting

配置后重启项目,就不会报错了,测试访问刚刚定义的 上传文件接口,结果如下图显示:

5.png

至此我们自定义一个stater 完成了,可以上传到maven私服仓库,之后的项目中需要上传文件的功能时,引入这个jar 调用默认的实现方法即可。