springboot实现校验参数,以及异常处理(转载)

转载地址:https://blog.csdn.net/qq_32352777/article/details/108424932

简述

@Validation是一套帮助我们继续对传输的参数进行数据校验的注解,通过配置Validation可以很轻松的完成对数据的约束。

@Validated作用在类、方法和参数上

@Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Validated {
    Class<?>[] value() default {};
}

错误的状态码

返回的响应码推荐使用400 bad request.(看个人喜好,自己封装请求返回结果其实更好)

所有参数注解含义

全局异常处理类

说明:若不做异常处理,@Validated注解的默认异常消息如下(示例):

2020-09-05 21:48:38.106  WARN 9796 --- [nio-8080-exec-3] .w.s.m.s.DefaultHandlerExceptionResolver :
Resolved [org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument [0] in public java.lang.String com.example.validateddemo.controller.DemoController.validatedDemo1(com.example.validateddemo.entity.dto.UseDto):
[Field error in object 'useDto' on field 'username': rejected value [null]; codes [NotBlank.useDto.username,NotBlank.username,NotBlank.java.lang.String,NotBlank];
arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [useDto.username,username]; arguments []; default message [username]]; default message [用户名不能为空!]] ]

因此我们在这里做了一个全局的异常处理类,用于处理参数校验失败后抛出的异常,同时进行日志输出。

/**
 * 传参异常处理
 * @Author: zt
 * @Date: 2021/5/27 21:59
 */

@Slf4j
@RestControllerAdvice
public class ParamValidatedAdvice {

    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public AjaxResult handleBindGetException(MethodArgumentNotValidException exception){

        List<String> errors = exception.getBindingResult()
                .getFieldErrors()
                .stream()
                .map(item -> item.getDefaultMessage())
                .collect(Collectors.toList());
        return AjaxResult.error("参数校验失败",errors);
    }
}

基础参数校验

实体类

package com.example.validateddemo.entity.dto;
 
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
 
import javax.validation.constraints.*;
 

@Data
public class User1Dto {
    /**
     * 用户名
     */
    @NotBlank(message = "用户名不能为空!")
    private String username;
    /**
     * 性别
     */
    @NotBlank(message = "性别不能为空!")
    private String gender;
    /**
     * 年龄
     */
    @Min(value = 1, message = "年龄有误!")
    @Max(value = 120, message = "年龄有误!")
    private int age;
    /**
     * 地址
     */
    @NotBlank(message = "地址不能为空!")
    private String address;
    /**
     * 邮箱
     */
    @Email(message = "邮箱有误!")
    private String email;
    /**
     * 手机号码
     */
    @Pattern(regexp = "^(13[0-9]|14[579]|15[0-3,5-9]|16[6]|17[0135678]|18[0-9]|19[89])\\d{8}$",message = "手机号码有误!")
    private String mobile;
}

控制类

package com.example.validateddemo.controller;
 
import com.example.validateddemo.entity.dto.Use1Dto;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
 
/**
 * @author He Changjie on 2020/9/5
 */
@RestController
@RequestMapping("/api/v1")
public class Demo1Controller {
 
    @PostMapping("/insert")
    public String validatedDemo1(@Validated @RequestBody Use1Dto use1Dto){
        System.out.println(use1Dto);
        return "success";
    }
}

 

嵌套参数验证

验证实体中的其他需要被验证的对象集合或其他对象

实体类

package com.example.validateddemo.entity.dto;
 
import lombok.Data;
 
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.List;
 
/**
 * 队伍实体
 * 数据传输对象
 * @author He Changjie on 2020/9/5
 */
@Data
public class Team1Dto {
    /**
     * 队伍名称
     */
    @NotBlank(message = "队伍名称不能为空!")
    private String name;
    /**
     * 队伍人员
     */
    @NotNull(message = "队伍人员不能为空!")
    @Valid
    private List<User1Dto> userList;
 
    /**
     * 队伍负责人
     */
    @NotNull(message = "队伍负责人不能为空!")
    @Valid
    private User1Dto user;
}

控制类

package com.example.validateddemo.controller;
 
import com.example.validateddemo.base.Result;
import com.example.validateddemo.entity.dto.Team1Dto;
import com.example.validateddemo.entity.dto.Use1Dto;
import com.example.validateddemo.utils.ResultUtil;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
 
/**
 * @author He Changjie on 2020/9/5
 */
@RestController
@RequestMapping("/api/v1")
public class Demo1Controller {
 
    @PostMapping("/insert")
    public Result validatedDemo1(@Validated @RequestBody Use1Dto use1Dto){
        return ResultUtil.success(use1Dto);
    }
 
    @PostMapping("/insert2")
    public Result validatedDemo2(@Validated @RequestBody Team1Dto team1Dto){
        return ResultUtil.success(team1Dto);
    }
}

分组参数验证

将不同的校验规则分给不同的组,在使用时,指定不同的校验规则

接口类

 

package com.example.validateddemo.interfaces;
 
/**
 * 校验分组1
 * @author He Changjie on 2020/9/5
 */
public interface Group1 {
}
package com.example.validateddemo.interfaces;
 
/**
 * 校验分组2
 * @author He Changjie on 2020/9/5
 */
public interface Group2 {
}

实体类

package com.example.validateddemo.entity.dto;
 
import com.example.validateddemo.interfaces.Group1;
import com.example.validateddemo.interfaces.Group2;
import lombok.Data;
 
import javax.validation.constraints.*;
 
/**
 * @author He Changjie on 2020/9/5
 */
@Data
public class User2Dto {
    /**
     * 用户名
     */
    @NotBlank(message = "用户名不能为空!", groups = {Group1.class})
    private String username;
    /**
     * 性别
     */
    @NotBlank(message = "性别不能为空!")
    private String gender;
    /**
     * 年龄
     */
    @Min(value = 1, message = "年龄有误!", groups = {Group1.class})
    @Max(value = 120, message = "年龄有误!", groups = {Group2.class})
    private int age;
    /**
     * 地址
     */
    @NotBlank(message = "地址不能为空!")
    private String address;
    /**
     * 邮箱
     */
    @Email(message = "邮箱有误!", groups = {Group2.class})
    private String email;
    /**
     * 手机号码
     */
    @Pattern(regexp = "^(13[0-9]|14[579]|15[0-3,5-9]|16[6]|17[0135678]|18[0-9]|19[89])\\d{8}$",message = "手机号码有误!", groups = {Group2.class})
    private String mobile;
}

控制类

package com.example.validateddemo.controller;
 
import com.example.validateddemo.base.Result;
import com.example.validateddemo.entity.dto.Team1Dto;
import com.example.validateddemo.entity.dto.User1Dto;
import com.example.validateddemo.entity.dto.User2Dto;
import com.example.validateddemo.interfaces.Group1;
import com.example.validateddemo.interfaces.Group2;
import com.example.validateddemo.utils.ResultUtil;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
 
/**
 * @author He Changjie on 2020/9/5
 */
@RestController
@RequestMapping("/api/v1")
public class Demo1Controller {
 
    @PostMapping("/insert")
    public Result validatedDemo1(@Validated @RequestBody User1Dto user1Dto){
        return ResultUtil.success(user1Dto);
    }
 
    @PostMapping("/insert2")
    public Result validatedDemo2(@Validated @RequestBody Team1Dto team1Dto){
        return ResultUtil.success(team1Dto);
    }
 
    @PostMapping("/insert3")
    public Result validatedDemo3(@Validated @RequestBody User2Dto user2Dto){
        return ResultUtil.success(user2Dto);
    }
 
    @PostMapping("/insert4")
    public Result validatedDemo4(@Validated(Group1.class) @RequestBody User2Dto user2Dto){
        return ResultUtil.success(user2Dto);
    }
 
    @PostMapping("/insert5")
    public Result validatedDemo5(@Validated(Group2.class) @RequestBody User2Dto user2Dto){
        return ResultUtil.success(user2Dto);
    }
}

 @Valid和@Validated 区别

通过源码分析:

@Target({ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Valid {
}
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Validated {
    Class<?>[] value() default {};
}

@Valid:没有分组的功能。

@Valid:可以用在方法、构造函数、方法参数和成员属性(字段)上

@Validated:提供了一个分组功能,可以在入参验证时,根据不同的分组采用不同的验证机制

@Validated:可以用在类型、方法和方法参数上。但是不能用在成员属性(字段)上

两者是否能用于成员属性(字段)上直接影响能否提供嵌套验证的功能

 

posted @ 2021-05-27 23:08  J.....ava  阅读(1502)  评论(0)    收藏  举报