SpringBoot 接口校验(非空非法字符/特殊字符长度等)
Posted cavan丶keke
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringBoot 接口校验(非空非法字符/特殊字符长度等)相关的知识,希望对你有一定的参考价值。
1、引入pom依赖
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.20.Final</version>
</dependency>
2、实体类
单层校验
直接在类属性上使用注解
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
public class ClassInfoVo {
@Pattern(regexp = "^.{0,100}$", message = "班级id最长为100个字符")
private String classId;
@Pattern(regexp = "^.{0,100}$", message = "班级名最长为100个字符")
@NotNull(message = "缺少必要的参数规则name")
@NotBlank(message = "班级名不能为null,或者只包含空格")
@NotEmpty(message = "班级name不能为null或者长度为0")
private String className;
}
嵌套多层
在对象属性上使用@Valid注解
import javax.validation.Valid;
import java.util.List;
public class SchoolInfo {
private String schoolName;
private String schoolId;
@Valid
private List<ClassInfoVo> rules;
}
public class ClassInfoVo {
@Pattern(regexp = "^.{0,100}$", message = "班级id最长为100个字符")
private String classId;
@Pattern(regexp = "^.{0,100}$", message = "班级名最长为100个字符")
@NotNull(message = "缺少必要的参数规则name")
@NotBlank(message = "班级名不能为null,或者只包含空格")
@NotEmpty(message = "班级name不能为null或者长度为0")
private String className;
}
3、控制层
使用@Valid
@RestController
@RequestMapping(value = "/school")
public class Controller {
@Autowired
private SchoolService schoolService;
@PostMapping(value = "/query")
public BaseResponse query(@RequestBody @Valid SchoolInfo infoVo) {
return schoolService.query(infoVo);
}
}
4、全局异常处理
- 处理Get请求,抛出BindException异常
- 处理请求参数格式错误 @RequestParam上,抛出ConstraintViolationException异常
- 处理请求参数格式错误 @RequestBody上,抛出MethodArgumentNotValidException
@ControllerAdvice
public class YourProjectNameExceptionAdvice {
private static final Logger LOGGER = LoggerFactory.getLogger(YourProjectNameExceptionAdvice.class);
/**
* 校验错误拦截处理
* 处理Get请求中 使用@Valid 验证路径中请求实体校验失败后抛出的异常
*
* @param exception 错误信息集合
* @return 错误信息
*/
@ResponseBody
@ExceptionHandler(BindException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public BaseResponse bindExceptionHandler(BindException exception) {
LOGGER.error("BindException encountered: {0}", exception);
String message =
exception.getBindingResult().getAllErrors().stream()
.map(DefaultMessageSourceResolvable::getDefaultMessage)
.collect(Collectors.joining());
return BaseResponse.newError("YourProjectName_BindException", message);
}
/**
* 校验错误拦截处理
* 处理请求参数格式错误 @RequestParam上validate失败后抛出的异常是javax.validation.ConstraintViolationException
*
* @param exception 错误信息集合
* @return 错误信息
*/
@ResponseBody
@ExceptionHandler(ConstraintViolationException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public BaseResponse constraintViolationHandler(ConstraintViolationException exception) {
LOGGER.error("ConstraintViolation exception encountered: {0}", exception);
return BaseResponse.newError("YourProjectName_ConstraintViolation", exception.getMessage());
}
/**
* 校验错误拦截处理
* 处理请求参数格式错误 @RequestBody上validate失败后抛出的异常是MethodArgumentNotValidException异常。
*
* @param exception 错误信息集合
* @return 错误信息
*/
@ResponseBody
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public BaseResponse methodArgumentNotValidHandler(MethodArgumentNotValidException exception) {
LOGGER.error("MethodArgumentNotValid exception encountered: {0}", exception);
BindingResult bindingResult = exception.getBindingResult();
StringBuilder sb = new StringBuilder();
for (FieldError fieldError : bindingResult.getFieldErrors()) {
sb.append(fieldError.getField()).append(": ").append(fieldError.getDefaultMessage()).append(", ");
}
return BaseResponse.newError("YourProjectName_MethodArgumentNotValid", sb.toString());
}
}
5、如果多个请求参数校验失败,则遇到一个校验失败就抛出异常,接下来的异常参数不做校验。
@Configuration
public class WebConfig {
@Bean
public Validator validator() {
ValidatorFactory validatorFactory = Validation.byProvider(HibernateValidator.class)
.configure()
//failFast的意思只要出现校验失败的情况,就立即结束校验,不再进行后续的校验。
.failFast(true)
.buildValidatorFactory();
return validatorFactory.getValidator();
}
@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
MethodValidationPostProcessor methodValidationPostProcessor = new MethodValidationPostProcessor();
methodValidationPostProcessor.setValidator(validator());
return methodValidationPostProcessor;
}
}
6、校验时常用注解
JSR303定义的校验类型
Constraint
|
详细信息
|
---|---|
@Valid | 递归的对关联对象进行校验,如果关联对象是个集合或者数组,那么对其中的元素进行递归校验 |
@Pattern(value) | 符合指定的正则表达式(校验非法字符) |
@NotNull | 参数不为 null |
@NotEmpty | 参数不能为null,或者是空 |
@NotBlank() | 参数不能为null,或者被Trim的长度是否大于0(可以用来校验全为空格字符) |
@Min() | 一个数字,值大于给定值 |
@Max() | 一个数字,值小于给定值 |
@Digits (integer, fraction) | 一个数字,其值必须在可接受的范围内 |
举例代码中使用的比较代表的:
@Pattern(regexp = "^[\\\\u4E00-\\\\u9FA5\\\\w\\\\-]{1,57}$", message = "只能包含中文字符、英文字符、数字、下划线和中横线,1~57个字符")
@Pattern(regexp = "^((?!=|\\\\+|-|@|>|<|%).)((?!>|<|%).){0,127}$", message = "不能以=,+,-或@开头,不能包含<,>和%字符,最长为128个字符")
@Pattern(regexp = "^(?:false|true)$", message = "只支持false/true")
@Pattern(regexp = "^[A-Za-z0-9]{32}$", message = "只能是32位的uuid(只有英文和字母)")
@Pattern(regexp = "^[\\\\w-.;]{1,100}$", message = "最长为100,只能包含英文、数字、“-”、“_”、“;”")
@Pattern(
regexp = "^[/][/\\\\w-.]{1,254}$",
message = "须以“/”开头,只能包含字母、数字、“/”、“_”、“-”和“.”," + "长度不少于2位,长度最长为255")
@Pattern(regexp = "^(?:A|B)$", message = "类型必须为A或者B")
@Max(value = 2_140_000_000, message = "只能大于0小于2140000")
@Min(value = 0, message = "只能大于0小于2140000")
@Max(value = 5000, message = "分页大小在【1,5000】之间")
@Min(value = 1, message = "分页大小在【1,5000】之间")
@Digits(integer = 1, fraction = 0, message = "只能为0或1")
@Max(value = 1, message = "只能为0或1")
@Min(value = 0, message = "只能为0或1")
@NotEmpty(message = "缺少必要的参数,数组classIds不能为null,或者长度为0")
private List<
@Pattern(regexp = "^[a-zA-Z\\\\d]{32}$", message = "id仅由字母和数字组成,且长度为32个字符")
@NotEmpty(message = "id不能为null或者为空") String>
classIds;
这些只是包含一些基本的校验,负责校验可以使用是定义校验注解的方式,主要是要实现ConstraintValidator
的处理类。(不多介绍)
7、自定义注解
自定义注解名称
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = ParamValidator.class)
public @interface RetryTimes {
String message() default "重试次数只能为0,5,10,20,50,100";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
同时实现ConstraintValidator类
public class ParamValidator implements ConstraintValidator<RetryTimes, Short> {
private static final Pattern PATTERN = Pattern.compile("^(?:0|5|10|20|50|100)$");
@Override
public boolean isValid(Short retryTimes, ConstraintValidatorContext constraintValidatorContext) {
return PATTERN.matcher(retryTimes.toString()).matches();
}
}
定义后,如何使用,直接在属性上添加该注解
@RetryTimes
private short retryTimes;
8、分组校验(后面补充)
以上是关于SpringBoot 接口校验(非空非法字符/特殊字符长度等)的主要内容,如果未能解决你的问题,请参考以下文章