spring boot通过Constraint和ConstraintValidator自定义参数校验注解 文件上传前置校验注解 validMessage

本文主要是介绍spring boot通过Constraint和ConstraintValidator自定义参数校验注解 文件上传前置校验注解 validMessage,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Constraint注解

在spring boot进行开发的时候,有时需要对请求的参数进行校验, 而@Constraint可以实现自定义的校验注解。

Spring boot自定义参数校验注解

1. 如果Spring boot是2.3.0之后的版本,需要引入新的依赖
		<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId></dependency>
2. 自定义注解
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = MultipartFileValidator.class)
public @interface MultipartFileUploadPreCheck {String DEFAULT_MAXSIZE = "-1";/*** AliasFor("endsWith")*/
//    FileUtils.Type[] value() default {};/*** 支持的文件后缀类型,默认全部,AliasFor("value")*/FileUtils.Type[] allowFileType() default {};/*** 文件后缀是否区分大小写*/boolean ignoreCase() default true;/*** 上传的文件是否允许为空*/boolean allowEmpty() default false;/*** Max file size. Values can use the suffixes "MB" or "KB" to indicate megabytes or* kilobytes respectively.<br/>* 默认不限制但必须小于等于SpringMVC中文件上传配置*/String maxSize() default DEFAULT_MAXSIZE;/*** Min file size. Values can use the suffixes "MB" or "KB" to indicate megabytes or* kilobytes respectively. default byte*/String minSize() default "0MB";String message() default "The uploaded file is not verified.";Class<?>[] groups() default {};Class<? extends Payload>[] payload() default {};}
3. FileUtils.Type文件
    @RequiredArgsConstructor(access = AccessLevel.PROTECTED)public static enum Type {/*** json*/JSON("json"),/*** JEPG.*/JPEG("FFD8FF"),JPG("FFD8FF"),/*** PNG.*/PNG("89504E47"),/*** GIF.*/GIF("47494638"),/*** TIFF.*/TIFF("49492A00"),/*** Windows Bitmap.*/BMP("424D"),/*** CAD.*/DWG("41433130"),/*** Adobe Photoshop.*/PSD("38425053"),/*** Rich Text Format.*/RTF("7B5C727466"),/*** XML.*/XML("3C3F786D6C"),/*** HTML.*/HTML("68746D6C3E"),/*** CSS.*/CSS("48544D4C207B0D0A0942"),/*** JS.*/JS("696B2E71623D696B2E71"),/*** Email [thorough only].*/EML("44656C69766572792D646174653A"),/*** Outlook Express.*/DBX("CFAD12FEC5FD746F"),/*** Outlook (pst).*/PST("2142444E"),/*** MS Word/Excel.* XLS_DOC:ppt,doc,xls* XLSX_DOCX:xlsx*/XLS("D0CF11E0"), XLSX("504B0304"),DOC("D0CF11E0"), DOCX("504B0304"),/*** Visio*/VSD("d0cf11e0a1b11ae10000"),/*** MS Access.*/MDB("5374616E64617264204A"),/*** WPS文字wps、表格et、演示dps都是一样的*/WPS("d0cf11e0a1b11ae10000"),/*** torrent*/TORRENT("6431303A637265617465"),/*** WordPerfect.*/WPD("FF575043"),/*** Postscript.*/EPS("252150532D41646F6265"),/*** Adobe Acrobat.*/PDF("255044462D312E"),/*** Quicken.*/QDF("AC9EBD8F"),/*** Windows Password.*/PWL("E3828596"),/*** ZIP Archive.*/
//        ZIP("504b0304140000000800"),/*** RAR Archive.*/RAR("52617221"),/*** JSP Archive.*/JSP("3C2540207061676520"),/*** JAVA Archive.*/JAVA("7061636B61676520"),/*** CLASS Archive.*/CLASS("CAFEBABE0000002E00"),
//        /**
//         * JAR Archive.
//         */
//        JAR("504b03040a0000000000"),/*** MF Archive.*/MF("4D616E69666573742D56"),/*** EXE Archive.*/EXE("4D5A9000030000000400"),/*** CHM Archive.*/CHM("49545346030000006000"),/*** Wave.*/WAV("57415645"),/*** AVI.*/AVI("41564920"),/*** Real Audio.*/RAM("2E7261FD"),/*** Real Media.*/RM("2E524D46"),/*** MPEG (mpg).*/MPG("000001BA"),/*** Quicktime.*/MOV("6D6F6F76"),/*** Windows Media.*/ASF("3026B2758E66CF11"),/*** MIDI.*/MID("4D546864"),/*** MP4.*/MP4("00000020667479706d70"),/*** MP3.*/MP3("49443303000000002176"),/*** FLV.*/FLV("464C5601050000000900"),/*** TXT:txt,docx*/TXT("0000000000000000000000000000");@Getterprivate final String value;private static HashMap<String, Type> codeValueMap = new HashMap<>(47);static {for (FileUtils.Type currentOne : FileUtils.Type.values()) {codeValueMap.put(currentOne.getValue(), currentOne);}}public static FileUtils.Type getInstance(int code) {return codeValueMap.get(code);}public static boolean exists(int code) {return codeValueMap.containsKey(code);}}
3. 编写自定义注解处理文件
public class MultipartFileValidator implements ConstraintValidator<MultipartFileUploadPreCheck, MultipartFile> {@Autowiredprivate MultipartProperties multipartProperties;private long maxSize = -1;private long minSize = 0;private MultipartFileUploadPreCheck multipartFileUploadPreCheck;private final ArrayList<FileUtils.Type> extension = new ArrayList<>();@Overridepublic void initialize(MultipartFileUploadPreCheck constraintAnnotation) {this.multipartFileUploadPreCheck = constraintAnnotation;//支持的文件扩展名集合
//        Collections.addAll(extension, multipartFileUploadPreCheck.value());Collections.addAll(extension, multipartFileUploadPreCheck.allowFileType());//文件上传的最大值if (constraintAnnotation.maxSize().equals(MultipartFileUploadPreCheck.DEFAULT_MAXSIZE)) {//默认最大值采用Spring中配置的单文件大小DataSize maxFileSize = multipartProperties.getMaxFileSize();this.maxSize = parseSize(maxFileSize.toString());} else {this.maxSize = parseSize(constraintAnnotation.maxSize());}//文件上传的最小值this.minSize = parseSize(constraintAnnotation.minSize());}private long parseSize(String size) {Assert.hasLength(size, "Size must not be empty");size = size.toUpperCase();long length = Long.parseLong(size.substring(0, size.length() - 2));if (size.endsWith("KB")) {return length * 1024;}if (size.endsWith("MB")) {return length * 1024 * 1024;}return Long.parseLong(size);}/*** 多个文件也可以 效验* @param multipartFiles* @param cvc* @return*/@SneakyThrowspublic boolean isValids(MultipartFile[] multipartFiles, ConstraintValidatorContext cvc) {//上传的文件是空的情况if (Objects.isNull(multipartFiles)) {if (multipartFileUploadPreCheck.allowEmpty()) {return true;}validMessage("上传文件不能为空", cvc);return false;}for (MultipartFile multipartFile : multipartFiles) {boolean valid = isValid(multipartFile, cvc);if (!valid) {return false;}}return true;}@SneakyThrows@Overridepublic boolean isValid(MultipartFile multipartFile, ConstraintValidatorContext cvc) {String fieldName = multipartFile.getName();//上传的文件是空的情况if (multipartFile.isEmpty()) {if (multipartFileUploadPreCheck.allowEmpty()) {return true;}validMessage("上传文件不能为空" + ",参数名:" + fieldName, cvc);return false;}//上传的文件不是空的情况,验证其他条件是否成立//获取文件名,如果上传文件后缀名不区分大小写则统一转成小写String originalFilename = multipartFile.getOriginalFilename();if (multipartFileUploadPreCheck.ignoreCase()) {originalFilename = originalFilename.toLowerCase();}if (StringUtils.isBlank(originalFilename)){validMessage("上传文件名不能为空", cvc);return false;}// 先通过后缀名过滤一部分明显错误的, 因为读取文件流获取文件头信息 比较消耗资源
//        String fileSuffixName = originalFilename.substring(originalFilename.lastIndexOf('.') + 1);
//        List<String> allowedFileSuffixNames = extension.stream().map(e -> e.name().toLowerCase(Locale.ROOT)).collect(Collectors.toList());
//        if (StringUtils.isNotBlank(fileSuffixName) && allowedFileSuffixNames.stream().noneMatch(e -> e.equals(fileSuffixName))) {
//            validMessage("上传文件类型不符合要求" + ",参数名:" + fieldName, cvc);
//            return false;
//        }FileUtils.Type type = FileUtils.getType(multipartFile.getInputStream());if (extension.size() > 0 && extension.stream().noneMatch(e -> e.equals(type))) {validMessage("上传文件类型不符合要求" + ",参数名:" + fieldName, cvc);return false;}//上传文件字节数long size = multipartFile.getSize();if (size < this.minSize) {validMessage("上传文件不能小于指定最小值" + ",参数名:" + fieldName, cvc);return false;}if (size > this.maxSize) {validMessage("上传文件不能大于指定最大值" + ",参数名:" + fieldName, cvc);return false;}return true;}private void validMessage(String message, ConstraintValidatorContext cvc) {cvc.disableDefaultConstraintViolation();cvc.buildConstraintViolationWithTemplate(message).addConstraintViolation();}}

这篇关于spring boot通过Constraint和ConstraintValidator自定义参数校验注解 文件上传前置校验注解 validMessage的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1041806

相关文章

Java实现检查多个时间段是否有重合

《Java实现检查多个时间段是否有重合》这篇文章主要为大家详细介绍了如何使用Java实现检查多个时间段是否有重合,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录流程概述步骤详解China编程步骤1:定义时间段类步骤2:添加时间段步骤3:检查时间段是否有重合步骤4:输出结果示例代码结语作

Java中String字符串使用避坑指南

《Java中String字符串使用避坑指南》Java中的String字符串是我们日常编程中用得最多的类之一,看似简单的String使用,却隐藏着不少“坑”,如果不注意,可能会导致性能问题、意外的错误容... 目录8个避坑点如下:1. 字符串的不可变性:每次修改都创建新对象2. 使用 == 比较字符串,陷阱满

Java判断多个时间段是否重合的方法小结

《Java判断多个时间段是否重合的方法小结》这篇文章主要为大家详细介绍了Java中判断多个时间段是否重合的方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录判断多个时间段是否有间隔判断时间段集合是否与某时间段重合判断多个时间段是否有间隔实体类内容public class D

IDEA编译报错“java: 常量字符串过长”的原因及解决方法

《IDEA编译报错“java:常量字符串过长”的原因及解决方法》今天在开发过程中,由于尝试将一个文件的Base64字符串设置为常量,结果导致IDEA编译的时候出现了如下报错java:常量字符串过长,... 目录一、问题描述二、问题原因2.1 理论角度2.2 源码角度三、解决方案解决方案①:StringBui

Java覆盖第三方jar包中的某一个类的实现方法

《Java覆盖第三方jar包中的某一个类的实现方法》在我们日常的开发中,经常需要使用第三方的jar包,有时候我们会发现第三方的jar包中的某一个类有问题,或者我们需要定制化修改其中的逻辑,那么应该如何... 目录一、需求描述二、示例描述三、操作步骤四、验证结果五、实现原理一、需求描述需求描述如下:需要在

Java中ArrayList和LinkedList有什么区别举例详解

《Java中ArrayList和LinkedList有什么区别举例详解》:本文主要介绍Java中ArrayList和LinkedList区别的相关资料,包括数据结构特性、核心操作性能、内存与GC影... 目录一、底层数据结构二、核心操作性能对比三、内存与 GC 影响四、扩容机制五、线程安全与并发方案六、工程

JavaScript中的reduce方法执行过程、使用场景及进阶用法

《JavaScript中的reduce方法执行过程、使用场景及进阶用法》:本文主要介绍JavaScript中的reduce方法执行过程、使用场景及进阶用法的相关资料,reduce是JavaScri... 目录1. 什么是reduce2. reduce语法2.1 语法2.2 参数说明3. reduce执行过程

如何使用Java实现请求deepseek

《如何使用Java实现请求deepseek》这篇文章主要为大家详细介绍了如何使用Java实现请求deepseek功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1.deepseek的api创建2.Java实现请求deepseek2.1 pom文件2.2 json转化文件2.2

Java调用DeepSeek API的最佳实践及详细代码示例

《Java调用DeepSeekAPI的最佳实践及详细代码示例》:本文主要介绍如何使用Java调用DeepSeekAPI,包括获取API密钥、添加HTTP客户端依赖、创建HTTP请求、处理响应、... 目录1. 获取API密钥2. 添加HTTP客户端依赖3. 创建HTTP请求4. 处理响应5. 错误处理6.

Spring AI集成DeepSeek的详细步骤

《SpringAI集成DeepSeek的详细步骤》DeepSeek作为一款卓越的国产AI模型,越来越多的公司考虑在自己的应用中集成,对于Java应用来说,我们可以借助SpringAI集成DeepSe... 目录DeepSeek 介绍Spring AI 是什么?1、环境准备2、构建项目2.1、pom依赖2.2