1 前言
后端如何优雅的对接口参数做校验,在开发过程中由于前端的一切输入都是不可信的,所以后端需要对前端的请求参数进行二次校验的。例如我们保存表单数据时候,这里的客户名称需要必填、手机号格式要正确,前端虽然做了校验,但是后端的校验也是必不可少的。因为用户可能修改我们的前端校验规则绕过前端校验。
2 验证框架
Spring Boot为我们后端提供了一个很强大的参数验证框架validation,它可以对我们的实体类字段进行校验,并且可以给我们提供详细的错误提示信息,使用过程也非常优雅。
3 使用步骤
1 在 pom.xml 文件中添加以下依赖
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
2 在实体类中字段属性添加验证规则注解
@Size(max=64)
@NotEmpty(message = "客户姓名不能为空")
private String name;
说明:在实体类中使用注解,可以指定当前字段是否可以为 null,以及字符串的长度和格式等信息,如果传入的参数不符合预定的规则,在校验时就会产生相应的提示。
常用的参数验证注解:
@Digits:验证注解字段的整数位数和小数位数是否符合预期;
@Email:验证注解的字段是否为Email格式。
@Max Min 字段最大最小值
@NotBlank:验证注解的字段不为null,且允许去除两端空格后不为空;
@NotEmpty:验证注解的字段不为null,且String类型也不为 "";
@NotNull:验证注解的字段不为null;
3 在Controller中对接口参数添加验证注解 @Valid
@RequiresPermissions("crm:memberBase:update")
@ResponseBody@RequestMapping("/save.json")
public ResponseObj<Boolean> save(@Valid @RequestBody MemberBase bean) {
return success(memberBaseApi.saveOrUpdate(getTenantId(),bean,getUsername()));
}
4 定义全局异常处理器,封装返回结果(demo)
@ControllerAdvice
@RestController
public class WebExceptionHandler {
@ExceptionHandler(Exception.class)
public Object handleException(Exception e) {
if(e instanceof BusinessException) {
BusinessException error = (BusinessException)e;
logger.warn(error.getMsg());
return rendError(new BaseCode(error.getCode(),error.getMsg()));
}
else if(e instanceof MethodArgumentNotValidException) {
BindingResult result = ((MethodArgumentNotValidException)e).getBindingResult();
FieldError error = result.getFieldError();
logger.warn("请求参数错误:{}",error.getDefaultMessage());
return rendError(BaseCode.ERR_PARAMS_VALID,error.getDefaultMessage());
}
logger.error("系统错误:{}",e.getMessage(), e);
return rendError(BaseCode.ERROR);
}
}
完成以上步骤后,后端校验就完成了。
4 自定义注解
如果validation框架 提供的校验规则不能满足我们的业务。我们也可以采用自定义注解和验证器的方式进行参数验证。比如,我们可以自定义校验注解对手机号格式进行校验。
1 自定校验器示例代码如下:
package com.mrxu.framework.boot.validation;
import cn.hutool.core.util.PhoneUtil;
import com.mrxu.framework.common.util.StrFunc;
import javax.validation.Constraint;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import javax.validation.Payload;
import java.lang.annotation.*;
public class MobileValidator implements ConstraintValidator<MobileValidator.Mobile,String> {
@Override
public void initialize(Mobile constraintAnnotation) {
ConstraintValidator.super.initialize(constraintAnnotation);
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if(StrFunc.isNotEmpty(value)) {
return PhoneUtil.isMobile(value);
}
return true;
}
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(validatedBy = {MobileValidator.class})
public @interface Mobile {
String message() default "手机号格式错误";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
}
2 使用时,我们在实体类字段上添加我们的注解
@MobileValidator.Mobile(message = "您手机号输错了")
private String mobile;
分享的内容如果对你有用记得点赞关注