SpringBoot整合Validation统一结果封装和全局异常捕获和参数校验

前言

什么是Validation?

相信大家都用过hibernate-validation 的校验工具,对我们参数校验的工具。

为什么要用它?

相信大家在开发过程中肯定会写if-else判断吧!!

Validation可以帮助我们简化这些操作,大大提高我们的开发效率

如何使用?

1,引入依赖包 pom.xml

        <!--SpringMvc-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--参数校验-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

这里我们引入lombok和mvc依赖,方便后续封装统一返回结果

lombok:通过注解形式简化 setter和getter的操作

mvc:接口所需的包

2,编写类

package com.demo.domain;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.validator.constraints.Length;

import javax.validation.constraints.NotBlank;

/**
 * @Program: SpringBoot
 * @ClassName User
 * @Author: liutao
 * @Description:
 * @Create: 2023-09-15 22:16
 * @Version 1.0
 **/

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    @NotBlank(message = "用户名不能为空")
    @Length(min = 3, max = 6, message = "用户名长度不能低于3个字符且不能超过6个字符")
    private String username;
    @NotBlank(message = "密码不能为空")
    private String password;
}

3,编写web接口

package com.demo.controller;

import com.demo.domain.User;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
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;
import javax.validation.constraints.NotBlank;

/**
 * @Program: SpringBoot
 * @ClassName TestController
 * @Author: liutao
 * @Description: 测试接口
 * @Create: 2023-09-15 22:16
 * @Version 1.0
 **/
@Validated
@RestController
public class TestController {
        @GetMapping("/get")
        String get(@NotBlank(message = "不能为空") String name) {
            return name;
        }
        @PostMapping("/save")
        User save(@Valid @RequestBody User user) {
            return user;
        }


}

ps:这里需要注意对类校验的参数 必须加上 @Valid 注解如上述 post请求一样

而对于对接口单个入参进行校验则必须在当前类加上 @Validated 注解 如上述get请求相同

4,测试 

get请求测试

 

post请求

 

 

 

 

这里我用了全局异常捕获和统一结果封装,下面将为大家讲解!! 

 封装统一返回结果

1,封装

package com.demo.common;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @Program: SpringBoot
 * @ClassName Result
 * @Author: liutao
 * @Description: 封装统一结果
 * @Create: 2023-09-15 22:47
 * @Version 1.0
 **/

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Result<T> {
    private Integer code;
    private String msg;
    private T data;

    public static<T> Result<T> success(Integer code, String msg, T data) {
        return new Result<T>(code, msg, data);
    }

    public static<T> Result<T> success(Integer code, T data) {
        return new Result<T>(code, "成功", data);
    }

    public static<T> Result<T> success(Integer code) {
        return new Result<T>(code, "成功", null);
    }
    public static <T> Result<T> error(Integer code, String msg) {
        return new Result<T>(code,msg,null);
    }


}

 2,使用

这里我们修改一下上面的get 请求如下所示:

@GetMapping("/ok")
Result<String> ok() {
    return Result.success(200);
}

3,效果

 全局异常捕获

在未使用全局异常捕获之前如下图:

我们可以看到测试效果,很难发现异常是什么对吧!!我们只有去看后台才知道那儿出问题了

我们可以看到后台已经抛出异常

接下来我们全局捕获异常

自定义一个ServiceException

package com.demo.exception;

import lombok.Getter;

/**
 * @Program: SpringBoot
 * @ClassName ServiceException
 * @Author: liutao
 * @Description: 自定义异常类
 * @Create: 2023-09-15 23:00
 * @Version 1.0
 **/

@Getter
public class ServiceException extends RuntimeException {
    private final Integer code;
    public ServiceException(Integer code, String msg) {
        super(msg);
        this.code = code;
    }
}

定义一个GlobalExceptionHandler 

package com.demo.exception;

import com.demo.common.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindException;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.ValidationException;
import java.util.stream.Collectors;

/**
 * @Program: SpringBoot
 * @ClassName GlobalExceptionHandler
 * @Author: liutao
 * @Description: 全局异常拦截
 * @Create: 2023-09-15 22:46
 * @Version 1.0
 **/
@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler
    @ResponseBody
    public Result<String> handle(ServiceException se) {
        log.error("业务异常" + se);
        return Result.error(se.getCode(), se.getMessage());
    }

    /**参数校验的拦截**/
    @ExceptionHandler(value = {BindException.class, ValidationException.class, MethodArgumentNotValidException.class})
    public ResponseEntity<Result<String>> handleValidatedException(Exception e) {
        Result<String> result = null;
        if (e instanceof MethodArgumentNotValidException) {
            MethodArgumentNotValidException ex = (MethodArgumentNotValidException) e;
            String errorMessages = ex.getBindingResult().getAllErrors().stream()
                    .map(ObjectError::getDefaultMessage)
                    .collect(Collectors.joining(";"));
            result = Result.error(HttpStatus.BAD_REQUEST.value(), errorMessages);
        } else if (e instanceof ConstraintViolationException) {
            ConstraintViolationException ex = (ConstraintViolationException) e;
            String errorMessages = ex.getConstraintViolations().stream()
                    .map(ConstraintViolation::getMessage)
                    .collect(Collectors.joining(";"));
            result = Result.error(HttpStatus.BAD_REQUEST.value(), errorMessages);
        } else if (e instanceof BindException) {
            BindException ex = (BindException) e;
            String errorMessages = ex.getAllErrors().stream()
                    .map(ObjectError::getDefaultMessage)
                    .collect(Collectors.joining(";"));
            result = Result.error(HttpStatus.BAD_REQUEST.value(), errorMessages);
        }
        return new ResponseEntity<>(result, HttpStatus.BAD_REQUEST);
    }
}

 然后我们再来测试

再看后台 

我们可以发现后台也没有抛出异常!!

结尾

到这里我们的文章就结束了!!

如果我们的文章对你的开发有用欢迎关注,点赞,收藏三连!!

将不定时发布原创精品文章,see you!!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

晚上睡不着!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值