测试开发专题:spring-boot自定义异常返回
上文测试开发专题: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自定义异常返回的更多相关文章
- spring boot 接口返回值封装
Spring Boot 集成教程 Spring Boot 介绍 Spring Boot 开发环境搭建(Eclipse) Spring Boot Hello World (restful接口)例子 sp ...
- 快速开发架构Spring Boot 从入门到精通 附源码
导读 篇幅较长,干货十足,阅读需花费点时间.珍惜原创,转载请注明出处,谢谢! Spring Boot基础 Spring Boot简介 Spring Boot是由Pivotal团队提供的全新框架,其设计 ...
- 后端开发实践——Spring Boot项目模板
在我的工作中,我从零开始搭建了不少软件项目,其中包含了基础代码框架和持续集成基础设施等,这些内容在敏捷开发中通常被称为"第0个迭代"要做的事情.但是,当项目运行了一段时间之后再来反 ...
- spring boot + vue + element-ui全栈开发入门——spring boot后端开发
前言 本文讲解作为后端的spring boot项目开发流程,如果您还不会配置spring boot环境,就请点击<玩转spring boot——快速开始>,如果您对spring boot还 ...
- 开发一个Spring Boot Starter!
在上一篇文章中,我们已经了解了一个starter实现自动配置的基本流程,在这一小结我们将复现上一过程,实现一个自定义的starter. 先来分析starter的需求: 在项目中添加自定义的starte ...
- Spring Boot 统一返回结果及异常处理
在 Spring Boot 构建电商基础秒杀项目 (三) 通用的返回对象 & 异常处理 基础上优化.调整 一.通用类 1.1 通用的返回对象 public class CommonReturn ...
- 【星云测试】开发者测试-采用精准测试工具对Spring Boot应用进行测试
简介:本文主要介绍把现今主流的springboot框架项目和精准测试工具进行结合和应用,通过精准测试的数据穿透.数据采集.测试用例与代码的双向追溯.数据分析等一系列精准测试的特有功能,达到对项目质量的 ...
- 从零开始开发一个Spring Boot Starter
一.Spring Boot Starter简介 Starter是Spring Boot中的一个非常重要的概念,Starter相当于模块,它能将模块所需的依赖整合起来并对模块内的Bean根据环境( 条件 ...
- Spring boot之返回json数据
1.步骤: 1. 编写实体类Demo 2. 编写getDemo()方法 3. 测试 2.项目构建 编写实体类Demo package com.kfit; /** * 这是一个测试实体类. */ pub ...
随机推荐
- java 第七周课后作业0417
定义一个矩形类Rectangle:(知识点:对象的创建和使用)1 定义三个方法:getArea()求面积.getPer()求周长,showAll()分别在控制台输出长.宽.面积.周长.2 有2个属性: ...
- CSS 中你应该了解的 BFC
我们常说的文档流其实分为定位流.浮动流和普通流三种.而普通流其实就是指BFC中的FC.FC是formatting context的首字母缩写,直译过来是格式化上下文,它是页面中的一块渲染区域,有一套渲 ...
- 【题解】P1291 百事世界杯之旅 - 期望dp
P1291 [SHOI2002]百事世界杯之旅 声明:本博客所有题解都参照了网络资料或其他博客,仅为博主想加深理解而写,如有疑问欢迎与博主讨论✧。٩(ˊᗜˋ)و✧*。 题目描述 "--在 \ ...
- 基于udp协议的套接字通信
服务端: import socket server=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) server.bind(('127.0.0.1',8 ...
- 负载均衡服务之HAProxy基础配置(四)
前文我们聊了haproxy的状态页配置,状态页中显示各参数的含义,以及基于cookie做会话保持的配置,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/12776 ...
- 使用pthread进行编程
使用pthread进行并行编程 进程与线程 进程是一个运行程序的实例:线程像一个轻量级的进程:在一个共享内存系统中,一个进程可以有多个线程 POSIX® Threads: 即 Pthreads,是一个 ...
- 7、窗口函数 & Windows 的 Operator demo
代码地址:https://gitee.com/nltxwz_xxd/abc_bigdata 一.窗口函数 在定义了窗口分配器之后,我们需要为每一个窗口明确的指定计算逻辑,这个就是窗口函数要做的事情,当 ...
- linux--配置开发环境 --Apache篇
现在我的的linux服务器上一般都是使用:Apache 和 Nginx 这两种配置. 你现在安装好了,启动了,也无法通过你服务器绑定的网址访问你的网站. 这是你可以通过这个命令查看一下你的80端口: ...
- js事件冒泡于事件捕获
事件冒泡 事件捕获指的是从document到触发事件的那个节点,即自上而下的去触发事件. 事件冒泡是自下而上(从最深节点开始,向上传播事件)的触发事件 //例子 <div id="pa ...
- 2019-2020-1 20199329《Linux内核原理与分析》第十三周作业
<Linux内核原理与分析>第十三周作业 一.本周内容概述 通过重现缓冲区溢出攻击来理解漏洞 二.本周学习内容 1.实验简介 注意:实验中命令在 xfce 终端中输入,前面有 $ 的内容为 ...