七、JSR303参数校验和全局异常处理

JSR303参数校验

系统需要登录时先做一个参数校验,有的方法同样也需要做参数校验,例如注册。
为了大量代码重复,这里使用JSR303校验
添加依赖

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-validation</artifactId>
    </dependency>

登录功能中我们要验证loginVo中两个属性

  1. Controller中在参数loginVo前加上标签@Valid
    @RequestMapping("/do_login")
    @ResponseBody
    public Result<Boolean> doLogin(HttpServletResponse response, @Valid LoginVo loginVo) {
        log.info(loginVo.toString());
        //登录
        userService.login(response, loginVo);
        return Result.success(true);
    }
  1. 在LoginVo类中每一个需要验证的属性上加注解,这里自定义了一个IsMobile校验器
public class LoginVo {

    @NotNull
    @IsMobile
    private String mobile;
    @NotNull
    @Length(min=32) //formPass为32个字符,128字节
    private String password;

    public String getMobile() {
        return mobile;
    }

    public void setMobile(String mobile) {
        this.mobile = mobile;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "LoginVo{" +
                "mobile='" + mobile + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

自定义校验器

  1. 定义@IsMobile注解
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(
        validatedBy = {IsMobileValidator.class} //系统看到@IsMobile注解时调用的校验器
)
public @interface IsMobile {

    boolean required() default true;  //默认不能为空

    String message() default "手机号格式错误";  //验证不通过时的信息

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};
}
  1. 定义具体的IsMobileValidator校验器类来判断格式问题
//需要extends ConstraintValidator,String为校验器校验的字段类型
public class IsMobileValidator implements ConstraintValidator<IsMobile,String> {

    private boolean required = false;

    //初始化时接收注解里的值
    @Override
    public void initialize(IsMobile isMobile) {   
        required = isMobile.required();
    }

    //判断value是否合法
    @Override
    public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext) { 
        if (required) {
            return ValidatorUtil.isMobile(value);
        } else {
            if (StringUtils.isEmpty(value)) {
                return true;
            } else {
                return ValidatorUtil.isMobile(value);
            }
        }
    }
}

ValidatorUtil类

public class ValidatorUtil {

    //正则表达式:第一位为1,后面加10位数字
    private static final Pattern mobile_pattern = Pattern.compile("1\\d{10}");

    public static boolean isMobile(String src) {
        if (StringUtils.isEmpty(src)) {
            return false;
        }
        Matcher m = mobile_pattern.matcher(src);
        return m.matches();
    }
}

全局异常处理

参数校验不通过会出现org.springframework.validation.BindException的异常,需要拦截这个绑定异常,输出错误信息。
这里自定义一个全局异常拦截器,使用@ControllerAdvice注解
@ControllerAdvice可用于实现:

  • 全局异常处理 @ExceptionHandler
  • 全局数据绑定 @ModelAttribute
  • 全局预处理 @ModelAttribute, @InitBinder
@ControllerAdvice
@ResponseBody
public class GlobalExceptionHandler {

    @ExceptionHandler(value=Exception.class)//指明异常的处理类型
    public Result<String> exceptionHandler(HttpServletRequest request, Exception e){

        e.printStackTrace();
        if (e instanceof GlobalException) {
            GlobalException ex = (GlobalException)e;
            return Result.error(ex.getCm());
        } else if (e instanceof BindException) {  //处理BindException
            BindException ex = (BindException)e;
            List<ObjectError> errors = ex.getAllErrors();
            ObjectError error = errors.get(0);  //这里只取第一个,可以都取
            String msg = error.getDefaultMessage();
            return Result.error(CodeMsg.BIND_ERROR.fillArgs(msg));  //返回带参数的错误码
        } else {
            return Result.error(CodeMsg.SERVER_ERROR);
        }
    }
}

CodeMsg

public class CodeMsg {
    ...
	public static CodeMsg BIND_ERROR = new CodeMsg(500101, "参数校验异常:%s");
	
	public CodeMsg(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }
	public CodeMsg fillArgs(Object... args) {  //实参个数可变
        int code = this.code;
        String message = String.format(this.msg, args);  //原始信息拼接参数
        return new CodeMsg(code, message);
    }
}

测试

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值