@valid和自定义异常

问题的产生:

当有很多参数需要校验时,比如name,age,email等很多参数都需要判空,或者有长度限制时,如果后端写很多if-else就有很多代码,不美观,不优雅.前端每个参数都效验的话工作量也很大

本文旨在解决这个问题,本文使用@valid 注解来解决这个问题.

首先定义一个

统一结果返回

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor; @NoArgsConstructor
@AllArgsConstructor
@Data
public class Result<T> { 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 <T> Result<T> 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<User> 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;

@Data
public class DefinitionException extends RuntimeException {
private Integer errorCode;
private String errorMsg; public DefinitionException(){ }
public DefinitionException(Integer errorCode, String errorMsg) {
this.errorCode = errorCode;
this.errorMsg = errorMsg;
} }

异常处理

@ControllerAdvice
public 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<String> test3(){
int i=1/0;
return Result.successWithResult("test3");
} @RequestMapping("test4")
public Result<String> 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<ObjectError> 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; @ControllerAdvice
public 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<ObjectError> 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;
} }

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

@valid和自定义异常的更多相关文章

  1. @Valid 数据校验 + 自定义全局异常信息

    关于javax.validation.Validator校验的使用 对于要校验的实体类:其需要校验的字段上需要添加注解 实际例子 使用:首先要拿到 validator的子类 Validator val ...

  2. 【springboot】@Valid参数校验

    转自: https://blog.csdn.net/cp026la/article/details/86495659 扯淡: 刚开始写代码的时候对参数的校验要么不做.要么写很多类似 if( xx == ...

  3. 小白解决CENTOS7错误:Cannot find a valid baseurl for repo: base/7/x86_6

    刚入手的MacBook想着学点东西,本汪还是决定玩玩CentOS服务器,安装好了VirtualBox + CentOS. 打开一看,懵逼了!命令行! 行吧,先装个图形界面: $sudo yum gro ...

  4. 记一个mvn奇怪错误: Archive for required library: 'D:/mvn/repos/junit/junit/3.8.1/junit-3.8.1.jar' in project 'xxx' cannot be read or is not a valid ZIP file

    我的maven 项目有一个红色感叹号, 而且Problems 存在 errors : Description Resource Path Location Type Archive for requi ...

  5. Leetcode 笔记 35 - Valid Soduko

    题目链接:Valid Sudoku | LeetCode OJ Determine if a Sudoku is valid, according to: Sudoku Puzzles - The R ...

  6. 安装CentOS7文字界面版后,无法联网,用yum安装软件提示 cannot find a valid baseurl for repo:base/7/x86_64 的解决方法

    *无法联网的明显表现会有: 1.yum install出现 Error: cannot find a valid baseurl or repo:base 2.ping host会提示unknown ...

  7. [LeetCode] Valid Word Square 验证单词平方

    Given a sequence of words, check whether it forms a valid word square. A sequence of words forms a v ...

  8. [LeetCode] Valid Word Abbreviation 验证单词缩写

    Given a non-empty string s and an abbreviation abbr, return whether the string matches with the give ...

  9. [LeetCode] Graph Valid Tree 图验证树

    Given n nodes labeled from 0 to n - 1 and a list of undirected edges (each edge is a pair of nodes), ...

随机推荐

  1. MySQL学习笔记(六)

    好耶,七天课程的最后一天!我当然还没精通了,,,之后可能是多练习题目然后再学学其他的东西吧.mysql新的知识点也会在后面补充的. 一.杂七杂八补充 1. 当多个函数共用同样的参数时,可以转变成类进行 ...

  2. Java基本概念:封装

    一.简介 描述: 生活中,我们要看电视,只需要按一下开关和换台就可以了.我们没有有必要了解电视机内部的结构. 制造厂家为了方便我们使用电视,把复杂的内部细节全部封装起来,只给我们暴露简单的接口,比如电 ...

  3. Docker搭建Hadoop环境

    文章目录 Docker搭建Hadoop环境 Docker的安装与使用 拉取镜像 克隆配置脚本 创建网桥 执行脚本 Docker命令补充 更换镜像源 安装vim 启动Hadoop 测试Word Coun ...

  4. 关于C++中构造函数的常见疑问

    基本概念 我们已经知道在定义一个对象时,该对象会根据你传入的参数来调用类中对应的构造函数.同时,在释放这个对象时,会调用类中的析构函数.其中,构造函数有三种,分别是默认构造函数,有参构造函数和拷贝构造 ...

  5. AtCoder Beginner Contest 190

    A Very Very Primitive Game int main() { int a, b, c; cin >> a >> b >> c; if(c == 0 ...

  6. ElasticSearch 进阶

    目录 ElasticSearch 进阶 SearchAPI 检索信息 Query DSL 基本语法格式 查询-match 查询-match_phrase 查询-multi_match 查询-bool复 ...

  7. 2019HDU多校第七场 HDU6656 Kejin Player H 【期望递归】

    一.题目 Kejin Player H 二.分析 因为在当前等级$i$,如果升级失败可能会退回到原来的某一等级$x$,相当于就是失败的期望就是$E + (Sum[i-1] - Sum[x-1]) + ...

  8. PTA 找出不是两个数组共有的元素

    7-2 找出不是两个数组共有的元素 (20 分)   给定两个整型数组,本题要求找出不是两者共有的元素. 输入格式: 输入分别在两行中给出两个整型数组,每行先给出正整数N(≤),随后是N个整数,其间以 ...

  9. Java系列教程-SpringMVC教程

    SpringMVC教程 1.SpringMVC概述 1.回顾MVC 1.什么是MVC MVC是模型(Model).视图(View).控制器(Controller)的简写,是一种软件设计规范. 是将业务 ...

  10. [差分][二分][贪心]luogu P3634 [APIO2012]守卫

    题面 https://www.luogu.com.cn/problem/P3634 给m个限制,可以是一段区间中必须有或者必须无忍者 最多有k个忍者,问有多少个位点一定有忍者 分析 首先用差分标记一下 ...