javax.validation分组校验(详解版)

您所在的位置:网站首页 notblank注解中groups javax.validation分组校验(详解版)

javax.validation分组校验(详解版)

#javax.validation分组校验(详解版)| 来源: 网络整理| 查看: 265

为什么使用分组?场景:比如: package com.springbootvalidation.entity; import com.springbootvalidation.common.BaseModel; import com.springbootvalidation.common.Group; import lombok.Data; import javax.validation.constraints.NotBlank; /** * Created by Administrator on 2021/9/20. */ @Data public class UserEntity extends BaseModel{ private static final long serialVersionUID = -6967633787950779639L; /* 没有加分组groups的属于Default默认分组。 添加分组groups的属于自定义分组,不属于默认分组。 validation校验默认使用默认分组校验,不会校验自定义分组。 因此如果需要校验自定义分组的字段,需要校验的时候加上自定义分组,如: ValidationUtil.validate(userEntity, Default.class, Group.AddGroup.class); 或者在controller方法体加上@RequestBody @Validated({Default.class, Group.AddGroup.class}) UserEntity userEntity, BindingResult bindingResult */ /** * 用户名 */ @NotBlank(message = "用户名不能为空!",groups = Group.AddGroup.class) private String userName; /** * 密码 */ @NotBlank(message = "密码不能为空!") private String password; } 在用户注册的时候或者登录的时候,我需要用户名和密码都进行非空校验。但是我在对用户进行分组的时候,我有一个分组实体,里面有分组名称和List。那么我在保存的时候,我会保存一个group和user的关系表,里面存分组id和userName。这时候我在保存关系的时候,我只需要对用户名进行非空校验,而不需要对密码进行非空校验。这时候该怎么办呢?再定义一个user实体password不加注解校验?或者单独程序校验而不用注解校验?其实javax.validation已经为我们考虑好了,不用那么麻烦。只需要对要校验的字段进行分组即可。 javax.validation分组校验:注意:没有加分组groups的属于Default默认分组。添加分组groups的属于自定义分组,不属于默认分组。validation校验默认使用默认分组校验,不会校验自定义分组。因此如果需要校验自定义分组的字段,需要校验的时候加上分组,如:ValidationUtil.validate(userEntity, Default.class, Group.AddGroup.class);或者在controller方法入参加上@RequestBody @Validated({Default.class, Group.AddGroup.class}) UserEntity userEntity, BindingResult bindingResult不想要校验某个分组的字段,把某个分组给去掉就好了。1.pom依赖: 4.0.0 com.springbootvalidation springboot-validation 1.0-SNAPSHOT 5.1.2 org.springframework.boot spring-boot-starter-parent 2.1.7.RELEASE org.springframework.boot spring-boot-starter-web org.projectlombok lombok com.github.pagehelper pagehelper ${pagehelper.version}

2.项目结构:

 BaseModel:

package com.springbootvalidation.common; import com.fasterxml.jackson.annotation.JsonFormat; import lombok.Data; import org.springframework.format.annotation.DateTimeFormat; import java.io.Serializable; import java.util.Date; /** * Created by Administrator on 2021/9/20. */ @Data public class BaseModel implements Serializable{ private static final long serialVersionUID = 4559817637980468562L; /** * 创建人 */ private String createUser; /** * 创建时间 */ @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private Date createTime; /** * 修改人 */ private String updateUser; /** * 修改时间 */ @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private Date updateTime; }

BaseResponse:

package com.springbootvalidation.common; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import com.github.pagehelper.PageInfo; import lombok.Getter; import java.util.HashMap; import java.util.Map; /** * 返回实体 * @className: BaseResponse * @author: admin * @date: 2021/9/20 12:36 */ @Getter @JsonInclude(JsonInclude.Include.NON_NULL) public class BaseResponse { /** * 成功返回值 */ private final static String SUCCESS_CODE = CodeConts.SUCCESS; /** * 失败默认返回值 */ private final static String FAILED_CODE = CodeConts.FAILURE; /** * 成功回复报文包含的对象 */ @JsonProperty("data") private final Object data; /** * 返回值 */ @JsonProperty("status") private final String status; /** * 返回msg */ @JsonProperty("message") private final String message; /** * 返回msg */ @JsonProperty("pages") private final Integer pages; /** * 返回msg */ @JsonProperty("pageNum") private final Integer pageNum; /** * 返回msg */ @JsonProperty("pageSize") private final Integer pageSize; /** * 其余参数 */ @JsonProperty("params") private final Map params; private BaseResponse(final Object data, final String status, final String message, final Integer pages, final Integer pageNum, final Integer pageSize, final Map params) { this.data = data; this.status = status; this.message = message; this.params = params; this.pages = pages; this.pageNum = pageNum; this.pageSize = pageSize; } /** * 构造成功报文builder * * @return 成功报文builder builder */ public static Builder successCustom() { return successCustom("操作成功!"); } /** * 构造成功报文builder * * @param message the message * @return builder */ public static Builder successCustom(final String message) { return new Builder(SUCCESS_CODE, message); } /** * 请求成功返回状态码和提示 * * @param successCode 状态码 * @param message 提示信息 * @return builder */ public static Builder successCustom(final String successCode, final String message) { return new Builder(successCode, message); } /** * 构造错误返回报文builder * * @param errorCode 错误码 * @param errorMsg 错误信息 * @return 错误返回报文builder builder */ public static Builder failedCustom(final String errorCode, final String errorMsg) { return new Builder(errorCode, errorMsg); } /** * Failed custom builder. * * @param errorMsg the error msg * @return the builder */ public static Builder failedCustom(final String errorMsg) { return new Builder(FAILED_CODE, errorMsg); } /** * The type Builder. */ public static final class Builder { /** * 返回值 */ private final String status; /** * msg */ private final String message; /** * 返回msg */ private Integer pages; /** * 返回msg */ private Integer pageNum; /** * 返回msg */ private Integer pageSize; /** * 其他参数 */ private final Map params = new HashMap(); /** * 任意可json化的对象 */ private Object data; private Builder(final String status, final String message) { this.status = status; this.message = message; } /** * 添加参数信息 * * @param key the key * @param value the value * @return builder */ public Builder addParam(final String key, final String value) { this.params.put(key, value); return this; } /** * 设置result data * * @param data the data * @return data */ public Builder setData(final Object data) { this.data = data; return this; } /** * 设置result 分页 * * @param pageInfo the page info * @return data */ public Builder setData(final PageInfo pageInfo) { this.data = pageInfo.getList(); //当前页 this.pageNum = pageInfo.getPageNum(); this.pageSize = pageInfo.getPageSize(); this.pages = pageInfo.getPages(); return this; } /** * build BaseResponse * * @return base response */ public BaseResponse build() { return new BaseResponse(this.data == null ? "" : this.data, this.status, this.message, this.pages, this.pageNum, this.pageSize, this.params); } } }

CodeConts:

package com.springbootvalidation.common; /** * Created by Administrator on 2021/9/20. */ public class CodeConts { public static String SUCCESS = "1000"; public static String FAILURE = "1001"; public static String SYSTEM_EXCEPTION = "4000"; }

Group:

package com.springbootvalidation.common; /** * 验证分组 * @className: Group * @author: liuyachao * @date: 2021/9/20 12:56 */ public class Group { public interface AddGroup{} }

UserController:

package com.springbootvalidation.controller; import com.springbootvalidation.common.BaseResponse; import com.springbootvalidation.common.CodeConts; import com.springbootvalidation.entity.UserEntity; import com.springbootvalidation.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.BindingResult; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.validation.groups.Default; /** * Created by Administrator on 2021/9/20. */ @RestController @RequestMapping("/user") public class UserController { @Autowired private UserService userService; @PostMapping("/addUser") public BaseResponse addUser(@RequestBody @Validated({Default.class}) UserEntity userEntity, BindingResult bindingResult){ try { if(bindingResult.hasErrors()){ return BaseResponse.failedCustom(bindingResult.getFieldError().getDefaultMessage()).build(); } return userService.addUser(userEntity); }catch (Exception e){ e.printStackTrace(); return BaseResponse.failedCustom(CodeConts.SYSTEM_EXCEPTION,"系统异常").build(); } } @PostMapping("/updUser") public BaseResponse updUser(@RequestBody UserEntity userEntity){ try { return userService.updUser(userEntity); }catch (Exception e){ e.printStackTrace(); return BaseResponse.failedCustom(CodeConts.SYSTEM_EXCEPTION,"系统异常").build(); } } }

UserEntity:

package com.springbootvalidation.entity; import com.springbootvalidation.common.BaseModel; import com.springbootvalidation.common.Group; import lombok.Data; import javax.validation.constraints.NotBlank; /** * Created by Administrator on 2021/9/20. */ @Data public class UserEntity extends BaseModel{ private static final long serialVersionUID = -6967633787950779639L; /* 没有加分组groups的属于Default默认分组。 添加分组groups的属于分组,不属于默认分组。 validation校验使用默认分组校验,不会校验自定义分组。 因此如果需要校验自定义分组的字段,需要校验的时候加上分组,如: ValidationUtil.validate(userEntity, Default.class, Group.AddGroup.class); 或者在controller方法体加上@RequestBody @Validated({Default.class, Group.AddGroup.class}) UserEntity userEntity, BindingResult bindingResult */ /** * 用户名 */ @NotBlank(message = "用户名不能为空!",groups = Group.AddGroup.class) private String userName; /** * 密码 */ @NotBlank(message = "密码不能为空!") private String password; }

UserService:

package com.springbootvalidation.service; import com.springbootvalidation.common.BaseResponse; import com.springbootvalidation.entity.UserEntity; /** * Created by Administrator on 2021/9/20. */ public interface UserService { BaseResponse addUser(UserEntity userEntity); BaseResponse updUser(UserEntity userEntity); }

UserServiceImpl:

package com.springbootvalidation.service.impl; import com.springbootvalidation.common.BaseResponse; import com.springbootvalidation.common.CodeConts; import com.springbootvalidation.common.Group; import com.springbootvalidation.entity.UserEntity; import com.springbootvalidation.service.UserService; import com.springbootvalidation.utils.ValidationUtil; import org.springframework.stereotype.Service; import javax.validation.groups.Default; import java.util.List; /** * Created by Administrator on 2021/9/20. */ @Service public class UserServiceImpl implements UserService{ @Override public BaseResponse addUser(UserEntity userEntity) { // BaseResponse validateResult = validateParam(userEntity); // if(!validateResult.getStatus().equals(CodeConts.SUCCESS)){ // return validateResult; // } System.out.println("插入成功"); return BaseResponse.successCustom().build(); } private BaseResponse validateParam(UserEntity userEntity) { List validateError = ValidationUtil.validate(userEntity, Default.class, Group.AddGroup.class); if (validateError != null && validateError.size() > 0) { // validateError.get(0) return BaseResponse.failedCustom(validateError.get(0)).build(); } return BaseResponse.successCustom().build(); } @Override public BaseResponse updUser(UserEntity userEntity) { System.out.println("更新成功"); return BaseResponse.successCustom().build(); } }

ValidationUtil:

package com.springbootvalidation.utils; import javax.validation.ConstraintViolation; import javax.validation.Validation; import javax.validation.Validator; import javax.validation.ValidatorFactory; import javax.xml.bind.ValidationException; import java.util.ArrayList; import java.util.List; import java.util.Set; /** * @description: 校验工具类 * @author liuyachao * @date 2021/9/18 16:38 */ public class ValidationUtil { private static Validator validator; static { ValidatorFactory vf = Validation.buildDefaultValidatorFactory(); validator = vf.getValidator(); } /** * javax.validation注解校验 * @throws ValidationException * @throws ValidationException * @Description: 校验方法 * @param t 将要校验的对象 * @throws ValidationException * void * @throws */ public static List validate(T t){ return validate(t,null); } public static List validate(T t, Class... groups){ Set set; if(groups != null && groups.length > 0){ set = validator.validate(t,groups); }else{ set = validator.validate(t); } List validateError = new ArrayList(); if(set.size()>0){ for(ConstraintViolation val : set){ validateError.add(val.getMessage()); } } return validateError; } }

App:

package com.springbootvalidation; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; /** * Created by Administrator on 2021/9/20. */ @SpringBootApplication public class App { public static void main(String[] args) { SpringApplication.run(App.class,args); } }

我们看下在controller的方法中校验:

@PostMapping("/addUser") public BaseResponse addUser(@RequestBody @Validated({Default.class}) UserEntity userEntity, BindingResult bindingResult){ try { if(bindingResult.hasErrors()){ return BaseResponse.failedCustom(bindingResult.getFieldError().getDefaultMessage()).build(); } return userService.addUser(userEntity); }catch (Exception e){ e.printStackTrace(); return BaseResponse.failedCustom(CodeConts.SYSTEM_EXCEPTION,"系统异常").build(); } }

 javax.validation默认是Default默认分组。上面@Validated({Default.class})表示默认分组,也可以只用@Validated或者@Valid表示,去掉({Default.class}),这样效果等同于@Validated({Default.class})表示只是用默认分组校验。

默认分组校验不会校验AddGroup分组的字段。即不会校验userName字段不能为空。

这样的话如果其他地方用到此实体,而不想要校验userName,那么只用默认分组校验就可以了。因为默认分组校验只会校验默认分组的字段(即不加任何分组的字段),不会校验自定义分组的字段(如:加了groups = Group.AddGroup.class)。

如果注册或者添加的时候,既要校验userName,又要校验password。那么只需要再controller的分组上加上自定义分组的class即可。如下:

@RequestBody @Validated({Default.class, Group.AddGroup.class}) UserEntity userEntity, BindingResult bindingResult

总结:

那些不管在哪儿使用都要校验的字段,我们用默认分组(不加任何分组)即可。如果有些字段在这里需要校验,而在其他地方不需要校验,那么把这些字段加上分组即可,

如果要校验自定义分组的字段,只需要在校验的时候加上Group.AddGroup.class即可。

只校验默认分组的字段:只需要Default.class。

只校验自定义分组的字段:只需要Group.AddGroup.class。

需要校验默认分组又需要校验自定义分组的字段:加上Default.class,Group.AddGroup.class。

分组的作用就是区分有些字段我需要校验,而有些字段我不需要校验,那么我校验的时候选择要校验的分组即可,不校验的字段的分组不选择。

校验字段的方式有两种:

方式1:在controller的方法入参中加上@Validated({Default.class, Group.AddGroup.class})和BindingResult bindingResult。

方式2:用ValidationUtil工具类校验,ValidationUtil工具类的校验使得校验不局限在controller的方法入参中。想在任何时候,任何地方校验,就在哪里添加工具类的校验。

方式1:这是controller方法中加的分组校验方式:

@PostMapping("/addUser") public BaseResponse addUser(@RequestBody @Validated({Default.class, Group.AddGroup.class}) UserEntity userEntity, BindingResult bindingResult){ try { if(bindingResult.hasErrors()){ return BaseResponse.failedCustom(bindingResult.getFieldError().getDefaultMessage()).build(); } return userService.addUser(userEntity); }catch (Exception e){ e.printStackTrace(); return BaseResponse.failedCustom(CodeConts.SYSTEM_EXCEPTION,"系统异常").build(); } }

在@Validated({Default.class, Group.AddGroup.class})中自行添加和删除要校验的分组。

方式2:使用ValidationUtil工具类校验(ValidationUtil工具类的代码已贴在上面),下面是工具类的使用:

BaseResponse validateResult = validateParam(userEntity); if(!validateResult.getStatus().equals(CodeConts.SUCCESS)){ return validateResult; } private BaseResponse validateParam(UserEntity userEntity) { List validateError = ValidationUtil.validate(userEntity, Default.class, Group.AddGroup.class); if (validateError != null && validateError.size() > 0) { // validateError.get(0) return BaseResponse.failedCustom(validateError.get(0)).build(); } return BaseResponse.successCustom().build(); }

在ValidationUtil.validate(userEntity, Default.class, Group.AddGroup.class)自行添加或删除需要校验的分组。

校验分组方便区分了同一个实体中哪些字段我们想要校验,哪些字段在另外一些地方又不想要校验。

我们只需要将实体中的字段分组,然后校验的时候选择分组即可。

3.测试结果:

1.只想要校验Default默认分组(不加任何分组的字段,@NotBlank(message = "密码不能为空!")):

List validateError = ValidationUtil.validate(userEntity, Default.class);//, Group.AddGroup.class

 userName是自定义分组的字段:

@NotBlank(message = "用户名不能为空!",groups = Group.AddGroup.class)

这个字段不在默认分组中,不会校验。

password在默认分组中,会校验:

 

 2.只想要校验AddGroup的字段(@NotBlank(message = "用户名不能为空!",groups = Group.AddGroup.class),带groups的):

List validateError = ValidationUtil.validate(userEntity, Group.AddGroup.class);

 userName是自定义分组的字段,为空,进行了非空校验。

password是默认分组的字段,不是自定义分组的字段,不会校验:

 

 3.既想要校验默认分组字段又想要校验自定义分组字段,那么把要校验的字段的分组都加上:

List validateError = ValidationUtil.validate(userEntity, Default.class, Group.AddGroup.class);

userName为空:

 password为空:

 两个字段都进行了校验。

 不同的分组,校验的字段不同。这样实现了对是否需要校验的字段的区分。即有些地方我需要校验某些字段,有些地方我不需要校验那些字段。

 



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3