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!!
阅读剩余
版权声明:
作者:涛哥
链接:https://ltbk.net/back/spring_family/spring-boot/article/1654.html
文章版权归作者所有,未经允许请勿转载。
作者:涛哥
链接:https://ltbk.net/back/spring_family/spring-boot/article/1654.html
文章版权归作者所有,未经允许请勿转载。
THE END