SpringBoot统一返回和统一异常处理

  • Session 认证和 Token 认证

  • 过滤器和拦截器

  • SpringBoot统一返回和统一异常处理

上篇文章我们学习了基于 Token 认证的登录功能实现,分别使用了过滤器和拦截器去实现登录功能,这篇文章我们来学习项目中常用的统一返回结果和统一异常处理。

一、统一返回结果

前后端分离时代,如果没有一个统一的数据返回格式,前后端调试时,前端开发人员会骂娘的,同时约定相同的返回接口数据也有助于高效的工作。

通常统一返回的格式包含三部分:

  • code:状态码,一般 200 表示正常
  • message:状态码对应的描述。
  • data:返回的数据
1.1、统一返回对象

新建一个 SpringBoot 项目定义通用的响应对象

package com.laoxiang.utils;import com.fasterxml.jackson.annotation.JsonInclude;import java.io.Serializable;/*** @author db* @version 1.0* @description ResponseResult* @since 2023/7/12*/
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ResponseResult<T> implements Serializable {private static final long serialVersionUID = 2233637474601103587L;// 接口响应状态码private Integer code;// 接口响应信息private String msg;// 接口响应的数据private T data;public ResponseResult() {this.code = AppHttpCodeEnum.SUCCESS.getCode();this.msg = AppHttpCodeEnum.SUCCESS.getMsg();}public ResponseResult(Integer code, T data) {this.code = code;this.data = data;}public ResponseResult(Integer code, String msg, T data) {this.code = code;this.msg = msg;this.data = data;}public ResponseResult(Integer code, String msg) {this.code = code;this.msg = msg;}public static ResponseResult errorResult(int code, String msg) {ResponseResult result = new ResponseResult();return result.error(code, msg);}public static ResponseResult okResult() {ResponseResult result = new ResponseResult();return result;}public static ResponseResult okResult(int code, String msg) {ResponseResult result = new ResponseResult();return result.ok(code, null, msg);}public static ResponseResult okResult(Object data) {ResponseResult result = setAppHttpCodeEnum(AppHttpCodeEnum.SUCCESS, AppHttpCodeEnum.SUCCESS.getMsg());if (data != null) {result.setData(data);}return result;}public static ResponseResult errorResult(AppHttpCodeEnum enums) {return setAppHttpCodeEnum(enums, enums.getMsg());}public static ResponseResult errorResult(AppHttpCodeEnum enums, String msg) {return setAppHttpCodeEnum(enums, msg);}public static ResponseResult setAppHttpCodeEnum(AppHttpCodeEnum enums) {return okResult(enums.getCode(), enums.getMsg());}private static ResponseResult setAppHttpCodeEnum(AppHttpCodeEnum enums, String msg) {return okResult(enums.getCode(), msg);}public ResponseResult<?> error(Integer code, String msg) {this.code = code;this.msg = msg;return this;}public ResponseResult<?> ok(Integer code, T data) {this.code = code;this.data = data;return this;}public ResponseResult<?> ok(Integer code, T data, String msg) {this.code = code;this.data = data;this.msg = msg;return this;}public ResponseResult<?> ok(T data) {this.data = data;return this;}public Integer getCode() {return code;}public void setCode(Integer code) {this.code = code;}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}public T getData() {return data;}public void setData(T data) {this.data = data;}
}
1.2、系统常量

上面代码中提到了常量 AppHttpCodeEnum,定义自己的应用程序特定状态码,来表示具体的情况。通过定义的状态码就可以知道具体代表什么意思。


package com.laoxiang.utils;/*** @author db* @version 1.0* @description AppHttpCodeEnum* @since 2023/7/12*/
public enum AppHttpCodeEnum {// 成功SUCCESS(200,"操作成功"),// 失败ERROR(500,"操作失败"),int code;String msg;AppHttpCodeEnum(int code, String errorMessage){this.code = code;this.msg = errorMessage;}public int getCode() {return code;}public String getMsg() {return msg;}
}
1.3、web 层统一响应结果

下面的例子,可以看到在实际项目中接口返回值。

二、统一异常处理

程序开发中不可避免的会遇到异常现象,如果不进行处理,遇到异常时,开发人员不能清晰地处理问题,或者使用 try{...}catch{...} 代码块进行处理,但是满屏的 try{...}catch{...} 代码块造成代码过于臃肿。

有没有更好的处理方式呢?全局统一异常处理应运而生。@ControllerAdvice 注解搭配 @ExceptionHandler 进行全局统一异常处理。

2.1、@ControllerAdvice注解
  • @ControllerAdvice注解:用于声明一个全局控制器 Advice,相当于把 @ExceptionHandler@InitBinder@ModelAttribute 注解的方法集中到一个地方。放在特定类上,被认为是全局异常处理器。
2.2、ExceptionHandler 注解
  • 用于定义异常处理方法,处理特定类型的异常。放在全局异常处理器类中的具体方法上。
    通过这两个注解的配合,可以实现全局的异常处理。当控制器中抛出异常时,SpringBoot 会自动调用匹配的 @ExceptionHandler 方法来处理异常,并返回定义的响应。

步骤如下:

  1. 新建一个统一异常处理类
  2. 类上标注 @RestControllerAdvice 注解
  3. 在方法上标注 @ExceptionHandler 注解,并且指定需要捕获的异常,可以同时捕获多个。

新建 exception 包,在包下新建 GlobalExceptionHandler 类。代码如下:

package com.duan.execption;import com.duan.pojo.AppHttpCodeEnum;
import com.duan.pojo.ResponseResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;/*** @author db* @version 1.0* @description GlobalExceptionHandler* @since 2023/7/23*/
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {// 全局异常@ExceptionHandler(Exception.class)public ResponseResult exceptionHandler(Exception e){//打印异常信息log.error("出现了异常! {}",e);//从异常对象中获取提示信息封装返回return ResponseResult.errorResult(AppHttpCodeEnum.SYSTEM_ERROR.getCode(),e.getMessage());}// 自定义异常@ExceptionHandler(LxAdminException.class)public ResponseResult LxAdminExceptionHandler(LxAdminException e){//打印异常信息log.error("出现了异常! {}",e);//从异常对象中获取提示信息封装返回return ResponseResult.errorResult(e.getCode(),e.getMsg());}}

exception包下新建自定义异常处理类 LxAdminException


package com.duan.execption;import com.duan.pojo.AppHttpCodeEnum;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;/*** @author db* @version 1.0* @description LxAdminException  自定义异常* @since 2023/7/23*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class LxAdminException extends RuntimeException{private int code;private String msg;public LxAdminException(AppHttpCodeEnum httpCodeEnum) {super(httpCodeEnum.getMsg());this.code = httpCodeEnum.getCode();this.msg = httpCodeEnum.getMsg();}
}
2.3、统一异常处理使用

在业务开发中,可以在 service 层处理业务时,可以手动抛出异常,由全局异常处理器处理进行统一处理。


package com.duan.controller;import com.duan.execption.LxAdminException;
import com.duan.pojo.AppHttpCodeEnum;
import com.duan.pojo.ResponseResult;
import com.duan.pojo.User;
import com.duan.utils.JWTUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;import java.util.HashMap;
import java.util.UUID;/*** @author db* @version 1.0* @description LoginController* @since 2023/12/19*/
@RestController
@Slf4j
public class LoginController {@PostMapping("/login")public ResponseResult login(@RequestBody User user){log.info("这是正常日志");if(!"admin".equals(user.getUsername()) && !"123456".equals(user.getPassword())){throw new LxAdminException(AppHttpCodeEnum.LOGIN_ERROR);}else{HashMap<String, Object> map = new HashMap<>();map.put("id", UUID.randomUUID().toString());// 生成tokenString token = JWTUtils.generateJwt(map);return ResponseResult.okResult(token);}}}

当我们请求接口时,假如用户名称或者密码错误,接口就会响应:

{"code": 505,"msg": "用户名或密码错误","data": null
}

实际开发中还有许多的异常需要捕获,比如 Token 失效、过期等异常, 如果整合了其他的框架,还要注意这些框架抛出的异常,比如Spring Security 等框架。

代码地址:https://gitee.com/duan138/practice-code/tree/dev/resultException

三、总结

SpringBoot 项目中,统一返回和统一异常处理是非常常用的一环,它们能提高应用的可读性和可维护性,统一返回有助于保持代码一致性和规范性,在前后端联调时更加方便,统一异常处理,减少了代码冗余,对异常处理更加易于管理。

下一篇我们来看看 SpringBoot 项目中怎么进行日志处理。


改变你能改变的,接受你不能改变的,关注公众号:程序员康康,一起成长,共同进步。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/642496.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【LeetCode每日一题】670. 最大交换

2024-1-22 文章目录 [670. 最大交换](https://leetcode.cn/problems/maximum-swap/)思路&#xff1a; 670. 最大交换 思路&#xff1a; 从后往前遍历整数的字符数组&#xff0c;找到第一个比当前最大值小的数字&#xff0c;然后将该数字与最大值进行交换。 将给定的整数转换为…

数据库-分库分表初探

文章目录 分库策略垂直切分垂直分库&#xff08;专库专用&#xff09;垂直分表&#xff08;拆表&#xff09;优点缺点 水平(Sharding)切分水平分表库内分表分库分表优点缺点 分表策略hash取模方案range范围区间取值方案映射表方案 分库分表问题事务一致性问题跨节点关联查询跨节…

浅谈拨测在网络安全中的应用

在当今数字化时代&#xff0c;网络安全成为各个行业和组织关注的焦点。为了保障网络的稳定性和信息的安全&#xff0c;拨测安全性成为一种日益重要的工具。本文将介绍拨测在网络安全中的应用&#xff1a; 1.威胁模拟 通过威胁模拟&#xff0c;拨测安全性可以模拟各种网络攻击&a…

初谈C++:命名空间、输入输出

文章目录 前言C关键字命名空间命名空间的作用命名空间定义命名空间的使用 C的输入&输出 前言 什么是C&#xff1f; C语言是结构化和模块化的语言&#xff0c;适合处理较小规模的程序。对于复杂的问题&#xff0c;规模较大的程序&#xff0c;需要高度的抽象和建模时&#…

mockjs(3)

mockjs&#xff08;1&#xff09; mockjs&#xff08;2&#xff09; 这篇主要是Mock.random工具类&#xff0c;前段要用的话主要是在模版中的占位符。mockjs&#xff08;1&#xff09;里面的3.2 6 Mock.random Mock.Random 是一个工具类&#xff0c;用于生成各种随机数据。 …

Wpf 使用 Prism 实战开发Day15

用户登录和注册接口 一.创建用户登录注册控制器&#xff08;LoginController&#xff09; /// <summary>/// 用户登录注册控制器/// </summary>[ApiController][Route("api/[controller]/[action]")]public class LoginController: ControllerBase{} 二.…

houdini fft 使用三层for each结构 以及for 问题

for each 中 使用 attrib wrangle detail时&#xff0c;不连接foreach_count1&#xff0c;只运行一次 for each 问题 merge eachiteration 对结构进行合并 transform 位置的移动针对的是原位置对原点的距离&#xff0c;而非移动后置0后再移

【C++】list容器功能模拟实现

介绍 上一次介绍了list队容器的迭代器模拟&#xff0c;这次模拟实现list的简单功能&#xff0c;尤其要注意构造函数、析构函数、以及赋值运算符重载的实现。 list容器需要接纳所有类型的数据&#xff0c;因此&#xff0c;结构设置与迭代器设置同理&#xff0c;需要引入结点&…

Python中的open与JSON的使用

目录 1 使用 open 函数进行文件操作 2 使用 json 模块进行 JSON 数据处理&#xff1a; 2.1 写入JSON 文件 2.2 读取JSON 文件 在 Python 中&#xff0c;open 函数和 json 模块常用于文件的读写和 JSON 数据的处理。 1 使用 open 函数进行文件操作 open 函数用于打开文件…

“智汇语言·驭领未来”——系列特辑:LLM大模型信息获取与企业应用变革

“智汇语言驭领未来”——系列特辑&#xff1a;LLM大模型信息获取与企业应用变革 原创 认真的飞速小软 飞速创软 2024-01-16 09:30 发表于新加坡 本期引言 LLM&#xff08;Large Language Model&#xff09;大型语言模型以其自然语言理解和生成能力&#xff0c;正以前所未有的…

libtorch学习第六

构建卷积网络 #include<torch/torch.h> #include<torch/script.h> #include<iostream>using std::cout; using std::endl;class LinearBnReluImpl : public torch::nn::Module { private:torch::nn::Linear ln{ nullptr };torch::nn::BatchNorm1d bn{ nullp…

开源的测试平台快2千星了,能带来多少收益呢

最近看了下自己去年初开源的测试平台&#xff0c;star一起算的话也到1.7k了&#xff1a; 做开源的初心一方面是想把自己的理解和思想展示出来&#xff0c;另一方面是想进一步打造个人IP&#xff0c;提升影响力&#xff08;其实这个想法很早之前就有了&#xff0c;计划过无数次但…

Day 28 | 回溯 93.复原IP地址 、78.子集 、 90.子集II

93.复原IP地址 题目 文章讲解 视频讲解 思路&#xff1a;每轮开始的位置需要变化就需要设置start class Solution {List<String> result new ArrayList<>();public List<String> restoreIpAddresses(String s) {if (s.length() < 4 ||s.length() >…

服务器数据恢复—服务器进水导致阵列中磁盘同时掉线的数据恢复案例

服务器数据恢复环境&#xff1a; 数台服务器数台存储阵列柜&#xff0c;共上百块硬盘&#xff0c;划分了数十组lun。 服务器故障&检测&#xff1a; 外部因素导致服务器进水&#xff0c;进水服务器中一组阵列内的所有硬盘同时掉线。 北亚数据恢复工程师到达现场后发现机房内…

Shopee夏季选品策略:吸引消费者,提高销售的10个有效方法

在Shopee平台上进行夏季选品时&#xff0c;卖家需要采取一些策略来吸引消费者并提高销售。本文将介绍十个有效的方法&#xff0c;帮助卖家在夏季市场做好准备&#xff0c;提供符合季节需求的产品&#xff0c;从而提高销售业绩。 先给大家推荐一款shopee知虾数据运营工具知虾免…

System.Data.SqlClient.SqlException:“在与 SQL Server 建立连接时出现与网络相关的或特定于实例的错误

目录 背景: 过程: SQL Express的认识: 背景: 正在运行程序的时候&#xff0c;我遇到一个错误提示&#xff0c;错误信息如下&#xff0c;当我将错误信息仔细阅读了一番&#xff0c;信息提示的很明显&#xff0c;错误出现的来源就是连接数据库代码这块string connStr "s…

【Linux工具篇】编辑器vim

目录 vim的基本操作 进入vim(正常模式&#xff09; 正常模式->插入模式 插入模式->正常模式 正常模式->底行模式 底行模式->正常模式 底行模式->退出vim vim正常模式命令集 vim插入模式命令集 vim末行模式命令集 vim操作总结 vim配置 Linux编译器…

服务器的异步通信——RabbitMQ

目录 一、同步通信 VS 异步通信 二、MQ——消息队列 RabbitMQ RabbitMQ安装 RabbitMQ的整体架构 常见消息模型 基本消息队列&#xff08;BasicQueue&#xff09; 工作消息队列&#xff08;WorkQueue&#xff09; 发布、订阅&#xff08;Publish、Subscribe&#xff0…

CSS文本外观属性内容(知识点1)

知识引入 使用HTML可以对文本外观进行简单的控制&#xff0c;但是效果并不理想&#xff0c;为此CSS提供了一系列的文本外观样式属性&#xff0c;具体如下。 color:文本颜色 color属性用于定义文本的颜色&#xff0c;其取值方式有以下三种。 &#xff08;1&#xff09;预定义…

爬取的数据可以入表吗?怎样入表?

合规是数据入表的前提。当前爬虫数据是非常敏感的&#xff0c;因为爬虫极容易造成两大不合规的问题&#xff1a;一是没有经过个人同意获取数据&#xff0c;二是爬取的数据里可能含有个人敏感信息也是一个问题。现在法律对于这部分非常严苛&#xff0c;如果企业里有50条未获得授…