一般系统对表单的提交都会提供一定的校验,分为前台校验和后台校验,前台校验主要为了减轻服
务器的负担,后台校验增加系统安全性。
javax.validation
的一系列注解可以帮我们完成参数校验,免去繁琐的串行校验
什么是javax.validation
JSR303 是一套JavaBean参数校验的标准,它定义了很多常用的校验注解,我们可以直接将这些
注解加在我们JavaBean的属性上面(面向注解编程的时代),就可以在需要校验的时候进行校验了,
在SpringBoot中已经包含在starter-web中,再其他项目中可以引用依赖,并自行调整版本。
步骤:
1. @Validated 声明要检查的参数
/***
* 新增Member
* @param member
* @return
*/
@PostMapping("/save")
public ResponseEntity<Object> add(@RequestBody @Validated Member member){
log.info("参数 : {}", member);
memberService.add(member);
return ResponseEntity.ok("success");
}
2. 对参数的字段进行注解标注
@NotBlank(message = "账号不能为空!")
private String account;
@NotBlank(message = "用户名不能为空")
private String name;
@Email(message = "邮箱格式不对")
private String mail;
@Pattern(regexp = "^[1][3,4,5,6,7,8,9][0-9]{9}$", message = "手机号格式有误")
private String mobile;
3. 在全局校验中增加校验异常
MethodArgumentNotValidException
是springBoot中进行绑定参数校验时的异常
/**
* 方法参数校验
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<Object> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
return ResponseEntity.accepted().body(ErrorVo.build("1000",e.getBindingResult().getFieldError().getDefaultMessage()));
}
全代码:
package com.nanjing.modules.resource.model;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import com.nanjing.common.Constants;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.*;
import lombok.experimental.Accessors;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
/**
* @program: backend
* @since: 2021-11-12 16:36:58
**/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("member")
@ApiModel(value="Member对象", description="成员")
public class Member implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "主键")
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
@NotBlank(message = "账号不能为空!")
private String account;
@NotBlank(message = "用户名不能为空")
private String name;
@ApiModelProperty(value = "部门代码")
private String department;
@Pattern(regexp = "^[1][3,4,5,6,7,8,9][0-9]{9}$", message = "手机号格式有误")
private String mobile;
@Email(message = "邮箱格式不对")
private String mail;
@ApiModelProperty(value = "性别 M 男 F女")
private String gender;
private String birthYear;
@ApiModelProperty(value = "Associate专科 Bachelor 本科 Master 硕士 Doctor 博士")
private String educationBg;
@ApiModelProperty(value = "工作经验(工龄)")
private Integer experience;
private Integer companyId;
@JsonFormat(pattern= Constants.DATE_FORMAT, timezone = Constants.TIME_ZONE)
private Date onBoardDate;
@JsonFormat(pattern= Constants.DATE_FORMAT, timezone = Constants.TIME_ZONE)
private Date offBoardDate;
private String comment;
@ApiModelProperty(value = "0代表在职,1代表离职")
private Integer isTermination;
}
package com.nanjing.modules.member;
import com.nanjing.common.CommonResult;
import com.nanjing.modules.resource.model.Member;
import com.nanjing.modules.resource.service.MemberService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.List;
/**
* @Date 2021/12/6
*/
@RestController
@RequestMapping("/member")
public class MemberController {
private static final Logger log = LogManager.getLogger("base");
@Autowired
private MemberService memberService;
/**
* Member列表
* @param page
* @param size
* @param member
* @return
*/
@PostMapping("/memberList/{page}/{size}")
public ResponseEntity<Object> memberList(@PathVariable Integer page,
@PathVariable Integer size,
@RequestBody(required = false) Member member) {
PageHelper.startPage(page,size);
List<Member> memberList = memberService.queryMemberPage(member);
PageInfo<Member> pageInfo = new PageInfo<>(memberList);
return ResponseEntity.ok(CommonResult.map("pageResult", pageInfo));
}
/**
* Member
* @param id
* @return
*/
@GetMapping("/member/{id}")
public ResponseEntity<Object> queryMemberById(@PathVariable String id) {
Member member = memberService.queryMemberById(id);
return ResponseEntity.ok(CommonResult.map("member", member));
}
/***
* 新增Member
* @param member
* @return
*/
@PostMapping("/save")
public ResponseEntity<Object> add(@RequestBody @Validated Member member){
log.info("参数 : {}", member);
memberService.add(member);
return ResponseEntity.ok("success");
}
/***
* 更新Member
* @param member
* @return
*/
@PutMapping(value="/update/{id}")
public ResponseEntity<Object> update(@RequestBody Member member,@PathVariable Integer id) {
member.setId(id);
memberService.update(member);
return ResponseEntity.ok("success");
}
/***
* 根据ID删除
* @param id
* @return
*/
@DeleteMapping(value = "/delete/{id}")
public ResponseEntity<Object> delete(@PathVariable Integer id){
memberService.delete(id);
return ResponseEntity.ok("success");
}
}
package com.nanjing.component;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import com.nanjing.component.ErrorCodeEnum.*;
import java.util.List;
/**
* @program: backend
* @description:
* @since: 2021-11-18 15:54:55
**/
@RestControllerAdvice
public class GlobalExceptionHandler {
@ResponseBody
@ExceptionHandler(BaseException.class)
public ResponseEntity<ErrorVo> handleBaseException(BaseException exception){
return ResponseEntity.status(exception.getHttpCode())
.body(ErrorVo.build(exception.getBizCode(), exception.getMessage()));
}
/**
* 运行异常处理
*
* @param error 异常对象
* @return 响应对象
*/
@ExceptionHandler(RuntimeException.class)
public ResponseEntity<Object> handleException(RuntimeException error) {
error.printStackTrace();
return ResponseEntity.status(ErrorCodeEnum.SERVER_ERROR.getHttpCode())
.body(ErrorVo.build(ErrorCodeEnum.SERVER_ERROR.getBizCode(), error.getMessage()));
}
/**
* 其他系统异常处理
*
* @param error 异常对象
* @return 响应对象
*/
@ExceptionHandler(Exception.class)
public ResponseEntity<Object> handleException(Exception error) {
error.printStackTrace();
return ResponseEntity.status(ErrorCodeEnum.SERVER_ERROR.getHttpCode())
.body(ErrorVo.build(ErrorCodeEnum.SERVER_ERROR.getBizCode(), error.getMessage()));
}
/**
* 方法参数校验
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<Object> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
return ResponseEntity.accepted().body(ErrorVo.build("1000",e.getBindingResult().getFieldError().getDefaultMessage()));
}
/**
* 校验异常
*
* @param ex MethodArgumentNotValidException
* @return Response
*/
/*@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseBody
public Response handleConstraintViolationException(MethodArgumentNotValidException ex) {
//获取所有错误异常
List<ObjectError> allErrors = ex.getBindingResult().getAllErrors();
//只返回第一个信息
ObjectError error = allErrors.get(0);
//返回自定义信息格式
return ResponseHelper.fail(error.getDefaultMessage());
}*/
}
postman测试:
拓展1:
自定义参数注解
拓展2:
分组校验
有的时候,我们在某一个实体类中定义了很多校验规则,但是在某一次业务处理中,并不需要这么
多校验规则,此时就可以使用分组校验。具体步骤如下。
1,创建分组接口
首先创建两个分组接口:
1 2 3 4 5 |
|
2,在实体类中添加分组信息
这次在注解中添加了groups属性,表示该校验规则所属的分组:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
|
3,在Controller中指定校验分组
接下来在@Validated注解中指定校验分组,这里的@Validated(ValidationGroup2.class) 表示这
里的校验使用ValidationGroup2分组的校验规则(只校验用户地址、邮箱地址是否为空):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
@Null 被注释的元素必须为 null
@NotNull 被注释的元素必须不为 null
@AssertTrue 被注释的元素必须为 true
@AssertFalse 被注释的元素必须为 false
@Min(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@Max(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMin(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@DecimalMax(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@Size(max=, min=) 被注释的元素的大小必须在指定的范围内
@Digits (integer, fraction) 被注释的元素必须是一个数字,其值必须在可接受的范围内
@Past 被注释的元素必须是一个过去的日期
@Future 被注释的元素必须是一个将来的日期
@Pattern(regex=,flag=) 被注释的元素必须符合指定的正则表达式
Hibernate Validator提供的校验注解:
@NotBlank(message =) 验证字符串非null,且trim后长度必须大于0
@Email 被注释的元素必须是电子邮箱地址
@Length(min=,max=) 被注释的字符串的大小必须在指定的范围内
@NotEmpty 被注释的字符串的必须非空
@Range(min=,max=,message=) 被注释的元素必须在合适的范围内
@AssertFalse 校验false
@AssertTrue 校验true
@DecimalMax(value=,inclusive=) 小于等于value,
inclusive=true,是小于等于
@DecimalMin(value=,inclusive=) 与上类似
@Max(value=) 小于等于value
@Min(value=) 大于等于value
@NotNull 检查Null
@Past 检查日期
@Pattern(regex=,flag=) 正则
@Size(min=, max=) 字符串,集合,map限制大小
@Valid 对po实体类进行校验如需其他注解,请参考hibernate validator官方文档了解其他验证约束注解和进行自定义的验证约束注解定义。
javax.validation参数校验 - 景、 - 博客园
@NotEmpty、@NotBlank、@NotNull 区别和使用
@NotNull
适用于基本数据类型(Integer,Long,Double等等),当 @NotNull 注解被使用在 String 类型的数据上,则表示该数据不能为 Null(但是可以为Empty)
@NotBlank
适用于 String 类型的数据上,加了@NotBlank 注解的参数不能为 Null 且 trim() 之后 size > 0
@NotEmpty
适用于 String、Collection集合、Map、数组等等,加了@NotEmpty 注解的参数不能为 Null 或者 长度为 0
@NotEmpty、@NotBlank、@NotNull 区别和使用_yangchao1125的博客-CSDN博客_notempty和notblank区别