@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 Result
test2(@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 Result
test3(){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();            List
allErrors = 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();            List
allErrors = 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; }}

至此,本文结束.文章中若有错误和疏漏之处,还请各位大佬不吝指出,谢谢大家!

上一篇:impdp导入表不创建segments
下一篇:Centos7查看外网ip,yum安装的curl无法正常使用

发表评论

最新留言

感谢大佬
[***.8.128.20]2025年04月06日 13时51分26秒