
本文共 20557 字,大约阅读时间需要 68 分钟。
文章目录
1. 基础简介
JCP
(Java Community Process
)为Java
技术制定标准技术规范的机构,任何人都可以注册 ,并且可以参与JSR
(Java Specification Requests
:Java
规范提案)的评审,也可以提交自己的JSR
。
Bean Validation
是Java
定义的一套基于注解的数据校验规范,出自JSR303
,JSR349
,JSR380
规范提案。目前最新规范是Bean Validation 2.0
。
2. 框架简介
JSR
规范提案只是提供了技术标准,并没有提供具体的实现。具体实现框架有validation-api
,jakarta.validation-api
和hibernate-validator
。
2.1. validation-api
javax.validation validation-api 2.0.1.Final
引用路径:
D:\Programmer\maven\repository\javax\validation\validation-api\2.0.1.Final\validation-api-2.0.1.Final.jar
Java
在2009
年的Java EE 6
中发布了JSR303
以及javax.validation
包,对JSR303
版本的Bean Validation
作了接口实现, 并没有相关校验代码。也就是validation-api
。
注意:单独使用该引用在使用SpringBoot 2.3.5.RELEASE
版本项目测试的时候,数据验证未生效。
2.2. jakarta.validation-api
jakarta.validation jakarta.validation-api 2.0.2
引用路径:
D:\Programmer\maven\repository\jakarta\validation\jakarta.validation-api\2.0.2\jakarta.validation-api-2.0.2.jar
jakarta.validation-api
是由validation-api
改名而来。2018-03-05
年,开源组织Eclipse
基金会宣布将Java EE
(Enterprise Edition
:企业版)被更名为Jakarta EE
(雅加达)。这是Oracle
将Java EE
移交给Eclipse
基金会后加强对Java
品牌控制的措施。随着Java EE
的改名,包名和路径名也做了相应修改,从上面的引用路径可以看出来。
注意:单独使用该引用在使用SpringBoot 2.3.5.RELEASE
版本项目测试的时候,数据验证未生效。
2.3. hibernate-validator
org.hibernate.validator hibernate-validator 6.1.6.Final
应用路径:
D:\Programmer\maven\repository\org\hibernate\validator\hibernate-validator\6.1.6.Final\hibernate-validator-6.1.6.Final.jar
hibernate-validator
与持久层框架Hibernate
没有什么关系,hibernate-validator
是Hibernate
基金会下的一个项目,是对Bean Validation
的具体实现,它提供了JSR380
规范中所有内置constraint
的实现,还加入了它自己的一些constraint
实现。点开pom
文件,会发现hibernate-validator
依赖于validation-api
(jakarta.validation-api
)。所以我们使用数据验证的时候可以直接引用这个包即可。
2.4. spring-boot-starter-validation
对于SpringBoot
项目,直接引用它提供的starter
,这个starter
内部依赖了hibernate-validator
。
org.springframework.boot spring-boot-starter-validation
3. 注解说明
3.1. 标识注解
注解 | 完整类型 | 说明 |
---|---|---|
@Valid | javax.validation.Valid | 标记用于验证级联的属性、方法参数或方法返回类型。在验证属性、方法参数或方法返回类型时,将验证在对象及其属性上定义的约束。 |
@Validated | org.springframework.validation.annotation.Validated | Spring 提供的扩展注解,可以添加在类、方法参数、普通方法上,表示它们需要进行约束校验,可以很方便的用于分组校验。 |
3.2. 约束注解
Bean Validation
规范中包含的22个注解,也就是validation-api
(jakarta.validation-api
)实现的注解:
每个注解都有message
,groups
,payload
这三个属性,这是Bean Validation
规范的要求。下表还列出了每个注解自有的一些属性。
注解 | 说明 | 可用类型 |
---|---|---|
@Null | 被注释的元素必须是 null。 | 任何类型 |
@NotNull | 被注释的元素不能是 null。 | 任何类型 |
@AssertTrue | 被注释的元素必须为 true。null 值是有效的。 | boolean,Boolean |
@AssertFalse | 被注释的元素必须为 false。null 值是有效的。 | boolean,Boolean |
@Min(value=) | 被注释的元素必须是一个数字,其值必须大于或等于指定的最小值。null 值是有效的。value :指定元素必须大于或等于的 long 值。 | BigDecimal,BigInteger,byte,short,int,long,Byte,Short,Integer,Long |
@Max(value=) | 被注释的元素必须是一个数字,其值必须小于或等于指定的最大值。null 值是有效的。value :指定元素必须小于或等于的 long 值。 | BigDecimal,BigInteger,byte,short,int,long,Byte,Short,Integer,Long |
@DecimalMin(value=,inclusive=) | 被注释的元素必须是一个数字,其值必须大于或等于指定的最小值。null 值是有效的。value :用 String 表示 BigDecimal 字符串的最小值。inclusive :true 表示大于或等于指定的最小值,false 表示大于最小值。默认为 true。 | BigDecimal,BigInteger,CharSequence ,byte,short,int,long,Byte,Short,Integer,Long |
@DecimalMax(value=,inclusive=) | 被注释的元素必须是一个数字,其值必须小于或等于指定的最大值。null 值是有效的。value :用 String 表示 BigDecimal 字符串的最大值。inclusive :true 表示小于或等于指定的最大值,false 表示小于最大值。默认为 true。 | BigDecimal,BigInteger,CharSequence ,byte,short,int,long,Byte,Short,Integer,Long |
@Negative | 被注释的元素必须是一个严格的负数(即 0 被认为是无效的值)。null 值是有效的。 | BigDecimal,BigInteger,byte,short,int,long,float ,double ,Byte,Short,Integer,Long,Float ,Double |
@NegativeOrZero | 被注释的元素必须是负数或 0。null 值是有效的。 | BigDecimal,BigInteger,byte,short,int,long,float ,double ,Byte,Short,Integer,Long,Float ,Double |
@Positive | 被注释的元素必须是一个严格的正数(即 0 被认为是无效的值)。null 值是有效的。 | BigDecimal,BigInteger,byte,short,int,long,float ,double ,Byte,Short,Integer,Long,Float ,Double |
@PositiveOrZero | 被注释的元素必须是正数或 0。null 值是有效的。 | BigDecimal,BigInteger,byte,short,int,long,float ,double ,Byte,Short,Integer,Long,Float ,Double |
@Size(min=, max=) | 被注释的元素大小必须介于最小和最大(闭区间)之间。null 值是有效的。 min :指定元素必须大于或等于的 int 值,默认为 0。max :指定元素必须小于或等于的 int 值,默认为 int 类型的最大值。 | CharSequence :计算字符序列的长度。Collection :计算集合大小。Map :计算 map 的大小。Array :计算数组长度。 |
@Digits(integer=, fraction=) | 带注释的元素必须是可接受范围内的数字。null 值是有效的。integer :此数字所接受的最大整数的位数。fraction :该数字所接受的最大小数的位数。 | BigDecimal,BigInteger,CharSequence ,byte,short,int,long,Byte,Short,Integer,Long |
@Past | 被注释的元素必须是一个过去的日期时间。null 值是有效的。 | java.util.Datejava.util.Calendarjava.time.Instantjava.time.LocalDatejava.time.LocalDateTimejava.time.LocalTimejava.time.MonthDayjava.time.OffsetDateTimejava.time.OffsetTimejava.time.Yearjava.time.YearMonthjava.time.ZonedDateTimejava.time.chrono.HijrahDatejava.time.chrono.JapaneseDatejava.time.chrono.MinguoDatejava.time.chrono.ThaiBuddhistDate |
@PastOrPresent | 被注释的元素必须是一个过去或现在的日期时间。null 值是有效的。 | 和@Past相同 |
@Future | 被注释的元素必须是一个未来的日期时间。null 值是有效的。 | 和@Past相同 |
@FutureOrPresent | 被注释的元素必须是一个现在或未来的日期时间。null 值是有效的。 | 和@Past相同 |
@Pattern(regexp=, flags={}) | 被注释的元素必须匹配指定的正则表达式。正则表达式遵循 Java 正则表达式约定,见 Java.util.regex.Pattern。null 值是有效的。regexp :要匹配的正则表达式。flags :解析正则表达式时考虑的 Flag 枚举数组。 | CharSequence |
@NotEmpty | 被注释的元素不能是 null 或空。 | CharSequence :计算字符序列的长度。Collection :计算集合大小。Map :计算 map 的大小。Array :计算数组长度。 |
@NotBlank | 被注释的元素不能是 null,并且必须包含至少一个非空白字符。 | CharSequence |
@Email(regexp=, flags={}) | 检查指定的字符序列是否为有效的电子邮件地址。允许通过可选参数regexp 和flags 指定电子邮件必须匹配的附加正则表达式(包括正则表达式标志)。null 值是有效的。 | CharSequence |
hibernate-validator
额外实现的注解:
注解 | 说明 | 可用类型 |
---|---|---|
@Length(min=, max=) | 验证字符串是否包含在 min 和 max 之间。min :指定元素的长度必须大于或等于的 int 值,默认为 0。max :指定元素的长度必须小于或等于的 int 值,默认为 int 类型的最大值。 | 验证字符串长度 |
@Range(min=, max=) | 被注释的元素必须在适当的范围内。 min :指定元素的数值必须大于或等于的 int 值,默认为 0。max :指定元素的数值必须小于或等于的 int 值,默认为 long 类型的最大值。 | 数值或数值字符串的数值大小 |
注解的可以到org.hibernate.validator.constraints
包下面自行查看,这里仅列举几个常用的注解。
org.hibernate.validator.internal.constraintvalidators
包下面自行查看。 3.3. 提示信息
注解的默认提示信息,如果没有写message
属性的话则默认显示文件中配置的提示信息,我们用的是简体中文的ValidationMessages_zh_CN.properties
文件,文件路径:
hibernate-validator-6.1.6.Final.jar!\org\hibernate\validator\ValidationMessages_zh_CN.properties
默认提示息如下所示:
javax.validation.constraints.AssertFalse.message = 必须为 falsejavax.validation.constraints.AssertTrue.message = 必须为 truejavax.validation.constraints.DecimalMax.message = 必须小于 ${ inclusive == true ? 'or equal to ' : ''}{ value}javax.validation.constraints.DecimalMin.message = 必须大于 ${ inclusive == true ? 'or equal to ' : ''}{ value}javax.validation.constraints.Digits.message = 数字值超出了边界(期望 <{ integer} digits>.<{ fraction} digits>)javax.validation.constraints.Email.message = 必须为格式规范的电子邮件地址javax.validation.constraints.Future.message = 必须是未来的日期javax.validation.constraints.FutureOrPresent.message = 必须是现在或将来的日期javax.validation.constraints.Max.message = 必须小于或等于 { value}javax.validation.constraints.Min.message = 必须大于或等于 { value}javax.validation.constraints.Negative.message = 必须小于 0javax.validation.constraints.NegativeOrZero.message = 必须小于或等于 0javax.validation.constraints.NotBlank.message = 不得为空白javax.validation.constraints.NotEmpty.message = 不得为空javax.validation.constraints.NotNull.message = 不得为 nulljavax.validation.constraints.Null.message = 必须为 nulljavax.validation.constraints.Past.message = 必须是过去的日期javax.validation.constraints.PastOrPresent.message = 必须是过去或现在的日期javax.validation.constraints.Pattern.message = 必须与 "{regexp}" 匹配javax.validation.constraints.Positive.message = 必须大于 0javax.validation.constraints.PositiveOrZero.message = 必须大于或等于 0javax.validation.constraints.Size.message = 大小必须在 { min} 和 { max} 之间org.hibernate.validator.constraints.CreditCardNumber.message = 无效信用卡卡号org.hibernate.validator.constraints.Currency.message = 无效货币(必须为 { value} 之一)org.hibernate.validator.constraints.EAN.message = 无效 { type} 条形码org.hibernate.validator.constraints.Email.message = 电子邮件地址格式不规范org.hibernate.validator.constraints.ISBN.message = 无效 ISBNorg.hibernate.validator.constraints.Length.message = 长度必须介于 { min} 与 { max} 之间org.hibernate.validator.constraints.CodePointLength.message = 长度必须介于 { min} 与 { max} 之间org.hibernate.validator.constraints.LuhnCheck.message = ${ validatedValue} 的校验位无效,Luhn Modulo 10 校验和失败org.hibernate.validator.constraints.Mod10Check.message = ${ validatedValue} 的校验位无效,Modulo 10 校验和失败org.hibernate.validator.constraints.Mod11Check.message = ${ validatedValue} 的校验位无效,Modulo 11 校验和失败org.hibernate.validator.constraints.ModCheck.message = ${ validatedValue} 的校验位无效,{ modType} 校验和失败org.hibernate.validator.constraints.NotBlank.message = 可能不为空org.hibernate.validator.constraints.NotEmpty.message = 可能不为空org.hibernate.validator.constraints.ParametersScriptAssert.message = 脚本表达式 "{script}" 未求值为 trueorg.hibernate.validator.constraints.Range.message = 必须介于 { min} 与 { max} 之间org.hibernate.validator.constraints.SafeHtml.message = 可能具有不安全的 HTML 内容org.hibernate.validator.constraints.ScriptAssert.message = 脚本表达式 "{script}" 未求值为 trueorg.hibernate.validator.constraints.UniqueElements.message = 必须仅包含唯一元素org.hibernate.validator.constraints.URL.message = 必须为有效 URLorg.hibernate.validator.constraints.br.CNPJ.message = 无效巴西企业纳税人登记号 (CNPJ)org.hibernate.validator.constraints.br.CPF.message = 无效巴西个人纳税人登记号 (CPF)org.hibernate.validator.constraints.br.TituloEleitoral.message = 无效巴西投票人身份证号org.hibernate.validator.constraints.pl.REGON.message = 无效波兰纳税人识别号 (REGON)org.hibernate.validator.constraints.pl.NIP.message = 无效 VAT 识别号 (NIP)org.hibernate.validator.constraints.pl.PESEL.message = 无效波兰身份证号 (PESEL)org.hibernate.validator.constraints.time.DurationMax.message = 必须短于 ${ inclusive == true ? ' or equal to' : ''}${ days == 0 ? '' : days == 1 ? ' 1 day' : ' ' += days += ' days'}${ hours == 0 ? '' : hours == 1 ? ' 1 hour' : ' ' += hours += ' hours'}${ minutes == 0 ? '' : minutes == 1 ? ' 1 minute' : ' ' += minutes += ' minutes'}${ seconds == 0 ? '' : seconds == 1 ? ' 1 second' : ' ' += seconds += ' seconds'}${ millis == 0 ? '' : millis == 1 ? ' 1 milli' : ' ' += millis += ' millis'}${ nanos == 0 ? '' : nanos == 1 ? ' 1 nano' : ' ' += nanos += ' nanos'}org.hibernate.validator.constraints.time.DurationMin.message = 必须长于 ${ inclusive == true ? ' or equal to' : ''}${ days == 0 ? '' : days == 1 ? ' 1 day' : ' ' += days += ' days'}${ hours == 0 ? '' : hours == 1 ? ' 1 hour' : ' ' += hours += ' hours'}${ minutes == 0 ? '' : minutes == 1 ? ' 1 minute' : ' ' += minutes += ' minutes'}${ seconds == 0 ? '' : seconds == 1 ? ' 1 second' : ' ' += seconds += ' seconds'}${ millis == 0 ? '' : millis == 1 ? ' 1 milli' : ' ' += millis += ' millis'}${ nanos == 0 ? '' : nanos == 1 ? ' 1 nano' : ' ' += nanos += ' nanos'}
4. 使用说明
- 在
pom
文件中添加spring-boot-starter-validation
的引用; - 在接口方法中对需要进行参数校验的对象添加
@Validated
注解或者@Valid
注解; - 然后在代码中使用
BindingResult
或者Errors
来获取错误信息。可以只返回第一个错误字段信息,也可以返回所有的错误字段信息。 - 使用了统一异常处理的话,可以省略
BindingResult
或者Errors
参数。
package com.example.demo.controller;import com.example.demo.entity.UserInfo;import com.example.demo.result.Result;import lombok.extern.slf4j.Slf4j;import org.springframework.validation.BindingResult;import org.springframework.validation.Errors;import org.springframework.validation.FieldError;import org.springframework.validation.annotation.Validated;import org.springframework.web.bind.annotation.*;import javax.validation.Valid;import java.util.ArrayList;import java.util.List;/** * @auther wangbo * @date 2021-01-15 14:57 */@Slf4j@RestController@RequestMapping("/user_info")public class UserInfoController { @PostMapping("/add") public Result add(@RequestBody @Validated UserInfo userInfo, BindingResult bindingResult){ //判断是否有字段校验错误 if (bindingResult.hasFieldErrors()){ //获取与字段相关的所有错误 ListfieldErrors = bindingResult.getFieldErrors(); List msgList = new ArrayList<>(); for (FieldError fieldError : fieldErrors){ msgList.add(fieldError.getField() + " : " + fieldError.getDefaultMessage()); } return Result.failure(msgList.toString()); } return Result.success(); } @PostMapping("/add1") public Result add1(@RequestBody @Valid UserInfo userInfo, Errors errors){ //判断是否有字段校验错误 if (errors.hasFieldErrors()){ //获取与字段相关的所有错误中的第一个错误,没有则返回null FieldError fieldError = errors.getFieldError(); assert fieldError != null; return Result.failure(fieldError.getField() + " : " + fieldError.getDefaultMessage()); } return Result.success(); } /** * 走异常处理中心 */ @PostMapping("/add2") public Result add2(@RequestBody @Valid UserInfo userInfo){ return Result.success(); }}
4.1. 一般性校验
- 普通对象校验,直接使用相关约束注解即可;
- 对于有嵌套对象的字段校验,需要在该字段上面加上
@Valid
注解; - 如果被校验的对象有继承关系,并且父类字段使用了约束注解,那么这些父类的约束条件也会被校验。
- 最好在约束注解都加上
message
属性,并且体现出字段信息,这样在异常处理的时候可以只返回message
信息,不用返回对应的字段信息了。不写message
的话,则使用的默认message
,体现不出具体错误字段信息,异常处理的时候需要带上字段信息。
package com.example.demo.entity;import lombok.Data;import org.hibernate.validator.constraints.Length;import org.hibernate.validator.constraints.Range;import javax.validation.Valid;import javax.validation.constraints.*;import java.util.List;/** * @auther wangbo * @date 2021-01-15 14:55 */@Datapublic class UserInfo { @NotBlank @Length(min=3, max=10) private String username; @NotNull @Range(min = 15, max = 100) private Integer age; @NotBlank @Email private String email; @NotBlank @Pattern(regexp="^((13[0-9])|(15[^4,\\D])|(18[0,3-9]))\\d{8}$", message = "手机号格式不正确") private String phone; @NotNull @AssertTrue private Boolean status; //嵌套对象校验 @NotNull @Valid private Interest interest; @NotEmpty @Valid private ListblogList; }
package com.example.demo.entity;import lombok.Data;import javax.validation.constraints.NotBlank;/** * @auther wangbo * @date 2021-01-16 22:46 */@Datapublic class Interest { @NotBlank private String name;}
package com.example.demo.entity;import lombok.Data;import javax.validation.constraints.Max;import javax.validation.constraints.Min;import javax.validation.constraints.NotBlank;import javax.validation.constraints.NotNull;/** * @auther wangbo * @date 2021-01-16 22:50 */@Datapublic class Blog { @NotBlank private String title; @NotNull @Min(value = 1) @Max(value = 5) private Integer type;}
4.2. 自定义校验
有时候框架提供的约束注解并不能满足我们的需求,所以需要自定义合适的校验规则来满足自己的校验需求。
自定义注解用到的注解:
@Target
:指定此注解支持的元素类型,比如:FIELD(属性)、METHOD(方法)等;@Rentention(RUNTIME)
:指定此类型的注解将在运行时通过反射方式使用;@Constraint(validatedBy = { })
:标记注解的类型为约束,指定注解所使用的验证器(写验证逻辑的类),如果约束可以用在多种数据类型中,则每种数据类型对应一个验证器。@Documented
:表示带有某种类型的注释将由 javadoc 和类似工具记录;@Repeatable(List.class)
:指示注解可以在相同的位置重复多次,通常具有不同的配置。List 包含注解类型。
Bean Validation API 规范要求任何约束注解都需要定义以下属性:
message
:定制化的提示信息,主要是从ValidationMessages.properties
里提取,也可以依据实际情况进行定制。groups
:用于将约束注解进行分组,不同组会执行不同的校验操作。payload
:主要是针对Bean
的,使用不多,未做详细了解。
下面定义一个注解,用在Field
字段上,运行时生效,触发的是DateStrFormatValidator
这个验证类。
自定义校验注解:
package com.example.demo.annotation;import com.example.demo.validator.DateStrFormatValidator;import javax.validation.Constraint;import javax.validation.Payload;import java.lang.annotation.Documented;import java.lang.annotation.Retention;import java.lang.annotation.Target;import static java.lang.annotation.ElementType.FIELD;import static java.lang.annotation.RetentionPolicy.RUNTIME;/** * 字符串日期格式校验注解 * @auther wangbo * @date 2021-01-17 10:10 */@Documented@Target({ FIELD})@Retention(RUNTIME)@Constraint(validatedBy = { DateStrFormatValidator.class})public @interface DateStrFormat { String message() default "日期格式和{format}不匹配"; Class [] groups() default { }; Class [] payload() default { }; /** * 自定义属性 */ String format() default "yyyy-MM-dd HH:mm:ss";}
提供一个校验程序:
package com.example.demo.validator;import com.example.demo.annotation.DateStrFormat;import org.springframework.util.StringUtils;import javax.validation.ConstraintValidator;import javax.validation.ConstraintValidatorContext;import java.time.format.DateTimeFormatter;import java.time.format.DateTimeParseException;/** * 字符串日期格式校验程序 * @auther wangbo * @date 2021-01-17 11:24 */public class DateStrFormatValidator implements ConstraintValidator{ private String format; /** * 初始化验证器 */ @Override public void initialize(DateStrFormat constraintAnnotation) { this.format = constraintAnnotation.format(); } /** * 实现验证逻辑 */ @Override public boolean isValid(String value, ConstraintValidatorContext context) { if (StringUtils.isEmpty(value)) { return true; } try { DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(format); dateTimeFormatter.parse(value); return true; } catch (DateTimeParseException e) { return false; } }}
在Java Bean
中字段上像普通约束注解一样进行使用:
@DateStrFormat(format = "yyyy-MM-dd")private String birthday;
4.3. 分组校验
同一个对象要复用,比如上面的UserInfo
在更新时候要校验userId
,在保存的时候不需要校验userId
,其他属性在两种情况下都要校验,这时候就可以在userId
上的约束注解中使用groups
属性。
先定义分组接口Create
和Update
:
package com.example.demo.group;import javax.validation.groups.Default;/** * @auther wangbo * @date 2021-01-17 21:23 */public interface Create extends Default { }
package com.example.demo.group;import javax.validation.groups.Default;/** * @auther wangbo * @date 2021-01-17 21:23 */public interface Update extends Default { }
注意:在声明分组的时候尽量加上extend Default
。因为如果约束注解上没有声明groups
属性的话,默认为groups = {Default.class}
。所以在声明@Validated(Update.class)
的时候,就会出现没添加groups
的约束注解不参与校验的问题。
在Java Bean
的字段上的约束注解上添加groups
属性:
@NotNull(groups = { Update.class})private Long userId;
接下来需要在声明校验的地方使用,如下所示,就实现了在更新接口校验userId
,在创建接口不校验userId
:
import com.example.demo.group.Create;import com.example.demo.group.Update;@PostMapping("/create")public Result create(@RequestBody @Validated(Create.class) UserInfo userInfo){ ...}@PostMapping("/update")public Result update(@RequestBody @Validated(Update.class) UserInfo userInfo){ ...}
JSR
规范支持手动校验,不直接支持使用注解校验,不过Spring
提供了分组校验注解扩展支持,即:@Validated
,参数为group
类集合。
4.4. 异常处理
前面都是在代码中使用对象获取错误,现在可以使用异常处理中心来处理这些参数校验错误。针对本文主要处理的是MethodArgumentNotValidException
和ValidationException
异常。
MethodArgumentNotValidException
异常是处理字段校验结果的。这里选择只处理第一个错误字段信息进行返回。当然也可以拿到所有错误字段信息。ValidationException
异常是处理在字段校验过程中出现的异常。比如自定义校验的实现代码有bug
,会在该异常中进行处理。
package com.example.demo.advice;import com.example.demo.exception.CustomException;import com.example.demo.result.Result;import lombok.extern.slf4j.Slf4j;import org.springframework.validation.BindingResult;import org.springframework.validation.FieldError;import org.springframework.web.bind.MethodArgumentNotValidException;import org.springframework.web.bind.annotation.ExceptionHandler;import org.springframework.web.bind.annotation.RestControllerAdvice;import javax.validation.ValidationException;/** * 全局异常统一处理 * * @auther wangbo * @date 2021-01-13 17:16 */@Slf4j@RestControllerAdvicepublic class ExceptionHandlerAdvice { /** * 通用异常处理 */ @ExceptionHandler(Exception.class) public Result exceptionHandler(Exception e) { log.info("通用异常处理"); return Result.failure(e.getMessage()); } /** * 自定义异常处理 */ @ExceptionHandler(CustomException.class) public Result customExceptionHandler(CustomException e) { log.info("自定义异常处理"); return Result.error(e.getResultCode()); } /** * 参数校验异常处理 */ @ExceptionHandler(MethodArgumentNotValidException.class) public Result methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) { log.info("参数校验异常处理"); BindingResult bindingResult = e.getBindingResult(); FieldError fieldError = bindingResult.getFieldError(); assert fieldError != null; return Result.failure(fieldError.getField() + " : " + fieldError.getDefaultMessage()); } /** * 参数校验过程异常处理 */ @ExceptionHandler(ValidationException.class) public Result validationExceptionHandler(ValidationException e) { log.info("参数校验过程异常处理"); String message = e.getCause().getMessage(); if (message != null) { return Result.failure(message); } return Result.failure("请求参数校验错误"); }}
参考博文:
发表评论
最新留言
关于作者
