起因:
入参DTO参数过多,最开始采取常规构造方法方式,但是发现因为有些参数必填有些不必填就造成了,要么采取大量嵌套构造方法,要么在多参数构造方式里面莫些参数传null,代码不够优雅,并且可能会传错
// 比如这种
public String getOssFile(String url) {
return getOssFile(url, null);
}
public String getOssFile(String url, String param) {
return OSSUtil.getOssFileUrl(getUrlWithoutDomain(url), param);
}
重构前代码
package com.tezign.intelligence.api.file.common.dto;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.tezign.intelligence.api.file.common.enums.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;
import java.util.List;
import java.util.Objects;
/**
* @author: zhangjian2
* @create: 2021-01-07 16:05
*/
@Data
public class FileProcessReqDTO {
/**
* 原始素材id
*/
private Long originAssetId;
/**
* 原始url
*/
private String originUrl;
/**
* 租户id
*/
private String tenantId = "default";
/**
* 回调地址
*/
private String callbackUrl;
/**
* 下载后的保存地址 请求方不需要填
*/
private String downloadPath;
/**
* 一个请求一个task
*/
private Long taskId;
/**
* 一个请求 一个资源 一个md5
*/
private String md5;
/**
* 请求资源类型 可以不传
*/
private String fileType;
private Long fileSize;
/**
* eg: 同一个资源可以生成带水印的pdf 跟不带水印的pdf 他们都属于一个FileOperationDTO
*/
private List<FileOperationDTO> fileOperationDTOList = Lists.newArrayList();
/**
* @Description: office 转成带水印的pdf
* @Param:
* @param originAssetId
* @param originUrl
* @param tenantId
* @param callbackUrl 回调
* @param code 为水印模板code vms_file_watermark_template
* @param watermarkText 水印文字
* @return: void
* @Author: zyx
* @time: 2021/2/5 11:03 上午
*/
private void convertToPdf(Long originAssetId,String originUrl,String tenantId,String callbackUrl,String code,String watermarkText){
init(originAssetId,originUrl,tenantId,callbackUrl);
final FileOperationDTO fileOperationDTO = new FileOperationDTO();
fileOperationDTO.setTenantId(tenantId);
FileWatermarkDTO fileWatermarkDTO = new FileWatermarkDTO();
fileWatermarkDTO.setCode(code);
fileWatermarkDTO.setWatermarkText(watermarkText);
fileWatermarkDTO.setTenantId(tenantId);
fileOperationDTO.setFileWatermarkDTO(fileWatermarkDTO);
ConversionDTO conversionDTO = new ConversionDTO();
conversionDTO.setFileTypeEnum(FileTypeEnum.PDF);
conversionDTO.setTenantId(tenantId);
fileOperationDTO.setConversionDTO(conversionDTO);
fileOperationDTO.setFileAbilityType(FileAbilityTypeEnum.CONVERSION_WAERMARK);
fileOperationDTO.setStatus(FileTaskStatusEnum.NOT_PROCESSING.getCode());
this.fileOperationDTOList.add(fileOperationDTO);
}
/**
* office 文件转pdf 不带水印
*/
private void convertToPdf(Long originAssetId,String originUrl,String tenantId,String callbackUrl){
init(originAssetId,originUrl,tenantId,callbackUrl);
final FileOperationDTO fileOperationDTO = new FileOperationDTO();
fileOperationDTO.setFileAbilityType(FileAbilityTypeEnum.CONVERSION);
fileOperationDTO.setTenantId(tenantId);
final ConversionDTO conversionDTO = new ConversionDTO();
conversionDTO.setTenantId(tenantId);
conversionDTO.setFileTypeEnum(FileTypeEnum.PDF);
fileOperationDTO.setConversionDTO(conversionDTO);
fileOperationDTO.setStatus(FileTaskStatusEnum.NOT_PROCESSING.getCode());
this.fileOperationDTOList.add(fileOperationDTO);
}
private void convertToPdf(Long originAssetId,String tenantId){
init(originAssetId,tenantId);
final FileOperationDTO fileOperationDTO = new FileOperationDTO();
fileOperationDTO.setFileAbilityType(FileAbilityTypeEnum.CONVERSION);
final ConversionDTO conversionDTO = new ConversionDTO();
conversionDTO.setTenantId(tenantId);
conversionDTO.setFileTypeEnum(FileTypeEnum.PDF);
fileOperationDTO.setConversionDTO(conversionDTO);
fileOperationDTO.setStatus(FileTaskStatusEnum.NOT_PROCESSING.getCode());
this.fileOperationDTOList.add(fileOperationDTO);
}
/**
* office 生成一个带水印的pdf 和一个不带水印的pdf
* @param code
* @param watermarkText
*/
private void sendToConvertAndWatermark(Long originAssetId,String originUrl,String tenantId,String callbackUrl,String code,String watermarkText){
convertToPdf(originAssetId,originUrl,tenantId,callbackUrl,code,watermarkText);
convertToPdf(originAssetId,originUrl,tenantId,callbackUrl);
}
/**
* @Description:
* @Param: [originAssetId , originUrl, tenantId, callbackUrl]
* @return: void
* @Author: zyx
* @time: 2021/2/5 11:00 上午
*/
private void init(Long originAssetId,String originUrl,String tenantId,String callbackUrl){
tenantId = StringUtils.isBlank(tenantId) ? "default" : tenantId;
this.originAssetId = originAssetId;
this.originUrl = originUrl;
this.tenantId = tenantId;
this.callbackUrl = callbackUrl;
}
private void init(Long originAssetId,String tenantId){
tenantId = StringUtils.isBlank(tenantId) ? "default" : tenantId;
this.originAssetId = originAssetId;
this.originUrl = null;
this.tenantId = tenantId;
this.callbackUrl = null;
}
public boolean isLocalFile() {
if (CollectionUtils.isEmpty(fileOperationDTOList)) {
return false;
}
return fileOperationDTOList.stream()
.filter(fileOperationDTO -> Objects.nonNull(fileOperationDTO.getFileAbilityType()))
.map(dto -> dto.getConversionDTO().getFileConversionType()).anyMatch(FileConversionTypeEnum::isLocalFile);
}
}
可以看到上面只是一个格式转换便可能产生多种情况,考虑到后面功能的不断叠加 可能会产生大量的构造方法。
重构后:
@Builder
public static class VideoTranscodeBuilder {
private Long originAssetId;
private String originUrl;
private String tenantId;
private String callbackUrl;
private String bitRate;
private String height;
private String fps;
private FileTypeEnum fileTypeEnum;
public FileProcessReqDTO buildReq() {
final FileProcessReqDTO fileProcessReqDTO = new FileProcessReqDTO();
fileProcessReqDTO.videoTranscode(this.originAssetId, this.originUrl, this.tenantId,
this.callbackUrl, this.bitRate, this.height, this.fps, this.fileTypeEnum);
return fileProcessReqDTO;
}
}
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class ConvertBuilder {
private Long originAssetId;
private String originUrl;
private String tenantId;
private String callbackUrl;
private FileTypeEnum fileTypeEnum;
public FileProcessReqDTO buildReq() {
final FileProcessReqDTO fileProcessReqDTO = new FileProcessReqDTO();
fileProcessReqDTO.convert(this.originAssetId, this.originUrl, this.tenantId,
this.callbackUrl, this.fileTypeEnum);
return fileProcessReqDTO;
}
}
可以看到代码的优雅性提高很多
再看使用情况
之前
final FileProcessReqDTO fileProcessReqDTO = new FileProcessReqDTO();
fileProcessReqDTO.convertToPdf(399L,null,"t2","http://10.244.3.230:10354/file-service/api-feign/callback");
fileProcessReqDTO.sendToConvertAndWatermark(398L,null,"t2","https://vms-]service.tezign.com","WATERMARK_TEST","admin11@tezign.com");
FileProcessRespDTO process = fileCenterService.process(fileProcessReqDTO);
之后
final FileProcessReqDTO fileProcessReqDTO = new FileProcessReqDTO.ConvertBuilder(1L,null,"t2",null, FileTypeEnum.PDF)
.buildReq();
final FileProcessReqDTO processReqDTO = FileProcessReqDTO.ConvertBuilder.builder().callbackUrl(null).tenantId("t10")
.originAssetId(2L).build().buildReq();
可以看到代码的优雅性 使用的方便性都有很大的提高