0
点赞
收藏
分享

微信扫一扫

springboot项目三种请求参数类型异常捕获处理方式

在项目中引入hibernate-validator,在springboot项目中,可以直接引入对应的starter

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

然后创建一个全局异常处理类

import com.xiaomifeng1010.response.R;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.Path;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;


/**
 * 全局异常处理器
 * @author
 * @version 1.0
 * @date: 2020/12/12
 */
@Order(value = Ordered.HIGHEST_PRECEDENCE)
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {


    /**
     * @description: json对象参数验证
     * @author: 
     * @date: 2022/2/19
     * @param exception
     * @return: R
     **/
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public R handleValidException(MethodArgumentNotValidException exception) {
        BindingResult result = exception.getBindingResult();
        String errorMessage= StringUtils.EMPTY;
        if (result.hasErrors()) {
            errorMessage= result.getFieldErrors().stream().map(FieldError::getDefaultMessage).collect(Collectors.toList()).toString();
            log.error("请求对象[{}]验证错误信息{}",result.getFieldErrors().get(0).getObjectName(),errorMessage);
        }
        return R.fail(HttpStatus.BAD_REQUEST.value(),errorMessage);
    }


    /**
     * 统一处理请求参数校验(实体对象传参)
     *
     * @param e BindException
     * @return
     */
    @ExceptionHandler(BindException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public R handleBindException(BindException e) {
        StringBuilder message = new StringBuilder();
        List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
        for (FieldError error : fieldErrors) {
            message.append(error.getField()).append(error.getDefaultMessage()).append(",");
        }
        message = new StringBuilder(message.substring(0, message.length() - 1));
        return R.fail(HttpStatus.BAD_REQUEST.value(),message.toString());
    }


    /**
     * 统一处理请求参数校验(普通传参)
     *
     * @param e ConstraintViolationException
     * @return
     */
    @ExceptionHandler(value = ConstraintViolationException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public R handleConstraintViolationException(ConstraintViolationException e) {
        StringBuilder message = new StringBuilder();
        Set<ConstraintViolation<?>> violations = e.getConstraintViolations();
        for (ConstraintViolation<?> violation : violations) {
            Path path = violation.getPropertyPath();
            String[] pathArr = StringUtils.splitByWholeSeparatorPreserveAllTokens(path.toString(), ".");
            message.append(pathArr[1]).append(violation.getMessage()).append(",");
        }
        message = new StringBuilder(message.substring(0, message.length() - 1));
        return R.fail(HttpStatus.BAD_REQUEST.value(),message.toString());
    }
}

R对象为封装的统一的接口响应对象 

接着可以写一个controller测试一下几种参数类型验证会被哪个handler拦截处理

package com.xiaomifeng1010.controller;

import com.xiaomifeng1010.test.Student;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
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.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import javax.validation.constraints.NotBlank;

/**
 * @author xiaomifeng1010
 * @version 1.0
 * @date: 2021/12/28 16:31
 * @Description
 */
@Api("测试验证参数")
@RestController
@Validated
public class TestController {

    @ApiOperation("测试请求参数string类型")
    @PostMapping("/hello")
    public String test(@RequestParam("name") @NotBlank(message = "姓名不能为空") String name){
        return name;
    }

    @ApiOperation("测试请求参数bean类型,表单参数较多,直接与java对象的属性名绑定")
    @PostMapping("/helloBean")
    public String testBeanParam(@Valid Student student){
        return student.getName();

    }

    @ApiOperation("测试请求参数为json类型")
    @PostMapping("/helloJson")
    public String testJson(@Valid @RequestBody Student student){
        return student.getName();

    }
}

Student类


import lombok.Data;

import javax.validation.constraints.Min;
import javax.validation.constraints.PastOrPresent;
import javax.validation.constraints.Size;
import java.util.Date;

/**
 * @author xiaomifeng1010
 * @version 1.0
 * @date: 2021/8/5 13:41
 * @Description
 */
@Data
public class Student {
    @Size(min = 3,max = 10,message = "名字长度范围为3-10")
    String name;
    @Min(value = 1,message = "年龄不能小于1岁")
    Integer age;
    String idCard;
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    @PastOrPresent(message = "生日不能早于今天")
    Date birthDay;
}

然后在knife4j在线文档中测试,或者在postman中测试

先测试第一个接口方法,在name参数值中敲一个空格,然后项目断点会进入异常处理类中

 

 是抛出的ConstraintViolationException这个异常

接着再测试第二个接口参数,多个参数,用一个对象接收

 

抛出的是绑定异常BindingException 

然后测试请求体为json格式的数据

 

 

 抛出的异常为MethodArgumentNotValidException

 

举报

相关推荐

0 条评论