【SpringBoot笔记18】SpringBoot实现统一异常处理、统一结果响应、统一参数校验
创始人
2024-04-02 02:30:23
0

这篇文章,主要介绍如何利用SpringBoot框架实现统一异常处理、统一结果响应、统一参数校验。

目录

一、SpringBoot统一结果响应

1.1、创建工程

1.2、配置FastJson

1.3、创建ResultEnum枚举

1.4、创建Result实体类

二、SpringBoot统一异常处理

2.1、创建自定义异常类

2.2、创建全局异常处理类

三、SpringBoot统一参数校验

3.1、引入参数校验依赖

3.2、创建测试实体类

3.3、创建测试控制器

3.4、运行测试


在实际的项目开发过程中,当应用程序发生异常时,用户可以接收到友好的错误提示信息,而不是直接出现一大堆看不懂的错误信息,这就需要对应用程序的所有异常进行统一的处理,SpringBoot框架提供了统一异常处理的注解,通过相应的注解就可以捕获所有可能出现的异常信息。

此外,在前后端分离的模式下,数据的交互都是采用JSON格式来传递的,如果每一个方法都返回不同格式的数据,这显然不太合适,所以,实际开发中都会将响应结果统一处理,并且对前后端传递的参数进行统一的校验。下面具体介绍如何实现三个统一。

一、SpringBoot统一结果响应

统一结果响应,这里是采用的JSON格式响应所有的数据,所以需要使用FastJson依赖。

1.1、创建工程

首先,创建一个SpringBoot工程,工程中需要引入下面几个依赖。


org.springframework.bootspring-boot-starter-parent2.3.0.RELEASE
org.springframework.bootspring-boot-starter-weborg.springframework.bootspring-boot-starter-jsoncom.alibabafastjson1.2.77
org.springframework.bootspring-boot-maven-pluginrepackage

1.2、配置FastJson

在工程里面,创建一个【CustomFastJsonConfig】配置类,添加如下配置。

package com.spring.boot.demo.common.config;import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;/*** @author ZhuYouBin* @version 1.0.0* @Date: 2022/10/29 21:07* @Description FastJson 配置类*/
@Configuration
public class CustomFastJsonConfig {@Beanpublic HttpMessageConverters fastjsonHttpMessageConverters() {// 创建 FastJsonHttpMessageConverter 消息转换器对象FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter();// 创建 FastJsonConfig 配置类对象FastJsonConfig fastJsonConfig = new FastJsonConfig();// 设置编码字符集fastJsonConfig.setCharset(StandardCharsets.UTF_8);// 设置日期格式fastJsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss");// 设置序列化特征: SerializerFeature 是一个枚举,可以选择不同的序列化特征SerializerFeature[] serializerFeatures = new SerializerFeature[]{// WriteNullStringAsEmpty: 如果字符串等于 null,那么会被序列化成空字符串 ""SerializerFeature.WriteNullStringAsEmpty,// WriteNullNumberAsZero: 如果数字等于 null,那么会被序列化成 0SerializerFeature.WriteNullNumberAsZero,// WriteNullBooleanAsFalse: 如果布尔类型等于 null,那么会被序列化成 falseSerializerFeature.WriteNullBooleanAsFalse,// PrettyFormat: 美化JSONSerializerFeature.PrettyFormat};fastJsonConfig.setSerializerFeatures(serializerFeatures);// 配置添加到消息转换器里面fastJsonHttpMessageConverter.setDefaultCharset(StandardCharsets.UTF_8);fastJsonHttpMessageConverter.setFastJsonConfig(fastJsonConfig);// 设置响应JSON格式数据List mediaTypeList = new ArrayList<>();mediaTypeList.add(MediaType.APPLICATION_JSON); // JSON 格式数据// 设置消息转换器支持的格式fastJsonHttpMessageConverter.setSupportedMediaTypes(mediaTypeList);// 返回消息转换器return new HttpMessageConverters(fastJsonHttpMessageConverter);}
}

1.3、创建ResultEnum枚举

在一个工程里面,可能会出现很多不同的响应结果状态,所以这里采用一个【ResultEnum】枚举类来保存。

  • 这里可以根据自己的需要,继续添加不同的枚举类型。
package com.spring.boot.demo.common.resp;/*** @author ZhuYouBin* @version 1.0.0* @Date: 2022/10/29 21:13* @Description 统一响应结果枚举类*/
public enum ResultEnum {SUCCESS(20000, "响应成功"),FAILED(50000, "操作异常");/** 状态码 */private Integer statusCode;/** 提示信息 */private String message;ResultEnum(int statusCode, String message) {this.statusCode = statusCode;this.message = message;}public Integer getStatusCode() {return statusCode;}public void setStatusCode(Integer statusCode) {this.statusCode = statusCode;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}
}

1.4、创建Result实体类

为了实现统一响应结果,这里创建一个【Result】类,该类作为所有控制器方法的返回值类型。

package com.spring.boot.demo.common.resp;import java.io.Serializable;/*** @author ZhuYouBin* @version 1.0.0* @Date: 2022/10/29 21:16* @Description 统一响应结果类*/
public class Result implements Serializable {/** 状态码 */private Integer statusCode;/** 提示信息 */private String message;/** 响应数据 */private T data;/** 私有构造方法 */private Result() {}/************************** common method **************************//* 响应成功 */public static  Result success() {Result result = new Result<>();result.setStatusCode(ResultEnum.SUCCESS.getStatusCode());result.setMessage(ResultEnum.SUCCESS.getMessage());return result;}/* 响应失败 */public static  Result failure() {Result result = new Result<>();result.setStatusCode(ResultEnum.FAILED.getStatusCode());result.setMessage(ResultEnum.FAILED.getMessage());return result;}/* 响应失败 */public static  Result failure(String message) {Result result = new Result<>();result.setStatusCode(ResultEnum.FAILED.getStatusCode());result.setMessage(message);return result;}/* 响应失败 */public static  Result failure(int statusCode, String message) {Result result = new Result<>();result.setStatusCode(statusCode);result.setMessage(message);return result;}/* 响应失败 */public static  Result failure(ResultEnum resultEnum) {Result result = new Result<>();result.setStatusCode(resultEnum.getStatusCode());result.setMessage(resultEnum.getMessage());return result;}/* 自定义响应状态码 */public Result statusCode(int statusCode) {this.setStatusCode(statusCode);return this;}/* 自定义响应提示信息 */public Result message(String message) {this.setMessage(message);return this;}/* 自定义响应数据 */public Result data(T data) {this.setData(data);return this;}/************************** getter and setter **************************/public Integer getStatusCode() {return statusCode;}public void setStatusCode(Integer statusCode) {this.statusCode = statusCode;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}public T getData() {return data;}public void setData(T data) {this.data = data;}@Overridepublic String toString() {return "Result{" +"statusCode=" + statusCode +", message='" + message + '\'' +", data=" + data +'}';}
}

到这里,我们就已经把统一响应结果的类定义好啦,下面继续定义统一全局异常处理的类。

二、SpringBoot统一异常处理

2.1、创建自定义异常类

在工程里面,创建一个自定义的异常类【BizException】,这个类主要用于我们在编写业务代码的时候,自定义设置错误的状态码和提示信息。

package com.spring.boot.demo.common.exception;/*** @author ZhuYouBin* @version 1.0.0* @Date: 2022/10/29 21:30* @Description 自定义异常类*/
public class BizException extends RuntimeException {/** 状态码 */private Integer statusCode;/** 提示信息 */private String message;public BizException(int statusCode, String message) {this.statusCode = statusCode;this.message = message;}public BizException() {super();}public BizException(String message) {this.message = message;}public BizException(String message, Throwable cause) {super(message, cause);}public BizException(Throwable cause) {super(cause);}protected BizException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {super(message, cause, enableSuppression, writableStackTrace);}public Integer getStatusCode() {return statusCode;}public void setStatusCode(Integer statusCode) {this.statusCode = statusCode;}@Overridepublic String getMessage() {return message;}public void setMessage(String message) {this.message = message;}
}

2.2、创建全局异常处理类

在工程里面,创建一个【GlobalExceptionHandler】类,这个类就是处理整个项目里面出现的所有异常的。

  • 这个类上面,需要使用【@ControllerAdvice】注解,表示该类会通过AOP的方式拦截所有Controller层抛出的所有异常。
  • 在该类里面,定义处理异常的方法,并且使用【@ExceptionHandler】注解,指定当前方法处理的异常类型。
package com.spring.boot.demo.common.exception;import com.spring.boot.demo.common.resp.Result;
import org.springframework.util.CollectionUtils;
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 java.util.List;/*** @author ZhuYouBin* @version 1.0.0* @Date: 2022/10/29 21:00* @Description 全局异常处理类*/
@ControllerAdvice // 指定AOP拦截Controller层方法
public class GlobalExceptionHandler {/*** 统一异常处理*/@ExceptionHandler(value = {Exception.class})@ResponseBodypublic Result commonHandler(Exception e) {e.printStackTrace();// 返回错误信息return Result.failure(e.getMessage());}/*** 捕获我们自定义的异常*/@ExceptionHandler(value = {BizException.class})@ResponseBodypublic Result bizExceptionHandler(BizException e) {e.printStackTrace();// 返回错误信息return Result.failure(e.getMessage());}/** 参数校验异常处理 */@ExceptionHandler(MethodArgumentNotValidException.class)@ResponseBodypublic Result exception(MethodArgumentNotValidException e) {e.printStackTrace();// 保存错误提示信息String message = "参数校验失败";// 从异常对象中拿到 ObjectError 对象List allErrors = e.getBindingResult().getAllErrors();if (!CollectionUtils.isEmpty(allErrors)) {// 返回第一个校验失败的参数名称message = allErrors.get(0).getDefaultMessage();}// 返回参数校验信息return Result.failure(message);}}

到这里,全局异常处理类就创建好啦,下面继续创建统一参数校验(注意:上面处理参数校验异常的时候,会报错,那是因为没有引入下面两个参数校验的依赖)。

三、SpringBoot统一参数校验

3.1、引入参数校验依赖

参数校验需要引入validation依赖,如下所示:


javax.validationvalidation-api


org.hibernate.validatorhibernate-validator

3.2、创建测试实体类

package com.spring.boot.demo.pojo;import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
import java.io.Serializable;/*** @author ZhuYouBin* @version 1.0.0* @Date: 2022/10/29 21:45* @Description*/
public class User implements Serializable {@NotBlank(message = "用户名称不能为空")@Size(min = 1, max = 50, message = "用户名称长度必须在1到50之间")private String username;@NotBlank(message = "用户密码不能为空")@Size(min = 1, max = 30, message = "用户密码长度必须在1到30之间")private String password;@NotBlank(message = "邮箱不能为空")@Email(message = "邮箱格式不正确")private String email;public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public String getEmail() {return email;}public void setEmail(String email) {this.email = email;}@Overridepublic String toString() {return "User{" +"username='" + username + '\'' +", password='" + password + '\'' +", email='" + email + '\'' +'}';}
}

3.3、创建测试控制器

package com.spring.boot.demo.controller;import com.spring.boot.demo.common.exception.BizException;
import com.spring.boot.demo.common.resp.Result;
import com.spring.boot.demo.pojo.User;
import org.springframework.web.bind.annotation.*;import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;/*** @author ZhuYouBin* @version 1.0.0* @Date: 2022/10/29 21:44* @Description*/
@RestController
@RequestMapping("/api")
public class TestController {@GetMapping("/success")public Result> success() {List list = new ArrayList<>();for (int i = 0; i < 3; i++) {User user = new User();user.setUsername("text-name00" + i);user.setPassword("pass-00" + i);user.setEmail("test@qq.com");list.add(user);}return Result.>success().data(list);}@GetMapping("/error")public Result failure() {int i = 10;// 模拟异常情况int ans = i / 0;return Result.success();}@GetMapping("/error02")public Result failure02() {int i = 10;// 模拟异常情况try {int ans = i / 0;} catch (Exception e) {throw new BizException("抛出自定义异常");}return Result.success();}@PostMapping("/error03")public Result param(@RequestBody @Valid User user) {// 测试参数校验异常, 必须使用【@Valid】注解生效return Result.success().data(user);}}

3.4、运行测试

启动工程,使用Postman一次访问上面四个请求地址,可以看到返回结果。

到此,SpringBoot统一异常处理、统一结果响应、统一参数校验就成功啦。

综上,这篇文章结束了,主要介绍如何利用SpringBoot框架实现统一异常处理、统一结果响应、统一参数校验。

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
客厅放八骏马摆件可以吗(家里摆... 今天给各位分享客厅放八骏马摆件可以吗的知识,其中也会对家里摆八骏马摆件好吗进行解释,如果能碰巧解决你...
苏州离哪个飞机场近(苏州离哪个... 本篇文章极速百科小编给大家谈谈苏州离哪个飞机场近,以及苏州离哪个飞机场近点对应的知识点,希望对各位有...