
@valid和自定义异常
发布日期:2021-05-09 05:08:26
浏览次数:20
分类:博客文章
本文共 6947 字,大约阅读时间需要 23 分钟。
@valid和自定义异常
问题的产生:
当有很多参数需要校验时,比如name,age,email等很多参数都需要判空,或者有长度限制时,如果后端写很多if-else就有很多代码,不美观,不优雅.前端每个参数都效验的话工作量也很大
本文旨在解决这个问题,本文使用@valid 注解来解决这个问题.
首先定义一个
统一结果返回
import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;@NoArgsConstructor@AllArgsConstructor@Datapublic class Result{ private String msg; private Integer code; private T data; private static final Integer successCode = 200; private static Integer errorCode = 500; private static final String successMsg = "成功"; private static final Object resultNoData = null; public static Result successNoResult() { return new Result(successMsg, successCode, resultNoData); } public static Result successWithResult(T data) { return new Result(successMsg, successCode, data); } public static Result successWithCodeAndMsg(Integer code, String msg) { return new Result(msg, code, resultNoData); } public static Result errorNoResult(String msg) { return new Result(msg, errorCode, resultNoData); } public static Result errorWithResult(String msg, Object data) { return new Result(msg, errorCode, data); } public static Result errorWithCodeAndMsg(Integer code, String msg) { return new Result(msg, code, resultNoData); }}
@valid 注解简单使用
先看下简单使用,复杂的自己查api吧
首先在控制层的参数上加上该注解
import javax.validation.Valid;import java.util.*;@RestController@RequestMapping("/test")public class Test2 { @RequestMapping("test2") public Resulttest2(@Valid User user){ return Result.successWithResult(user); }}
然后在实体类中加上如下注解
import javax.validation.constraints.NotBlank;import javax.validation.constraints.NotNull;import javax.validation.constraints.Size;public class User { /** * @NotEmpty:不能为null,而且长度必须大于0 * @NotBlank:只用在String上,表示传进来的值不能为null,而且调用trim()后,长度必须大于0 * @NotNull:不能为null,但可以为empty * @Length(message = "名称不能超过个 {max} 字符", max = 10) * @Range(message = "年龄范围为 {min} 到 {max} 之间", min = 1, max = 100) */ @NotNull( message = "ID不能为空") private Integer id; @NotBlank( message = "昵称不能为空") @Size( min = 2,max = 5,message ="昵称的字数个数必须在0和5之间" ) private String name; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; }}
请求该接口
http://localhost:8080/test/test2?id=5&name=xxwwwww
查看效果,如下
可以看到,已经能表示该请求参数错误
但是还有个问题,我们不能直接这样子直接返回给前端,需要返回统一的结果
全局异常处理
Spring-boot对于异常的处理也做了不错的支持,
它提供了一个 @ControllerAdvice注解以及 @ExceptionHandler注解,
前者是用来开启全局的异常捕获,后者则是说明捕获哪些异常,对那些异常进行处理。如下
自定义异常
import lombok.Data;@Datapublic class DefinitionException extends RuntimeException { private Integer errorCode; private String errorMsg; public DefinitionException(){ } public DefinitionException(Integer errorCode, String errorMsg) { this.errorCode = errorCode; this.errorMsg = errorMsg; }}
异常处理
@ControllerAdvicepublic class GlobalExceptionHandler { /** * 处理自定义异常 */ @ExceptionHandler(value = DefinitionException.class) @ResponseBody public Result bizExceptionHandler(DefinitionException definitionException) { Result result=new Result(); result.setCode(definitionException.getErrorCode()); result.setMsg(definitionException.getErrorMsg()); return result; } /** * 处理异常 */ @ExceptionHandler(value = Exception.class) @ResponseBody public Result runtimeExceptionHandler(Exception exception) { Result result=new Result(); result.setCode(500); result.setMsg(exception.getMessage()); return result; }}
测试代码
@RequestMapping("test3")public Resulttest3(){int i=1/0;return Result.successWithResult("test3");}@RequestMapping("test4")public Result test4(){throw new DefinitionException(500,"啊哦,报错了");}
查看结果
将@valid注解抛的异常也返回统一格式
我们再请求一下这个接口
http://localhost:8080/test/test2?id=5&name=xxwwwww
看下结果
返回格式是统一的格式了,但是返回的信息不太友好,我们看看怎么优化
debug一下,看看这个是什么异常
我们看到,这个异常是org.springframework.validation.BindException类的,
我们看下这个类的具体内容,我们只要我们想要的信息就行
这里,我们只要这个信息就可以了我们改动后如下
/** * 处理异常 */ @ExceptionHandler(value = Exception.class) @ResponseBody public Result runtimeExceptionHandler(Exception exception) { Result result=new Result(); if(exception instanceof BindException){//注解类异常 StringBuilder sb = new StringBuilder(); BindException bindException= (BindException) exception; BindingResult bindingResult = bindException.getBindingResult(); ListallErrors = bindingResult.getAllErrors(); for (ObjectError item : allErrors) { sb .append(item.getDefaultMessage()) .append(','); } sb.deleteCharAt(sb.length()-1); result.setCode(500); result.setMsg(sb.toString()); } return result; }
再请求该接口,得到结果
到此为止,我们已经得到了我们想要的结果
优化代码
最后,我们在优化一下全局异常处理代码如下
import com.yoocar.util.Result;import org.springframework.validation.BindException;import org.springframework.validation.BindingResult;import org.springframework.validation.ObjectError;import org.springframework.web.bind.annotation.ControllerAdvice;import org.springframework.web.bind.annotation.ExceptionHandler;import org.springframework.web.bind.annotation.ResponseBody;import java.util.List;@ControllerAdvicepublic class GlobalExceptionHandler { /** * 处理自定义异常 */ @ExceptionHandler(value = Exception.class) @ResponseBody public Result exceptionHandler(Exception exception) { Result result=new Result(); //自定义类型异常 if(exception instanceof DefinitionException){ DefinitionException definitionException= (DefinitionException) exception; result.setCode(definitionException.getErrorCode()); result.setMsg(definitionException.getErrorMsg()); }else if(exception instanceof BindException){//@valid注解抛出的异常 //使用StringBuilder来拼接错误信息,减少对象开销 StringBuilder stringBuilder = new StringBuilder(); //获取并拼接所有错误信息 BindException bindException= (BindException) exception; BindingResult bindingResult = bindException.getBindingResult(); ListallErrors = bindingResult.getAllErrors(); for (ObjectError item : allErrors) { stringBuilder.append(item.getDefaultMessage()) .append(','); } //删除最后一个逗号 stringBuilder.deleteCharAt(stringBuilder.length()-1); result.setCode(600);//这里自定义了600用于表示参数有误 result.setMsg(stringBuilder.toString()); }else {//其他异常 result.setCode(500); result.setMsg(exception.getMessage()); } return result; }}
至此,本文结束.文章中若有错误和疏漏之处,还请各位大佬不吝指出,谢谢大家!
发表评论
最新留言
感谢大佬
[***.8.128.20]2025年04月06日 13时51分26秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
源码解析之 Mybatis 对 Integer 参数做了什么手脚?
2021-05-09
oracle使用DBMS_RANDOM包生成随机数据
2021-05-09
[转]收集Oracle UNDO诊断信息脚本
2021-05-09
Qt快速入门之三:Qt项目建立、编译、运行和源码详解
2021-05-09
【QML 快速入门】属性(Properties)
2021-05-09
音视频基础知识---像素格式YUV(转)
2021-05-09
音视频-测试工具推荐
2021-05-09
C++9018:2333/2235——柠檬汽水(Lemonade Line)
2021-05-09
力扣 - 430. 扁平化多级双向链表
2021-05-09
过滤器和监听器总结
2021-05-09
MinIO分布式集群的扩展方案及实现
2021-05-09
《深度探索C++对象模型》第二章 | 构造函数语意学
2021-05-09
C++高精度模板
2021-05-09
错题重错之WYT的刷子 单调队列
2021-05-09
洛谷 P2403 [SDOI2010]所驼门王的宝藏 题解
2021-05-09
关于结构体的初始化
2021-05-09
洛谷 P6851 【onu】贪心
2021-05-09
联赛模拟测试20 B. Walk (建图)
2021-05-09
联赛模拟测试22 D. 简单计算
2021-05-09
联赛模拟测试23 D. 真相 思维题
2021-05-09