测试开发专题: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 ...
随机推荐
- 通过神秘代码登录自己的QQ
通过神秘代码登录自己的QQ 如图:是怎么做成的呢? 其实很明显,这个是QQ号码的16进制 所以网上搜索进制转换打开一个网页 输入自己的QQ号码,得到16进制的QQ号码 在QQ页面账号处先添加0x然后复 ...
- I NEED A OFFER! HDU - 1203
概率+0 1背包 要算成功的最大概率,那就是失败的最小概率,所以01背包直接让失败的概率最小就行了. 注意: 概率与概率之间是要相乘的,不是相加. #include<bits/stdc++.h& ...
- 数据结构与算法--二分搜索(binary search)
前言 之前面试准备秋招,重新翻起了<编程之美>.在第三章节看到了一道关于二分搜索的讨论,觉得有许多细节是自己之前也没怎么特别注意地方,比如二分搜索的初始条件,转化.终止条件之类的. 问题 ...
- 曹工杂谈--只用一个命令,centos系统里装了啥软件,啥时候装的,全都清清楚楚
前言 一直以来,对linux的掌握就是半桶水的状态,经常yum装个东西,结果依赖一堆东西:然后再用源码装个东西,只知道make.make install,背后干了啥也不清楚了,卸载也不方便. 这几天工 ...
- 7、窗口函数 & Windows 的 Operator demo
代码地址:https://gitee.com/nltxwz_xxd/abc_bigdata 一.窗口函数 在定义了窗口分配器之后,我们需要为每一个窗口明确的指定计算逻辑,这个就是窗口函数要做的事情,当 ...
- Golang——Cron 定时任务
开门见山写一个 package main import ( "fmt" "github.com/robfig/cron" "log" &qu ...
- vue-cli3.0 gui初体验
为什么80%的码农都做不了架构师?>>> 介绍 新版的vuecli3.0提供了一个vue ui这个命令,这个命令是做什么的呢,这里引用官网的一段介绍 vue ui 你可以通过 v ...
- Git经典学习指南
https://www.liaoxuefeng.com/ 转载于:https://blog.51cto.com/4402071/1977945
- 加分二叉树 vijos1991 NOIP2003第三题 区间DP/树形DP/记忆化搜索
描述 设一个n个节点的二叉树tree的中序遍历为(l,2,3,-,n),其中数字1,2,3,-,n为节点编号.每个节点都有一个分数(均为正整数),记第i个节点的分数为di,tree及它的每个子树都有一 ...
- C++编程入门题目--No.3
题目:一个整数,它加上100后是一个完全平方数,再加上168又是一个完全平方数,请问该数是多少? 程序分析: 在10万以内判断,先将该数加上100后再开方,再将该数加上268后再开方,如果开方后 的结 ...