大家好,我是bug菌~~

Hi ,小伙伴们,我们又见面啦,今天,我们来聊点什么咧?对了,前几天有个小学妹找我私聊了个关于校验后端参数的问题,大概意思就是“逻辑校验请求参数是否符合基本预期值时,每次都要自己做参数拦截校验(if…else一堆),很繁琐很,笨重,问我在这一块优有没有更优雅的玩法可以借鉴学习?”,答案肯定是有的。

于是我今天就来给大家聊聊它,怎么在项目中使用Spring 自带的 @Validated、@Valid 等校验注解来替代手动对参数进行校验,文中还涉及这类校验注解的基本用法、高阶玩法及衍生用法,也包括知识拓展等。

可能很多小伙伴们都不太了解,为了让大家更加了解,bug菌今个儿给大家总结了以下内容,具有很好的教学价值,希望小伙伴们根据这篇文章可以有所收获,建议小伙伴们先收藏后阅读哦。

小伙伴们如果觉得文章不错,点赞、收藏、评论,分享走一起呀,记得给bug菌来个一键三连~~

好了,我们开始这期的正文吧。

在开始教学之前,先照顾下还没接触过 Spring 提供的后台参数校验框架 及@Valid @Validated 等注解使用 的小伙伴们,至于学过的朋友们就请再温故一遍吧!所谓”

温故而知新,可以为师矣。 –《论语》”

验证用户输入是否正确是我们应用程序中的常见功能。Spring提供了@Valid和@Validated两个注解来实现验证功能,下面我们先来详细介绍一下它两。

@Valid:

1、概念:

@Valid是JSR303声明的,其中JSR303是JAVA EE 6 中的一项子规范,叫做 Bean Validation,为 JavaBean 验证定义了相应的元数据模型和 AP,Hibernate validation对其进行实现;

2、项目引入方式:所属包为:javax.validation.Valid

相关pom依赖:

<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>6.0.16.Final</version>
</dependency>
复制代码

3、作用范围:

@Valid:作用在方法、构造函数、方法参数和成员属性(field)上

@Target({ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Valid {
}
复制代码

@Validated:

1、概念:

Spring Validation验证框架对参数的验证机制提供了@Validated(Spring’s JSR-303规范,是标准JSR-303的一个变种),是一套帮助我们继续对传输的参数进行数据校验的注解,通过配置Validation可以很轻松的完成对数据的约束。

2、项目引入方式:

相关pom依赖:

<!--集成在这个父模块中   spring-boot-starter-validation-->
<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
</dependency>
复制代码

3、作用范围:

@Validated作用在类、方法和参数上;

@Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Validated {
    Class<?>[] value() default {};
}
复制代码

二者区别:

在检验Controller的入参是否符合规范时,使用@Validated或者@Valid在基本验证功能上没有太多区别。但是在分组、注解地方、嵌套验证等功能上两个有所不同:如下

1、注解位置:

  • @Validated:用在类型、方法和方法参数上。但不能用于成员属性(field)。
  • @Valid:可以用在方法、构造函数、方法参数和成员属性(field)上。

2、分组:

  • @Validated:提供分组功能,可以在入参验证时,根据不同的分组采用不同的验证机制。
  • @Valid:作为标准JSR-303规范,没有分组功能。

3. 嵌套验证:

一个待验证的pojo类,其中还包含了待验证的对象,需要在待验证对象上注解@valid,才能验证待验证对象中的成员属性。

  • @Validated: 用在方法入参上无法单独提供嵌套验证功能,不能用在成员属性(字段)上,也无法提示框架进行嵌套验证。能配合嵌套验证注解@Valid进行嵌套验证。
  • @Valid: 用在方法入参上无法单独提供嵌套验证功能。能够用在成员属性(字段)上,提示验证框架进行嵌套验证。能配合嵌套验证注解@Valid进行嵌套验证。

顺便给大家科普下 @Target 设定注解的不同使用范围;

@Target 共以下八种使用范围:

@Target:注解的作用目标
        @Target(ElementType.TYPE)   //接口、类、枚举
        @Target(ElementType.FIELD) //字段、枚举的常量
        @Target(ElementType.METHOD) //方法
        @Target(ElementType.PARAMETER) //方法参数
        @Target(ElementType.CONSTRUCTOR)  //构造函数
        @Target(ElementType.LOCAL_VARIABLE)//局部变量
        @Target(ElementType.ANNOTATION_TYPE)//注解
        @Target(ElementType.PACKAGE) ///包   
复制代码

以上纯属就给大家伙儿温习了一遍概念,想必大家已经对Spring提供的验证框架也有了一定的了解了吧,如果还不清楚,建议反复看几遍…那么接下来,bug菌就要开始今天的核心内容了,先从使用认识注解开始学起,好好看好好学~可千万别走神啊。

保证句句是重点!!!

首先Spring中bean validation由自身的校验和部分hibernate的校验组成;javax.validation.constraints包下校验注解有如下几大种类,比如空和非空校验、Boolean值校验等,具体看下表,梳理的很详细,文字就不做过多描述了。

想必大家肯定对有些注解并不陌生,甚至会经常出现在实体类中,比如@NotNull、@NotBlank、@NotEmpty等,对吧;但是也只是大家用来做参数校验,其实还隐藏更高阶玩法,有待大家解锁,今天bug菌就要不余余力的给大家爆料,带着大家玩透它!

核心文依次分四场景带着大家由浅入深式的体验,相信你们在通读完此文后,保证大家一定会有所收获!不信咱接着往下学~

场景一:

试问:前端传过来的字段如何通过某些注解在后台做校验?最笨的方法就是通过if else判断校验,你若看了我今天教的,你就会觉得以前写的是多么的low,而且非常笨重、不灵活。如果前端传来100个字段你还用if else 做判断吗?不得累死。

接下来的 第一个场景 演示的就是在后台创建的实体和前端传来的字段做对应映射,加上JSR303注解来做灵活校验,减轻代码量。

第一步:先给Bean实体添加校验注解:javax.validation.constraints(大部分注解都在这个包下),并定义自己的message提示,如下:

Specify entity class:

@APIModelProperty (value = "id", type = idType.auto) @tableId (value = "ID ", type = idType.auto) private Integer ID; @notBlank (message = "userName cannot be blank ") @APIModelProperty (value =" userName ") private String userName; @min (value = 1,message = "input age must not be less than 1") @max (value = 150,message =" input age must not be more than 150") @notnull (message = "input age must not be empty ") @APIModelProperty (value = "password ") private Integer userAge; @notblank (message = "password cannot be blank ") @length (min = 6, Max = 10,message =" Password Length must be at least 6 but not more than 10 characters!" , groups = {updateGroup.class, addGroup.class}) @APIModelProperty (value = "password ") private String userPwd; @email (message = "Email format is incorrect ") @APIModelProperty (value =" Email ") private String Email;Copy the code

Step 2: Enable the validation function. Use @Validated. At this point, you may ask why not use @Valid.

In fact, @ “Validated” encapsulates another layer on @ “Valid”, for example, adding a grouping function, which I will not reveal for the moment;

Validation results: A default response is generated after a validation error. A BindingResult is followed by a validation bean.

The sample Controller:

@postmapping (value = "/saveUser") @apiOperation (value = "User add ", Public ResultResponse saveUser(@Validated(addGroup.class) UserEntity UserEntity, BindingResult BindingResult) {/** * result.haserrors () returns false if the value passed from the front does not correspond to the annotation annotated in the entity class. For example, @notBlank (message = "user name cannot be blank ") in the name field of the entity returns false without passing the name; */ if (bindingResult.hasErrors()) { Map<String, String> map = new HashMap<>(); //1, result.getFielderrors (); BindingResult. GetFieldErrors ()) {/ / FieldError get error message String message. = FieldError getDefaultMessage (); String field = fielderor.getField (); map.put(field, message); } return new ResultResponse<>(map); } return new ResultResponse<>(testService.save(userEntity)); }Copy the code

Effect demonstration 1: request the user to add a new interface, what parameters are not passed, check whether there can be returned parameter verification error message:

Effect demonstration 2: request the user to add a new interface, and pass the password parameter, and the value of the password is deliberately so that the length does not meet the verification requirements, other parameters are not a test verification, are the same usage, as long as the parameter does not meet the verification will return you set the message content:

@length (min = 6, Max = 10,message = “Password Length is at least 6 but not more than 10 characters!” )

The password length of the userPwd is between 6 and 10 characters. If the password length is less than 6 characters or more than 10 characters, the message prompt will be displayed.

Effect demonstration 3: request user to add interface, test @email annotation use, check whether there can be returned parameter verification error message.

Effect demonstration 4: request user to add interface, all parameters according to the requirements, check whether the new successfully.

The result is as follows, see for yourself:

Scene 2:

In combination with a scene, we already know how to check the parameters and capture the error message, and then returned to the front, but then I want to ask you a question, if in accordance with the written as we must capture parameters in each method are written judgment and message traversal code, right, does it write one hundred times to one hundred interface to capture error parameters of code? Mother question this is certainly not, redundant code too much, difficult to maintain, then how to do? I’m going to talk about what bugs think;

Perhaps many partners have thought of global exception capture along with my thinking, global exception capture can be done. However, I don’t want to do that today. Instead, I want to teach you a fancy way of doing this, such as aop, which means that you can customize an exception section to catch the exception information thrown by BindingResult each time. Since AOP is executed before the global exception order, you only need to return the specific parameter verification result in the slice. It’s the same as defining global exception catching;

Look at the code I wrote below! It’s pretty straightforward.

@Order(10) @Around("execution(public * com.system.xiaoma.controller.*.*(..) )") public ResultResponse validAspect1(ProceedingJoinPoint pjp) throws Throwable { BindingResult bindingResult = getBindingResult(pjp); / / for normal return if (bindingResult = = null | |! bindingResult.hasErrors()) { ResultResponse resultResponse = new ResultResponse(); ResultResponse o = (ResultResponse) pjp.proceed(pjp.getArgs()); resultResponse.setData(o.getData()); return resultResponse; } else {return map <String, String> map = new HashMap<>(); List<FieldError> errors = bindingResult.getFieldErrors(); errors.forEach(e -> map.put(e.getField(),e.getDefaultMessage())); return new ResultResponse(map); @param PJP pointcut */ private BindingResult getBindingResult(ProceedingJoinPoint PJP) { Object[] args = pjp.getArgs(); for (Object arg : args) { if (arg instanceof BindingResult) { return (BindingResult) arg; } } return null; }Copy the code

Here is the actual return body:

Scenario 3:

We have worked out how to handle the field validation from the front end and how to handle the return validation error message in the two scenarios above.

Let’s assume a scenario where we add a user with userName, userAge, userPwd, etc., and add validation annotations to the entity class.

Soon, we’ll have an interface that just changes the user name. Change the userName based on the user ID only. The front end only passes you the user id and the newly changed userName userName, but we in the entity before annotated a lot of verification annotations, in addition to id userName, other parameters do not pass will be null return, that separate to open an interface to do rename? Or encapsulate a separate entity class with only id and userName?

不不不,肯定是能复用就复用!要是像上面这么玩,cto不得被你气吐血咯~

接下来我就来聊聊这个怎么解决这个问题吧,其实还是用@Validated,它有做分组功能。怎么理解呢?

意思是在新增接口我们给新增标识的校验注解, 在修改接口使用修改标识的校验注解,这样就不会新增修改接口冲突(分组校验(多场景的复杂校验))。如下:

第一步:先为不同接口加上分组标志;

@NotNull(message = "用户id不能为空", groups = UpdateGroup.class)
private Integer id;
复制代码

这个UpdateGroup.class是干什么用的,其实就是我们自定义的一个标识用来告诉程序不同的接口校验不同的属性罢了;然后在新增接口上也同样加上 AddGroup.class 的分组标志,即可;

	@PostMapping(value = "/update")
	@ApiOperation(value = "用户修改", notes = "根据userId对用户信息修改")
	public ResultResponse updateUser(@Validated(UpdateGroup.class) UserEntity userEntity, BindingResult bindingResult) {
//		if (bindingResult.hasErrors()) {
//			Map<String, String> map = new HashMap<>();
//			//1、result.getFieldErrors()获取校验的错误结果对象然后遍历
//			for (FieldError fieldError : bindingResult.getFieldErrors()) {
//				//FieldError 获取到错误提示
//				String message = fieldError.getDefaultMessage();
//				//获取错误的属性的名字
//				String field = fieldError.getField();
//				map.put(field, message);
//			}
//			return new ResultResponse<>(map);
//		}
		return new ResultResponse<>(testService.updateById(userEntity));
	}
复制代码

如下定义分组标识:

//新增标识

public @interface AddGroup {
}
复制代码

//修改标识

public @interface UpdateGroup {
}
复制代码

//查询标识

public @interface QueryGroup {
}
复制代码

效果演示1:请求用户新增接口,先不传id,验证是否会提示要求传id

​效果演示2:请求用户修改接口,也不传id,验证是否会提示要求传id

​效果演示3:请求用户修改接口:传id,看结果,验证是否会有必传参数提示:

有朋友可能就会问了,要是既UpdateGroup标识,也AddGroup 分组标识的,怎么理解?

像这种情景,就表示无论是新增操作还是修改操作都会校验该属性,如下:email就新增还是修改操作都会对其进行参数校验,校验是否满足邮箱格式。

@Email(message = "邮箱格式不正确", groups = {UpdateGroup.class, AddGroup.class})
@ApiModelProperty(value = "邮箱")
private String email;
复制代码

如果只加上修改标识不加新增标识的话,这个就只会在修改操作时会触发校验该属性。

@NotNull(message = "用户id不能为空", groups = UpdateGroup.class)
@ApiModelProperty(value = "id自增列")
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
复制代码

场景四:

终于讲到第四大场景了,给大家假设这么一个场景,就一个实体中,存在嵌套类,举个栗子,如下,可以看到Company对象中含有User对象做为自己的属性,那么在进行Company校验时,user内的属性会被校验吗?如果不会又该怎么做才会进行嵌套类校验呢?大家想过没有?

科普一下:嵌套类就是一个类中包含另一个类!

	@NotNull(message = "用户对象不能为空", groups = {UpdateGroup.class})
    //注解加载bean属性上,表示当前属性不是数据库的字段,但在项目中必须使用,这样在新增等使用bean的时候,mybatis-plus就会忽略这个,不会报错;
	@TableField(exist = false)
	private UserEntity userEntity;
复制代码

就不给大家卖关子了,很简单,只需要用到@Validated 的嵌套验证即可;

如下图Company类中只能校验UserEntity是否为空,却不能校验UserEntity类中的userName、userPwd等属性是否为空;

如果想要嵌套验证,必须在Company对象的UserEntity字段上面标明这个字段的实体也要进行验证!

由于@Validated不能用在成员属性(字段)上,但是@Valid能加在成员属性(字段)上,而且@Valid类注解上也说明了它支持嵌套验证功能;

那么我们能够推断出:@Valid 加在方法参数时并不能够自动进行嵌套验证,而是用在需要嵌套验证类的相应字段上,来配合方法参数上@Validated或@Valid来进行嵌套验证;

在该需要做嵌套校验的属性上加@Valid 注解即可; 如下:

@Valid
@NotNull(message = "用户对象不能为空", groups = {UpdateGroup.class})
@TableField(exist = false)
private UserEntity userEntity;

@PostMapping(value = "/updateCompanyInfo")
@ApiOperation(value = "公司修改", notes = "公司信息修改")
public ResultResponse updateCompanyInfo(@Validated(UpdateGroup.class) Company company, BindingResult bindingResult) {
   return new ResultResponse<>(iCompanyService.updateById(company));
}
复制代码

效果演示1:请求公司信息修改接口,不传参数userEntity,验证是否会提示嵌套类里头的属性为空。

​效果演示2:还是请求公司信息修改接口,但传参数userEntity对象,验证是否会提示嵌套类里头的属性为空。

​如上截图结果,显然校验出了userEntity对象中的必传属性,表示 @Valid 确实可以实现嵌套类的验证!是不是就很nice~

OK,以上就是本期的所有干货内容啦!听完我的课,是不是该有所表示呢,要是我,果断就给它pia的一下点亮!

再不行,就当支持bug菌熬夜爆肝码了两万多字的份上,给个鼓励啦。

原创不易

请鼓励支持一下咯

点赞三连

走起

各位兄弟姐妹萌

bug菌不胜感激

~

~~~

若是还不够吃,bug菌还有!要不再投点?

往期热文推荐:

  • 在Ubuntu上使用IDEA搞开发是种什么体验?没想到竟是…最后有惊喜!
  • 520夜我花了288大洋就得到了小师妹青睐,原因竟是…一定要看到最后!
  • 你一定没用过的代码生成工具,好不好用你们说了算
  • 如何实现Springboot项目保存本地系统日志文件,超详细,你值得拥有!
  • 使用MultipartFile实现图片指定路径上传下载并使用postman测试教程 | 附完整源码,强烈建议收藏!
  • 一篇文带你零基础玩转mysql触发器 | 超级干货,建议收藏

若想解锁更多高阶隐藏玩法,请关注bug菌的专栏《收藏夹吃灰系列》。bug菌会持续更新哒,只因你的特别关注,我定不负所望~

Attached with the above example source code:

Company

package com.system.xiaoma.entity; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.system.xiaoma.model.groups.AddGroup; import com.system.xiaoma.model.groups.UpdateGroup; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import javax.validation.Valid; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; /** * ApiModel(value = "ApiModel ", @data public class Company extends BaseEntity {private static Final Long serialVersionUID = 1L; @notnull (message = "company ID cannot be empty ", Groups = updateGroup.class) @apiModelProperty (value = "company_id") @tableId (value = "company_id", type = IdType.AUTO) private Integer companyId; @notblank (message = "company name cannot be blank ", groups = {updategroup.class, Addgroup.class}) @APIModelProperty (value = "companyName ") private String companyName; @valid@notnull (message = "user object cannot be empty ", groups = {updategroup.class}) Mybatis - Plus will ignore this error when adding and using beans. @TableField(exist = false) private UserEntity userEntity; }Copy the code

UserEntity

package com.system.xiaoma.entity; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.system.xiaoma.model.groups.AddGroup; import com.system.xiaoma.model.groups.UpdateGroup; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import org.hibernate.validator.constraints.Length; import javax.validation.constraints.*; /** * @author luoYong * @date 2021-06-13 11:13 */ @tablename (value = "user") @apiModel (value = "user"), Description = "User object ") @data Public class UserEntity extends BaseEntity {private Static Final Long serialVersionUID = 1L; @notnull (message = "user id cannot be null ", groups = updateGroup.class) @apiModelProperty (value = "id") @tableId (value = "id", type = IdType.AUTO) private Integer id; @notblank (message = "user name cannot be blank ", groups = {updategroup.class, Addgroup.class}) @APIModelProperty (value = "userName ") private String userName; @min (value = 1,message = "input age < 1", groups = {updategroup.class, Addgroup.class}) @max (value = 150,message = "input age cannot exceed 150", groups = {updategroup.class, Addgroup.class}) @notnull (message = "input age cannot be empty ", groups = {updategroup.class, Addgroup.class}) @APIModelProperty (value = "password ") private Integer userAge; @notblank (message = "password cannot be blank ", groups = {updategroup.class, addgroup.class}) @length (min = 6, Max = 10,message = "Password length is at least 6 but not more than 10 characters!" , groups = {updateGroup.class, addGroup.class}) @APIModelProperty (value = "password ") private String userPwd; @email (message = "Email format incorrect ", groups = {updategroup.class, Addgroup.class}) @APIModelProperty (value = "email ") private String Email; }Copy the code

TestController

package com.system.xiaoma.controller; import com.system.xiaoma.entity.Company; import com.system.xiaoma.entity.UserEntity; import com.system.xiaoma.model.groups.AddGroup; import com.system.xiaoma.model.groups.UpdateGroup; import com.system.xiaoma.service.ICompanyService; import com.system.xiaoma.service.TestService; import com.system.xiaoma.vo.ResultResponse; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.BindingResult; import org.springframework.validation.FieldError; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.HashMap; import java.util.Map; /** * @author luoYong * @date 2021-06-13 11:12 */ @restController @API (tags = "test") @requestMapping ("/test") public class TestController { @Autowired private TestService testService; @Autowired private ICompanyService iCompanyService; @postmapping (value = "/saveUser") @apiOperation (value = "User add ", Public ResultResponse saveUser(@Validated(addGroup.class) UserEntity UserEntity, BindingResult BindingResult) {/** * result.haserrors () returns false if the value passed from the front does not correspond to the annotation annotated in the entity class. For example, @notBlank (message = "user name cannot be blank ") in the name field of the entity returns false without passing the name; */ if (bindingResult.hasErrors()) { Map<String, String> map = new HashMap<>(); //1, result.getFielderrors (); BindingResult. GetFieldErrors ()) {/ / FieldError get error message String message. = FieldError getDefaultMessage (); String field = fielderor.getField (); map.put(field, message); } return new ResultResponse<>(map); } return new ResultResponse<>(testService.save(userEntity)); } @postmapping (value = "/update") @apiOperation (value = "user modify ", Notes = "Modify user information based on userId ") public ResultResponse updateUser(@Validated(updateGroup.class) UserEntity UserEntity, BindingResult bindingResult) { // if (bindingResult.hasErrors()) { // Map<String, String> map = new HashMap<>(); // //1, result.getFielderrors (); // for (FieldError FieldError: BindingResult. GetFieldErrors ()) {/ / / / FieldError get error message / / String message. = FieldError getDefaultMessage (); // // get the name of the wrong attribute // String field = fielderor.getField (); // map.put(field, message); // } // return new ResultResponse<>(map); // } return new ResultResponse<>(testService.updateById(userEntity)); } @postmapping (value = "/updateCompanyInfo") @apiOperation (value = "", Public ResultResponse updateCompanyInfo(@Validated(updategroup.class) Company Company, BindingResult bindingResult) { // if (bindingResult.hasErrors()) { // Map<String, String> map = new HashMap<>(); // for (FieldError fieldError : BindingResult. GetFieldErrors ()) {/ / / / FieldError get error message / / String message. = FieldError getDefaultMessage (); // // get the name of the wrong attribute // String field = fielderor.getField (); // map.put(field, message); // } // return new ResultResponse<>(map); // } return new ResultResponse<>(iCompanyService.updateById(company)); }}Copy the code

ValidAspect

package com.system.xiaoma.aspect.valid; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.system.xiaoma.exception.ParamsException; import com.system.xiaoma.vo.ResultResponse; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import org.springframework.validation.BindException; import org.springframework.validation.BindingResult; import org.springframework.validation.FieldError; import javax.annotation.PostConstruct; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @component public class ValidAspect {private ObjectMapper ObjectMapper = new ObjectMapper(); @component public class ValidAspect {private ObjectMapper ObjectMapper = new ObjectMapper(); / / @postconstruct public void init() {objectmapper. configure(jsonparser.feature.allow_single_quotes, true); objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true); objectMapper.configure(JsonParser.Feature.IGNORE_UNDEFINED, true); objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); objectMapper.enable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); objectMapper.enable(SerializationFeature.WRITE_ENUMS_USING_INDEX); } @Order(10) @Around("execution(public * com.system.xiaoma.controller.*.*(..) )") public ResultResponse validAspect1(ProceedingJoinPoint pjp) throws Throwable { BindingResult bindingResult = getBindingResult(pjp); if (bindingResult == null || ! bindingResult.hasErrors()) { ResultResponse resultResponse = new ResultResponse(); ResultResponse o = (ResultResponse) pjp.proceed(pjp.getArgs()); resultResponse.setData(o.getData()); return resultResponse; } else { Map<String, String> map = new HashMap<>(); List<FieldError> errors = bindingResult.getFieldErrors(); errors.forEach(e -> map.put(e.getField(),e.getDefaultMessage())); return new ResultResponse(map); @param PJP pointcut */ private BindingResult getBindingResult(ProceedingJoinPoint PJP) { Object[] args = pjp.getArgs(); for (Object arg : args) { if (arg instanceof BindingResult) { return (BindingResult) arg; } } return null; }}Copy the code

AddGroup

package com.system.xiaoma.model.groups;

public @interface AddGroup {
}
Copy the code

UpdateGroup

package com.system.xiaoma.model.groups;

public @interface UpdateGroup {
}
Copy the code

If this article has been helpful, please put your thumb in the bottom left corner of the article. (# ^. ^ #);

If you like the articles shared by Bug bug, please send bug bug a note! The danjun ‘ᴗ, you guys will have a cameo appearance with you.

If you have any questions about this article, please leave a comment below or join the group [Group number: 708072830].

In view of limited personal experience, all views and technical research points, if you have any objection, please directly reply to participate in the discussion (no offensive comments, thank you);

Copyright notice: This article is the blogger’s original article, reprint please attach the original source link and this article statement, all rights reserved, piracy will investigate! (* ^ del ^ *).