Java中如何避免硬编码图片文件扩展名?
优化硬编码文件扩展名的几种方案
方案一:用枚举类统一管理扩展名与FileType映射
把所有扩展名和对应的FileType封装到枚举中集中管理,既避免散落在代码各处的硬编码,还能统一处理扩展名的大小写、带点/不带点的格式问题,后续修改规则只需更新枚举即可。
import java.util.Set; import java.util.stream.Collectors; public enum FileTypeMapping { ZIP(Set.of("zip"), FileType.ZIP), IMAGE(Set.of("jpg", "jpeg", "png", "bmp", "svg", "webp", "jfif", "pjpeg", "pjp", "apng", "avif"), FileType.IMAGE); private final Set<String> extensions; private final FileType fileType; FileTypeMapping(Set<String> extensions, FileType fileType) { // 统一转小写并去掉点,兼容不同格式的扩展名输入 this.extensions = extensions.stream() .map(ext -> ext.toLowerCase().replace(".", "")) .collect(Collectors.toSet()); } public static FileType getFileTypeByExtension(String extension) { String processedExt = extension.toLowerCase().replace(".", ""); for (FileTypeMapping mapping : values()) { if (mapping.extensions.contains(processedExt)) { return mapping.fileType; } } throw new GlobalCustomException(ErrorCode.ILLIGAL_FILE_TYPE); } }
业务代码可简化为:
FileType fileType = FileTypeMapping.getFileTypeByExtension(extension); FileUtil.saveFile(multipartFile, historyFolder, fileType, backupFilePath); FileUtil.saveFile(multipartFile, target, fileType, filePath);
方案二:通过配置文件动态加载扩展名映射
如果需要在不修改代码、不重启服务的情况下调整扩展名规则,可以把映射关系放到配置文件中,实现动态配置。
比如在application.yml中配置:
file-type-config: mappings: zip: ["zip"] image: ["jpg", "jpeg", "png", "bmp", "svg", "webp", "jfif", "pjpeg", "pjp", "apng", "avif"]
然后创建配置类读取并处理映射:
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; @Component @ConfigurationProperties(prefix = "file-type-config") public class FileTypeConfig { private Map<String, Set<String>> mappings; private Map<String, FileType> extensionToType; @PostConstruct public void init() { extensionToType = new HashMap<>(); mappings.forEach((typeKey, exts) -> { FileType fileType = FileType.valueOf(typeKey.toUpperCase()); Set<String> processedExts = exts.stream() .map(ext -> ext.toLowerCase().replace(".", "")) .collect(Collectors.toSet()); processedExts.forEach(ext -> extensionToType.put(ext, fileType)); }); } public FileType getFileTypeByExtension(String extension) { String processedExt = extension.toLowerCase().replace(".", ""); FileType fileType = extensionToType.get(processedExt); if (fileType == null) { throw new GlobalCustomException(ErrorCode.ILLIGAL_FILE_TYPE); } return fileType; } // getter、setter }
业务代码使用:
@Autowired private FileTypeConfig fileTypeConfig; // ... FileType fileType = fileTypeConfig.getFileTypeByExtension(extension); FileUtil.saveFile(multipartFile, historyFolder, fileType, backupFilePath); FileUtil.saveFile(multipartFile, target, fileType, filePath);
方案三:策略模式+注册表,最大化扩展性
如果后续需要为不同文件类型添加更多自定义处理逻辑(不只是保存文件),策略模式可以让每种类型的处理逻辑完全独立,新增类型时无需修改原有代码,符合开闭原则。
首先定义策略接口:
public interface FileHandler { boolean supports(String extension); void handleFile(MultipartFile multipartFile, String historyFolder, String backupFilePath, String target, String filePath); }
实现Zip和Image的处理策略:
@Component public class ZipFileHandler implements FileHandler { private static final Set<String> SUPPORTED_EXTS = Set.of("zip"); @Override public boolean supports(String extension) { String processedExt = extension.toLowerCase().replace(".", ""); return SUPPORTED_EXTS.contains(processedExt); } @Override public void handleFile(MultipartFile multipartFile, String historyFolder, String backupFilePath, String target, String filePath) { FileUtil.saveFile(multipartFile, historyFolder, FileType.ZIP, backupFilePath); FileUtil.saveFile(multipartFile, target, FileType.ZIP, filePath); } } @Component public class ImageFileHandler implements FileHandler { private static final Set<String> SUPPORTED_EXTS = Set.of("jpg", "jpeg", "png", "bmp", "svg", "webp", "jfif", "pjpeg", "pjp", "apng", "avif"); @Override public boolean supports(String extension) { String processedExt = extension.toLowerCase().replace(".", ""); return SUPPORTED_EXTS.contains(processedExt); } @Override public void handleFile(MultipartFile multipartFile, String historyFolder, String backupFilePath, String target, String filePath) { FileUtil.saveFile(multipartFile, historyFolder, FileType.IMAGE, backupFilePath); FileUtil.saveFile(multipartFile, target, FileType.IMAGE, filePath); } }
创建注册表管理所有策略:
import org.springframework.stereotype.Component; import java.util.List; @Component public class FileHandlerRegistry { private final List<FileHandler> fileHandlers; public FileHandlerRegistry(List<FileHandler> fileHandlers) { this.fileHandlers = fileHandlers; } public FileHandler getHandler(String extension) { return fileHandlers.stream() .filter(handler -> handler.supports(extension)) .findFirst() .orElseThrow(() -> new GlobalCustomException(ErrorCode.ILLIGAL_FILE_TYPE)); } }
业务代码使用:
@Autowired private FileHandlerRegistry handlerRegistry; // ... FileHandler handler = handlerRegistry.getHandler(extension); handler.handleFile(multipartFile, historyFolder, backupFilePath, target, filePath);
后续新增文件类型时,只需新增一个FileHandler实现类即可,无需改动原有业务代码。
内容的提问来源于stack exchange,提问作者user19901531
相关产品推荐
相关产品推荐

