上文测试开发专题:spring-boot统一异常捕获咱们讨论了java异常以及如何使用Spring-Boot捕获异常,可是没有去说捕获异常后该如何进一步处理,这篇文章咱们将对这个遗留的问题进行讨论.html
咱们但愿在程序发生异常的时候,可以给用户返回一个比较友好且明确的信息,对于api接口来讲,一种比较好的格式是json,相似于下面这种格式前端
{ "code": "10001", "message": "消息", "uri":"Get /v2/banner" }
因此须要一个对象来描述这种数据格式:java
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; } }
上文咱们谈到从开发者的角度来讲,异常分为已知异常和未知异常,针对不一样的异常使用不一样的异常处理函数进行处理,咱们以前定义两个处理函数spring
@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
,序列化后返回给用户json
@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写到日志里,方便后面问题查询。api
返回给用户的message能够自定义一个通用的,好比服务器错误什么的。浏览器
咱们来测试一下,在Controller里抛出一个Exception:服务器
@RequestMapping(value = "/v2/banner", method = {RequestMethod.GET}) public String test() throws Exception{ throw new Exception("我抛出来的"); }
而后再浏览器里访问,发现出错了app
这里的这个异常,看不太懂,回到异常处理方法当中去,咱们直接是返回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是一个泛型类,是能够直接return回去的,能够设置不少属性,包括status、headers、body等。
用ResponseEntity来自定义已知异常处理方法的返回信息:
而后再Controller里抛出一个NotFoundException,从新运行程序,访问路由:
能够看到也可以返回正确的状态码。
本篇文章咱们介绍了,定义错误响应以及如何返回自定义的错误信息,多种方式进行定制状态码,可是咱们在文章的错误信息都是硬编码在代码里的,这样很很差管理,因此下篇文章咱们将介绍如何对错误信息管理,敬请关注!!!
本文连接:https://www.immortalp.com/articles/2020/05/10/1589096782703.html
欢迎你们去 个人博客 瞅瞅,里面有更多关于测试实战的内容哦!!