博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SpringCloud Finchley Gateway 统一异常处理
阅读量:6905 次
发布时间:2019-06-27

本文共 6280 字,大约阅读时间需要 20 分钟。

SpringCloud Finchley Gateway 统一异常处理

全文搜索
[@@]搜索重点内容标记
  • 1 . 问题:使用SpringCloud Gateway时,会出现各种系统级异常,默认返回HTML.
  • 2 . Finchley版本的Gateway,使用WebFlux形式作为底层框架,而不是Servlet容器,所以常规的异常处理无法使用
  • 翻阅源码,默认是使用DefaultErrorWebExceptionHandler这个类实现结构如下:

图片描述

  • 可以实现参考DefaultErrorWebExceptionHandlerAbstractErrorWebExceptionHandler自定义实现ErrorWebExceptionHandler,然后,注册为Bean到Spring容器中即可(Bean Name:"errorWebExceptionHandler"
  • 具体实现代码如下:
package pro.chenggang.example.spring.cloud.gateway.support;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;import org.springframework.cloud.gateway.support.NotFoundException;import org.springframework.http.HttpStatus;import org.springframework.http.MediaType;import org.springframework.http.codec.HttpMessageReader;import org.springframework.http.codec.HttpMessageWriter;import org.springframework.http.server.reactive.ServerHttpRequest;import org.springframework.util.Assert;import org.springframework.web.reactive.function.BodyInserters;import org.springframework.web.reactive.function.server.RequestPredicates;import org.springframework.web.reactive.function.server.RouterFunctions;import org.springframework.web.reactive.function.server.ServerRequest;import org.springframework.web.reactive.function.server.ServerResponse;import org.springframework.web.reactive.result.view.ViewResolver;import org.springframework.web.server.ResponseStatusException;import org.springframework.web.server.ServerWebExchange;import reactor.core.publisher.Mono;import java.util.Collections;import java.util.HashMap;import java.util.List;import java.util.Map;/** * @classDesc: 统一异常处理,参考{@link org.springframework.web.server.AbstractErrorWebExceptionHandler}修改 * @author: chenggang * @createTime: 2018/10/30 */public class JsonExceptionHandler implements ErrorWebExceptionHandler {    private static final Logger log = LoggerFactory.getLogger(JsonExceptionHandler.class);    /**     * MessageReader     */    private List
> messageReaders = Collections.emptyList(); /** * MessageWriter */ private List
> messageWriters = Collections.emptyList(); /** * ViewResolvers */ private List
viewResolvers = Collections.emptyList(); /** * 存储处理异常后的信息 */ private ThreadLocal
> exceptionHandlerResult = new ThreadLocal<>(); /** * 参考AbstractErrorWebExceptionHandler * @param messageReaders */ public void setMessageReaders(List
> messageReaders) { Assert.notNull(messageReaders, "'messageReaders' must not be null"); this.messageReaders = messageReaders; } /** * 参考AbstractErrorWebExceptionHandler * @param viewResolvers */ public void setViewResolvers(List
viewResolvers) { this.viewResolvers = viewResolvers; } /** * 参考AbstractErrorWebExceptionHandler * @param messageWriters */ public void setMessageWriters(List
> messageWriters) { Assert.notNull(messageWriters, "'messageWriters' must not be null"); this.messageWriters = messageWriters; } @Override public Mono
handle(ServerWebExchange exchange, Throwable ex) { /** * 按照异常类型进行处理 */ HttpStatus httpStatus; String body; if (ex instanceof NotFoundException) { httpStatus = HttpStatus.NOT_FOUND; body = "Service Not Found"; }else if(ex instanceof ResponseStatusException) { ResponseStatusException responseStatusException = (ResponseStatusException) ex; httpStatus = responseStatusException.getStatus(); body = responseStatusException.getMessage(); }else{ httpStatus = HttpStatus.INTERNAL_SERVER_ERROR; body ="Internal Server Error"; } /** * 封装响应体,此body可修改为自己的jsonBody */ Map
result = new HashMap<>(2,1); result.put("httpStatus",httpStatus); result.put("body",body); /** * 错误记录 */ ServerHttpRequest request = exchange.getRequest(); log.error("[全局异常处理]异常请求路径:{},记录异常信息:{}",request.getPath(),ex.getMessage()); /** * 参考AbstractErrorWebExceptionHandler */ if (exchange.getResponse().isCommitted()) { return Mono.error(ex); } exceptionHandlerResult.set(result); ServerRequest newRequest = ServerRequest.create(exchange, this.messageReaders); return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse).route(newRequest) .switchIfEmpty(Mono.error(ex)) .flatMap((handler) -> handler.handle(newRequest)) .flatMap((response) -> write(exchange, response)); } /** * 参考DefaultErrorWebExceptionHandler * @param request * @return */ protected Mono
renderErrorResponse(ServerRequest request) { Map
result = exceptionHandlerResult.get(); return ServerResponse.status((HttpStatus) result.get("httpStatus")) .contentType(MediaType.APPLICATION_JSON_UTF8) .body(BodyInserters.fromObject(result.get("body"))); } /** * 参考AbstractErrorWebExceptionHandler * @param exchange * @param response * @return */ private Mono
write(ServerWebExchange exchange, ServerResponse response) { exchange.getResponse().getHeaders() .setContentType(response.headers().getContentType()); return response.writeTo(exchange, new ResponseContext()); } /** * 参考AbstractErrorWebExceptionHandler */ private class ResponseContext implements ServerResponse.Context { @Override public List
> messageWriters() { return JsonExceptionHandler.this.messageWriters; } @Override public List
viewResolvers() { return JsonExceptionHandler.this.viewResolvers; } }}
  • 注册Bean
/**     * 自定义异常处理[@@]注册Bean时依赖的Bean,会从容器中直接获取,所以直接注入即可     * @param viewResolversProvider     * @param serverCodecConfigurer     * @return     */    @Primary    @Bean    @Order(Ordered.HIGHEST_PRECEDENCE)    public ErrorWebExceptionHandler errorWebExceptionHandler(ObjectProvider
> viewResolversProvider, ServerCodecConfigurer serverCodecConfigurer) { JsonExceptionHandler jsonExceptionHandler = new JsonExceptionHandler(); jsonExceptionHandler.setViewResolvers(viewResolversProvider.getIfAvailable(Collections::emptyList)); jsonExceptionHandler.setMessageWriters(serverCodecConfigurer.getWriters()); jsonExceptionHandler.setMessageReaders(serverCodecConfigurer.getReaders()); log.debug("Init Json Exception Handler Instead Default ErrorWebExceptionHandler Success"); return jsonExceptionHandler; }
  • [@@]注意事项:

    • 1 .注册Bean时依赖的Bean,都会从Spring容器中获取到
    • 2 .参考此方法思路,可实现统一异常处理,统一封装错误信息。

转载地址:http://zumdl.baihongyu.com/

你可能感兴趣的文章
17款jQuery在线QQ客服代码分享
查看>>
ipsec在企业网中的应用
查看>>
iptables笔记
查看>>
Kali Linux 教程 之 Kali Linux 更新源
查看>>
xshell远程qemu-kvm虚拟机安装
查看>>
×××配置实例_06:分支机构到中心站点动态IPSEC ×××配置
查看>>
利用开源的驰骋工作流程引擎,生产类企业应用案例之三
查看>>
虚拟机Hyper-v目前急需解决的问题
查看>>
REDIS HGETALL按序输出结果
查看>>
heartbeat安装配置
查看>>
如果我是项目经理:那么这样子。。。
查看>>
CentOS7挂载windows共享时提示写保护
查看>>
我的友情链接
查看>>
git clone出现SSL错误
查看>>
解决mysql-socket报错问题
查看>>
CentOS 5/6.X 使用 EPEL YUM源
查看>>
golang redis驱动的比较
查看>>
python 遇到NameError: name '__file__' is not defi...
查看>>
CentOS7.3 64位安装Hyperledger fabric多通道多组织多节点
查看>>
应用偶发性连接不上Oracle数据库的排查案例
查看>>