最后总结
搞定算法,面试字节再不怕,有需要文章中分享的这些二叉树、链表、字符串、栈和队列等等各大面试高频知识点及解析
最后再分享一份终极手撕架构的大礼包(学习笔记):分布式+微服务+开源框架+性能优化
-
先看异常对象是不是ResponseStatusException类型
-
如果是ResponseStatusException类型,就调用异常对象的getStatus方法作为返回值
-
如果不是ResponseStatusException类型,再看异常类有没有ResponseStatus注解,
-
如果有,就取注解的code属性作为返回值
-
如果异常对象既不是ResponseStatusException类型,也没有ResponseStatus注解,就返回500
- 最后看map的message字段(也就是response body的message字段),在DefaultErrorAttributes是如何生成的:
-
异常对象是不是BindingResult类型
-
如果不是BindingResult类型,就看是不是ResponseStatusException类型
-
如果是,就用getReason作为返回值
-
如果也不是ResponseStatusException类型,就看异常类有没有ResponseStatus注解,如果有就取该注解的reason属性作为返回值
-
如果通过注解取得的reason也无效,就返回异常的getMessage字段
- 上述内容就是本篇精华,但是并未包含分析过程,如果您对Spring Cloud源码感兴趣,请允许欣宸陪伴您来一次短暂的源码阅读之旅
Spring Cloud Gateway错误处理源码
- 首先要看的是配置类ErrorWebFluxAutoConfiguration.java,这里面向spring注册了两个实例,每个都非常重要,咱们先关注第一个,也就是说ErrorWebExceptionHandler的实现类是DefaultErrorWebExceptionHandler:
- 处理异常时,会通过FluxOnErrorResume调用到这个ErrorWebExceptionHandler的handle方法处理,该方法在其父类AbstractErrorWebExceptionHandler.java中,如下图,红框位置的代码是关键,异常返回内容就是在这里决定的:
- 展开这个getRoutingFunction方法,可见会调用renderErrorResponse来处理响应:
@Override
protected RouterFunction getRoutingFunction(ErrorAttributes errorAttributes) {
return route(acceptsTextHtml(), this::renderErrorView).andRoute(all(), this::renderErrorResponse);
}
- 打开renderErrorResponse方法,如下所示,真相大白了!
protected Mono renderErrorResponse(ServerRequest request) {
// 取出所有错误信息
Map<String, Object> error = getErrorAttributes(request, getErrorAttributeOptions(request, MediaType.ALL));
// 构造返回的所有信息
return ServerResponse
// 控制返回码
.status(getHttpStatus(error))
// 控制返回ContentType
.contentType(MediaType.APPLICATION_JSON)
// 控制返回内容
.body(BodyInserters.fromValue(error));
}
- 通过上述代码,咱们得到两个重要结论:
-
返回给调用方的状态码,取决于getHttpStatus方法的返回值
-
返回给调用方的body,取决于error的内容
- 都已经读到了这里,自然要看看getHttpStatus的内部,如下所示,status来自入参:
protected int getHttpStatus(Map<String, Object> errorAttributes) {
return (int) errorAttributes.get(“status”);
}
-
至此,咱们可以得出一个结论:getErrorAttributes方法的返回值是决定返回码和返回body的关键!
-
来看看这个getErrorAttributes方法的庐山真面吧,在DefaultErrorAttributes.java中(回忆刚才看ErrorWebFluxAutoConfiguration.java的时候,前面曾提到里面的东西都很重要,也包括errorAttributes方法):
public Map<String, Object> getErrorAttributes(ServerRequest request, ErrorAttributeOptions options) {
Map<String, Object> errorAttributes = this.getErrorAttributes(request, options.isIncluded(Include.STACK_TRACE));
if (Boolean.TRUE.equals(this.includeException)) {
options = options.including(new Include[]{Include.EXCEPTION});
}
if (!options.isIncluded(Include.EXCEPTION)) {
errorAttributes.remove(“exception”);
}
if (!options.isIncluded(Include.STACK_TRACE)) {
errorAttributes.remove(“trace”);
}
if (!options.isIncluded(Include.MESSAGE) && errorAttributes.get(“message”) != null) {
errorAttributes.put(“message”, “”);
}
if (!options.isIncluded(Include.BINDING_ERRORS)) {
errorAttributes.remove(“errors”);
}
return errorAttributes;
}
- 篇幅所限,就不再展开上述代码了,直接上结果吧:
-
返回码来自determineHttpStatus的返回
-
message字段来自determineMessage的返回
- 打开determineHttpStatus方法,终极答案揭晓,请关注中文注释:
private HttpStatus determineHttpStatus(Throwable error, MergedAnnotation responseStatusAnnotation) {
// 异常对象是不是ResponseStatusException类型
return error instanceof ResponseStatusException
// 如果是ResponseStatusException类型,就调用异常对象的getStatus方法作为返回值
? ((ResponseStatusException)error).getStatus()
// 如果不是ResponseStatusException类型,再看异常类有没有ResponseStatus注解,
一线互联网大厂Java核心面试题库
正逢面试跳槽季,给大家整理了大厂问到的一些面试真题,由于文章长度限制,只给大家展示了部分题目,更多Java基础、异常、集合、并发编程、JVM、Spring全家桶、MyBatis、Redis、数据库、中间件MQ、Dubbo、Linux、Tomcat、ZooKeeper、Netty等等已整理上传,感兴趣的朋友可以看看支持一波!
等已整理上传,感兴趣的朋友可以看看支持一波!