上文测试开发专题:spring-boot统一异常捕获我们讨论了java异常以及如何使用Spring-Boot捕获异常,但是没有去说捕获异常后该如何进一步处理,这篇文章我们将对这个遗留的问题进行讨论.

统一错误响应定义

我们希望在程序发生异常的时候,能够给用户返回一个比较友好且明确的信息,对于api接口来说,一种比较好的格式是json,类似于下面这种格式

{
"code": "10001",
"message": "消息",
"uri":"Get /v2/banner"
}

所以需要一个对象来描述这种数据格式:

public class UnifyResponse {
private int code;
private String message;
private String requestUri; public UnifyResponse(int code, String message, String requestUri){
this.code = code;
this.message = message;
this.requestUri = requestUri;
}
}

错误响应处理

上文我们谈到从开发者的角度来说,异常分为已知异常和未知异常,针对不同的异常使用不同的异常处理函数进行处理,我们之前定义两个处理函数

@ControllerAdvice
public class GlobalExceptionAdvice { /**
* 处理未知异常
* @param req
* @param ex
*/
@ExceptionHandler(value = Exception.class)
public void handleHttpException(HttpServletRequest req, Exception ex){
System.out.println("发生异常了");
} /**
* 处理已知异常
* @param req
* @param ex
*/
@ExceptionHandler(value = HttpException.class)
public void handleHttpException(HttpServletRequest req, HttpException ex){ System.out.println("发生了 HttpException");
}
}

当未知异常发生时,需要将异常信息存储进 UnifyResponse,序列化后返回给用户

@ExceptionHandler(value = Exception.class)
public UnifyResponse handleHttpException(HttpServletRequest req, Exception ex){
String uri = req.getRequestURI();
String method = req.getMethod();
System.out.println(ex.getMessage());
return new UnifyResponse(9999, "服务器错误", method + " " + uri);
}

对于未知异常我们也不知道发生了什么,所以这里的code码就定义一个通用的,虽然Exception里面有message,但是这里不建议将这个异常里的message返回给用户,这位可能涉及到代码结构的一些东西,而且即使将这个信息返回给前端,他也不知道是啥问题,没什么意义,所以可以将这个message写到日志里,方便后面问题查询。

返回给用户的message可以自定义一个通用的,比如服务器错误什么的。

我们来测试一下,在Controller里抛出一个Exception:

 @RequestMapping(value = "/v2/banner", method = {RequestMethod.GET})
public String test() throws Exception{
throw new Exception("我抛出来的");
}

然后再浏览器里访问,发现出错了

这里的这个异常,看不太懂,回到异常处理方法当中去,我们直接是返回UnifyResponse对象,如果这里返回的是一个字符串,那会不会出错呢,再是试一下看看,结果还是会报这个错,也就是说无论这里返回自定义对象还是字符串,都会出现问题,那就是说spring-boot压根儿就可能不识别我们返回的东西。

在spring-boot里有一个注解@ResponseBody,可以将我们的返回值,绑定的响应的body上,我们来试一下看看能否解决这个问题。

会发现,上面改的返回String是可以成功的,但是返回UnifyResponse对象还是报错,而且报错和之前的还不一样

刚才报的还是404的错误,现在变成了500,哪里错了呢。

我们来看一下UnifyResponse的定义,我们定义了三个私有的成员变量,但是确没有定义getter方法,那在序列化的时候是无法获取到成员变量的值的,所以报错,这里我们加上:

然后在运行程序,访问路由:

返回的响应就和我们预期的一样了,但是从上面的图中,看到返回的状态码是200,这显然是不对的,因为服务器已经出错了,状态码应该是500,所以这里要对状态码进行自定义。

自定义状态码

spring-boot提供了两种可以自定义状态码的方式:

注解

直接在异常处理函数上标记一个叫做

@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)并制定状态码的枚举值

重启程序,访问路由:

可以看到状态码已经变成500了。

上面使用注解的的形式虽然能够实现我们的目的,但是这种方式不太灵活,,这里很多的response的设置都是spring-boot帮我们做了,如果需要做一些自定义就不是太方便,接下来的这种方式确可以让我们通过代码灵活的进行控制。

ResponseEntity

ResponseEntity是一个泛型类,是可以直接return回去的,可以设置很多属性,包括status、headers、body等。

用ResponseEntity来自定义已知异常处理方法的返回信息:

然后再Controller里抛出一个NotFoundException,重新运行程序,访问路由:

可以看到也能够返回正确的状态码。

总结

本篇文章我们介绍了,定义错误响应以及如何返回自定义的错误信息,多种方式进行定制状态码,但是我们在文章的错误信息都是硬编码在代码里的,这样很不好管理,所以下篇文章我们将介绍如何对错误信息管理,敬请关注!!!

本文链接:https://www.immortalp.com/articles/2020/05/10/1589096782703.html

欢迎大家去 我的博客 瞅瞅,里面有更多关于测试实战的内容哦!!

测试开发专题:spring-boot自定义异常返回的更多相关文章

  1. spring boot 接口返回值封装

    Spring Boot 集成教程 Spring Boot 介绍 Spring Boot 开发环境搭建(Eclipse) Spring Boot Hello World (restful接口)例子 sp ...

  2. 快速开发架构Spring Boot 从入门到精通 附源码

    导读 篇幅较长,干货十足,阅读需花费点时间.珍惜原创,转载请注明出处,谢谢! Spring Boot基础 Spring Boot简介 Spring Boot是由Pivotal团队提供的全新框架,其设计 ...

  3. 后端开发实践——Spring Boot项目模板

    在我的工作中,我从零开始搭建了不少软件项目,其中包含了基础代码框架和持续集成基础设施等,这些内容在敏捷开发中通常被称为"第0个迭代"要做的事情.但是,当项目运行了一段时间之后再来反 ...

  4. spring boot + vue + element-ui全栈开发入门——spring boot后端开发

    前言 本文讲解作为后端的spring boot项目开发流程,如果您还不会配置spring boot环境,就请点击<玩转spring boot——快速开始>,如果您对spring boot还 ...

  5. 开发一个Spring Boot Starter!

    在上一篇文章中,我们已经了解了一个starter实现自动配置的基本流程,在这一小结我们将复现上一过程,实现一个自定义的starter. 先来分析starter的需求: 在项目中添加自定义的starte ...

  6. Spring Boot 统一返回结果及异常处理

    在 Spring Boot 构建电商基础秒杀项目 (三) 通用的返回对象 & 异常处理 基础上优化.调整 一.通用类 1.1 通用的返回对象 public class CommonReturn ...

  7. 【星云测试】开发者测试-采用精准测试工具对Spring Boot应用进行测试

    简介:本文主要介绍把现今主流的springboot框架项目和精准测试工具进行结合和应用,通过精准测试的数据穿透.数据采集.测试用例与代码的双向追溯.数据分析等一系列精准测试的特有功能,达到对项目质量的 ...

  8. 从零开始开发一个Spring Boot Starter

    一.Spring Boot Starter简介 Starter是Spring Boot中的一个非常重要的概念,Starter相当于模块,它能将模块所需的依赖整合起来并对模块内的Bean根据环境( 条件 ...

  9. Spring boot之返回json数据

    1.步骤: 1. 编写实体类Demo 2. 编写getDemo()方法 3. 测试 2.项目构建 编写实体类Demo package com.kfit; /** * 这是一个测试实体类. */ pub ...

随机推荐

  1. 挑战全网最幽默的Vuex系列教程:第二讲 Vuex旗下的State和Getter

    先说两句 上一讲 「Vuex 到底是个什么鬼」,已经完美诠释了 Vuex 的牛逼技能之所在(纯属自嗨).如果把 Vuex 比喻成农药里面的刘备,那就相当于你现在已经知道了刘备他是一个会打枪的力量型英雄 ...

  2. python os模块获取指定目录下的文件列表

    bath_path = r"I:\ner_results\ner_results" dir_list1 = os.listdir(bath_path) for dir1 in di ...

  3. 【编程之美】超时重传,滑动窗口,可靠性传输原理C语言实现

    版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://www.cnblogs.com/lihuidashen/p/128003 ...

  4. 用python把技术文档中,每个模块系列截图生成一个动态GIF

    前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 最近在写技术文档的时候,发现一个问题.对于每个技术步骤,都需要一个截图,这 ...

  5. PHP的yield是个什么玩意

    来源:https://segmentfault.com/a/1190000018457194 其实,我并不是因为迭代或者生成器或者研究PHP手册才认识的yield,要不是协程,我到现在也不知道PHP中 ...

  6. 2019-2020-1 20199303《Linux内核原理与分析》第九周作业

    进程的切换和一般执行过程 知识总结 操作系统原理中介绍了大量进程调度算法,这些算法从实现的角度看仅仅是从运行队列中选择一个新进程,选择的过程中运用了不同的策略而已. 对于理解操作系统的工作机制,反而是 ...

  7. Linux网络管理员:网络概论

    1.TCP/IP网络 包是适合通过网络传输的一小段数据,交换发生于网络的每一个链接点.当不同来源的包必须经过同一条线路传输数据时,这些包将被交替传输. 2.TCP/IP协议组 TCP/IP协议簇是In ...

  8. Spring Boot中的测试

    文章目录 简介 添加maven依赖 Repository测试 Service测试 测试Controller @SpringBootTest的集成测试 Spring Boot中的测试 简介 本篇文章我们 ...

  9. Scala教程之:可变和不变集合

    文章目录 mutable HashMap immutable HashMap 集合在程序中是非常有用的,只有用好集合才能真正感受到该语言的魅力.在scala中集合主要在三个包里面:scala.coll ...

  10. docker-compose简介及安装

    一.简介 Compose是用于定义和运行多容器Docker应用程序的工具,是docker的服务编排工具,主要应用于构建基于Docker的复杂应用,compose通过一个配置文件来管理多个docker容 ...