大数据

validation实现对Restful请求拦截

2020-01-06  本文已影响0人  他是人间惆怅客

Spring Boot在内部通过集成hibernate-validation实现了JSR-349验证规范接口,我们可以在MVC模式中对DTO进行灵活的校验,代码看起来也会更简洁、更优雅.
参考地址:https://docs.jboss.org/hibernate/stable/validator/reference/en-US/pdf/hibernate_validator_reference.pdf

常用注解列表

@AssertTrue 用于boolean字段,该字段只能为true
@AssertFalse 该字段的值只能为false
@CreditCardNumber 对信用卡号进行一个大致的验证
@DecimalMax 只能小于或等于该值
@DecimalMin 只能大于或等于该值
@Digits(integer=,fraction=) 检查是否是一种数字的整数、分数,小数位数的数字
@Email 检查是否是一个有效的email地址
@Future 检查该字段的日期是否是属于将来的日期
@Length(min=,max=) 检查所属的字段的长度是否在min和max之间,只能用于字符串
@Max 该字段的值只能小于或等于该值
@Min 该字段的值只能大于或等于该值
@NotNull 不能为null
@NotBlank 不能为空,检查时会将空格忽略
@NotEmpty 不能为空,这里的空是指空字符串
@Null 检查该字段为空
@Past 检查该字段的日期是在过去
@Pattern(regex=,flag=) 被注释的元素必须符合指定的正则表达式
@Range(min=,max=,message=) 被注释的元素必须在合适的范围内
@Size(min=, max=) 检查该字段的size是否在min和max之间,可以是字符串、数组、集合、Map等
@URL(protocol=,host,port) 检查是否是一个有效的URL,如果提供了protocol,host等,则该URL还需满足提供的条件
@Valid 该注解主要用于字段为一个包含其他对象的集合或map或数组的字段,或该字段直接为一个其他对象的引用,这样在检查当前对象的同时也会检查该字段所引用的对象

maven依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
       <!--Jackson,用于前端传过来的json字符串,对其序列号和反序列化-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-json</artifactId>
        </dependency>

controller控制层

package com.example.demo.controller;


import com.alibaba.fastjson.JSONObject;
import com.example.demo.model.Result;
import com.example.demo.model.Student;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;


@RestController
public class ValidationItemException {

    @PostMapping(value = "/validation/save")
    public Result saveStudentPage(@Valid @RequestBody Student student) {
        return new Result(200, "", JSONObject.toJSON(student).toString());
    }

    @PostMapping(value = "/validation/save2")
    public Student saveStudentPage2(@Valid @RequestBody Student student) {
        return student;
    }
}

DTO实体层(Student)

1.错误信息统一管理

我们也可以把错误信息message定制化到配置文件message.properties里面统一管理

2.@Valid和@Validated的区别

@Valid是javax.validation里的 @Validated是@Valid 的一次封装,是Spring提供的校验机制使用。@Validated 提供分组功能,但是在校验项比较多的情况下,本人不是很推荐分组校验,因为在开发中容易出错.


package com.example.demo.model;

import com.fasterxml.jackson.annotation.JsonFormat;
import org.hibernate.validator.constraints.Range;

import javax.validation.constraints.Future;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Size;
import java.time.LocalDateTime;

public class Student {

    @Range(min=15,max=65,message = "年龄必须在15岁到65岁")
    private int age;

    @Size(min=2, max=30)
    private String name;

    @NotEmpty(message = "自定义错误信息,score不能为空!")
    private String score;

    @Future(message = "生效时间必须大于当前时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime createTime;


    public LocalDateTime getCreateTime() {
        return createTime;
    }

    public void setCreateTime(LocalDateTime createTime) {
        this.createTime = createTime;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getScore() {
        return score;
    }

    public void setScore(String score) {
        this.score = score;
    }


    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "age=" + age +
                ", name='" + name + '\'' +
                ", score='" + score + '\'' +
                '}';
    }
}


DTO实体层(Result)

package com.example.demo.model;

public class Result implements java.io.Serializable{

    private int code;
    private String msg;
    private Object data;

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    @Override
    public String toString() {
        return "Result{" +
                "code=" + code +
                ", msg='" + msg + '\'' +
                ", data=" + data +
                '}';
    }
}

全局异常捕获

package com.example.demo.Hanlder;

import com.example.demo.model.Result;
import org.springframework.http.HttpStatus;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.List;
import java.util.stream.Collectors;

@RestControllerAdvice
public class BindExceptionHandler {
    /**
     * 全局异常捕捉处理
     *
     * @param ex
     * @return
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Result handleBindException(MethodArgumentNotValidException ex) {

// 同样是获取BindingResult对象,然后获取其中的错误信息
        // 如果前面开启了fail_fast,事实上这里只会有一个信息
        //如果没有,则可能又多个
        List<String> errorInformation = ex.getBindingResult().getAllErrors()
                .stream()
                .map(ObjectError::getDefaultMessage)
                .collect(Collectors.toList());
        return new Result(HttpStatus.BAD_REQUEST.value(),errorInformation.toString(),null) ;
    }
}

测试结果

image.png
上一篇 下一篇

猜你喜欢

热点阅读