Spring Cloud Gateway-自定义异常处理

参考 https://blog.csdn.net/suyuaidan/article/details/132663141,写法不同于注入方式不一样

ErrorWebFluxAutoConfiguration

@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
@ConditionalOnClass(WebFluxConfigurer.class)
@AutoConfigureBefore(WebFluxAutoConfiguration.class)
@EnableConfigurationProperties({ ServerProperties.class, ResourceProperties.class })
public class ErrorWebFluxAutoConfiguration {private final ServerProperties serverProperties;public ErrorWebFluxAutoConfiguration(ServerProperties serverProperties) {this.serverProperties = serverProperties;}@Bean@ConditionalOnMissingBean(value = ErrorWebExceptionHandler.class, search = SearchStrategy.CURRENT)@Order(-1)public ErrorWebExceptionHandler errorWebExceptionHandler(ErrorAttributes errorAttributes,ResourceProperties resourceProperties, ObjectProvider<ViewResolver> viewResolvers,ServerCodecConfigurer serverCodecConfigurer, ApplicationContext applicationContext) {DefaultErrorWebExceptionHandler exceptionHandler = new DefaultErrorWebExceptionHandler(errorAttributes,resourceProperties, this.serverProperties.getError(), applicationContext);exceptionHandler.setViewResolvers(viewResolvers.orderedStream().collect(Collectors.toList()));exceptionHandler.setMessageWriters(serverCodecConfigurer.getWriters());exceptionHandler.setMessageReaders(serverCodecConfigurer.getReaders());return exceptionHandler;}@Bean@ConditionalOnMissingBean(value = ErrorAttributes.class, search = SearchStrategy.CURRENT)public DefaultErrorAttributes errorAttributes() {return new DefaultErrorAttributes();}}

DefaultErrorWebExceptionHandler

public class DefaultErrorWebExceptionHandler extends AbstractErrorWebExceptionHandler {private static final MediaType TEXT_HTML_UTF8 = new MediaType("text", "html", StandardCharsets.UTF_8);private static final Map<HttpStatus.Series, String> SERIES_VIEWS;static {Map<HttpStatus.Series, String> views = new EnumMap<>(HttpStatus.Series.class);views.put(HttpStatus.Series.CLIENT_ERROR, "4xx");views.put(HttpStatus.Series.SERVER_ERROR, "5xx");SERIES_VIEWS = Collections.unmodifiableMap(views);}private final ErrorProperties errorProperties;/*** Create a new {@code DefaultErrorWebExceptionHandler} instance.* @param errorAttributes the error attributes* @param resourceProperties the resources configuration properties* @param errorProperties the error configuration properties* @param applicationContext the current application context*/public DefaultErrorWebExceptionHandler(ErrorAttributes errorAttributes, ResourceProperties resourceProperties,ErrorProperties errorProperties, ApplicationContext applicationContext) {super(errorAttributes, resourceProperties, applicationContext);this.errorProperties = errorProperties;}@Overrideprotected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {return route(acceptsTextHtml(), this::renderErrorView).andRoute(all(), this::renderErrorResponse);}/*** Render the error information as an HTML view.* @param request the current request* @return a {@code Publisher} of the HTTP response*/protected Mono<ServerResponse> renderErrorView(ServerRequest request) {Map<String, Object> error = getErrorAttributes(request, getErrorAttributeOptions(request, MediaType.TEXT_HTML));int errorStatus = getHttpStatus(error);ServerResponse.BodyBuilder responseBody = ServerResponse.status(errorStatus).contentType(TEXT_HTML_UTF8);return Flux.just(getData(errorStatus).toArray(new String[] {})).flatMap((viewName) -> renderErrorView(viewName, responseBody, error)).switchIfEmpty(this.errorProperties.getWhitelabel().isEnabled()? renderDefaultErrorView(responseBody, error) : Mono.error(getError(request))).next();}private List<String> getData(int errorStatus) {List<String> data = new ArrayList<>();data.add("error/" + errorStatus);HttpStatus.Series series = HttpStatus.Series.resolve(errorStatus);if (series != null) {data.add("error/" + SERIES_VIEWS.get(series));}data.add("error/error");return data;}/*** Render the error information as a JSON payload.* @param request the current request* @return a {@code Publisher} of the HTTP response*/protected Mono<ServerResponse> renderErrorResponse(ServerRequest request) {Map<String, Object> error = getErrorAttributes(request, getErrorAttributeOptions(request, MediaType.ALL));return ServerResponse.status(getHttpStatus(error)).contentType(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(error));}protected ErrorAttributeOptions getErrorAttributeOptions(ServerRequest request, MediaType mediaType) {ErrorAttributeOptions options = ErrorAttributeOptions.defaults();if (this.errorProperties.isIncludeException()) {options = options.including(Include.EXCEPTION);}if (isIncludeStackTrace(request, mediaType)) {options = options.including(Include.STACK_TRACE);}if (isIncludeMessage(request, mediaType)) {options = options.including(Include.MESSAGE);}if (isIncludeBindingErrors(request, mediaType)) {options = options.including(Include.BINDING_ERRORS);}return options;}/*** Determine if the stacktrace attribute should be included.* @param request the source request* @param produces the media type produced (or {@code MediaType.ALL})* @return if the stacktrace attribute should be included*/@SuppressWarnings("deprecation")protected boolean isIncludeStackTrace(ServerRequest request, MediaType produces) {switch (this.errorProperties.getIncludeStacktrace()) {case ALWAYS:return true;case ON_PARAM:case ON_TRACE_PARAM:return isTraceEnabled(request);default:return false;}}/*** Determine if the message attribute should be included.* @param request the source request* @param produces the media type produced (or {@code MediaType.ALL})* @return if the message attribute should be included*/protected boolean isIncludeMessage(ServerRequest request, MediaType produces) {switch (this.errorProperties.getIncludeMessage()) {case ALWAYS:return true;case ON_PARAM:return isMessageEnabled(request);default:return false;}}/*** Determine if the errors attribute should be included.* @param request the source request* @param produces the media type produced (or {@code MediaType.ALL})* @return if the errors attribute should be included*/protected boolean isIncludeBindingErrors(ServerRequest request, MediaType produces) {switch (this.errorProperties.getIncludeBindingErrors()) {case ALWAYS:return true;case ON_PARAM:return isBindingErrorsEnabled(request);default:return false;}}/*** Get the HTTP error status information from the error map.* @param errorAttributes the current error information* @return the error HTTP status*/protected int getHttpStatus(Map<String, Object> errorAttributes) {return (int) errorAttributes.get("status");}/*** Predicate that checks whether the current request explicitly support* {@code "text/html"} media type.* <p>* The "match-all" media type is not considered here.* @return the request predicate*/protected RequestPredicate acceptsTextHtml() {return (serverRequest) -> {try {List<MediaType> acceptedMediaTypes = serverRequest.headers().accept();acceptedMediaTypes.removeIf(MediaType.ALL::equalsTypeAndSubtype);MediaType.sortBySpecificityAndQuality(acceptedMediaTypes);return acceptedMediaTypes.stream().anyMatch(MediaType.TEXT_HTML::isCompatibleWith);}catch (InvalidMediaTypeException ex) {return false;}};}}

观察上面的代码,我们可以知道我们要做两步工作

  1. 全局处理异常怎么操作(实现ErrorWebExceptionHandler,或者直接继承他的子类DefaultErrorWebExceptionHandler)
  2. 如何把异常处理注入到框架中(自定CustomErrorWebFluxAutoConfiguration)

自定义ErrorWebExceptionHandler

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.web.ErrorProperties;
import org.springframework.boot.autoconfigure.web.ResourceProperties;
import org.springframework.boot.autoconfigure.web.reactive.error.DefaultErrorWebExceptionHandler;
import org.springframework.boot.web.reactive.error.ErrorAttributes;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.*;
import reactor.core.publisher.Mono;import java.util.HashMap;
import java.util.Map;/*** 自定义异常处理器*/
@Slf4j
public class CustomErrorWebExceptionHandler extends DefaultErrorWebExceptionHandler {public CustomErrorWebExceptionHandler(ErrorAttributes errorAttributes, ResourceProperties resourceProperties,ErrorProperties errorProperties, ApplicationContext applicationContext) {super(errorAttributes, resourceProperties, errorProperties, applicationContext);}@Overrideprotected Mono<ServerResponse> renderErrorResponse(ServerRequest request) {// 原始的异常信息可以用getError方法取得Throwable throwable = getError(request);// 这里和父类的做法一样,取得DefaultErrorAttributes整理出来的所有异常信息Map<String, Object> errorAttributes = getErrorAttributes(request, getErrorAttributeOptions(request, MediaType.ALL));HttpStatus status = HttpStatus.valueOf((Integer) errorAttributes.get("status"));// todo 写你自己的逻辑也可根据status封装不同的结果集枚举Map<String, Object> responseBodyMap = new HashMap<>();responseBodyMap.put("code", "my error code");responseBodyMap.put("msg", throwable.getMessage());return ServerResponse// http返回码.status(HttpStatus.INTERNAL_SERVER_ERROR)// 类型和以前一样.contentType(MediaType.APPLICATION_JSON)// 响应body的内容.body(BodyInserters.fromValue(responseBodyMap));}@Overrideprotected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse);}}

自定义CustomErrorWebFluxAutoConfiguration

import com.hatzi.gateway.plus.handler.CustomErrorWebExceptionHandler;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.condition.SearchStrategy;
import org.springframework.boot.autoconfigure.web.ResourceProperties;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.reactive.error.DefaultErrorAttributes;
import org.springframework.boot.web.reactive.error.ErrorAttributes;
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.web.reactive.config.WebFluxConfigurer;
import org.springframework.web.reactive.result.view.ViewResolver;import java.util.List;
import java.util.stream.Collectors;/*** @Description* @Author weiwenbin* @Date 2024/6/6 15:01*/
@Configuration
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
@ConditionalOnClass(WebFluxConfigurer.class)
@AutoConfigureBefore(WebFluxAutoConfiguration.class)
@EnableConfigurationProperties({ServerProperties.class, ResourceProperties.class})
public class CustomErrorWebFluxAutoConfiguration {private final ServerProperties serverProperties;private final ApplicationContext applicationContext;private final ResourceProperties resourceProperties;private final List<ViewResolver> viewResolvers;private final ServerCodecConfigurer serverCodecConfigurer;public CustomErrorWebFluxAutoConfiguration(ServerProperties serverProperties,ResourceProperties resourceProperties,ObjectProvider<ViewResolver> viewResolversProvider,ServerCodecConfigurer serverCodecConfigurer,ApplicationContext applicationContext) {this.serverProperties = serverProperties;this.applicationContext = applicationContext;this.resourceProperties = resourceProperties;this.viewResolvers = viewResolversProvider.orderedStream().collect(Collectors.toList());this.serverCodecConfigurer = serverCodecConfigurer;}@Bean@ConditionalOnMissingBean(value = ErrorWebExceptionHandler.class,search = SearchStrategy.CURRENT)@Order(Ordered.HIGHEST_PRECEDENCE)public ErrorWebExceptionHandler errorWebExceptionHandler(ErrorAttributes errorAttributes) {CustomErrorWebExceptionHandler exceptionHandler = new CustomErrorWebExceptionHandler(errorAttributes,resourceProperties,this.serverProperties.getError(),applicationContext);exceptionHandler.setViewResolvers(this.viewResolvers);exceptionHandler.setMessageWriters(this.serverCodecConfigurer.getWriters());exceptionHandler.setMessageReaders(this.serverCodecConfigurer.getReaders());return exceptionHandler;}@Bean@ConditionalOnMissingBean(value = ErrorAttributes.class, search = SearchStrategy.CURRENT)public DefaultErrorAttributes errorAttributes() {return new DefaultErrorAttributes();}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/66072.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

121.【C语言】数据结构之快速排序(未优化的Hoare排序存在的问题)以及时间复杂度的分析

目录 1.未优化的Hoare排序存在的问题 测试代码 "量身定制"的测试代码1 运行结果 "量身定制"的测试代码2 运行结果 "量身定制"的测试代码3 运行结果 分析代码1、2和3栈溢出的原因 排有序数组的分析 分析测试代码1:给一个升序数组,要求排…

DC-2 靶场渗透

目录 环境搭建 开始渗透 扫存活 扫端口 扫服务 看一下80端口 看一下指纹信息 使用wpscan扫描用户名 再使用cewl生成字典 使用wpscan爆破密码 登陆 使用7744端口 查看shell rbash绕过 切换到jerry用户 添加环境变量 现在可以使用su命令了 提权 使用git提权 环…

如何在 Ubuntu 22.04 上优化 Apache 以应对高流量网站教程

简介 在本教程中&#xff0c;我们将学习如何优化 Apache 以应对高流量网站。 当运行高流量网站时&#xff0c;确保你的 Apache Web 服务器得到优化对于有效处理负载至关重要。在本指南中&#xff0c;我们将介绍配置 Apache 以提高性能和可扩展性的基本技巧。 为高流量网站优…

安卓NDK视觉开发——手机拍照文档边缘检测实现方法与库封装

一、项目创建 创建NDK项目有两种方式&#xff0c;一种从新创建整个项目&#xff0c;一个在创建好的项目添加NDK接口。 1.创建NDK项目 创建 一个Native C项目&#xff1a; 选择包名、API版本与算法交互的语言&#xff1a; 选择C版本&#xff1a; 创建完之后&#xff0c;可…

反向传播算法的偏置更新步骤

偏置的更新步骤 假设我们有一个三层神经网络&#xff08;输入层、隐藏层和输出层&#xff09;&#xff0c;并且每层的激活函数为 sigmoid 函数。我们需要更新隐藏层和输出层的偏置。以下是详细的步骤&#xff1a; 1. 计算误差项&#xff08;Error Term&#xff09; 输出层的…

Spring源码分析之事件机制——观察者模式(一)

目录 事件基类定义 事件监听器接口 事件发布者接口及实现 事件广播器实现 小小总结 Spring源码分析之事件机制——观察者模式&#xff08;一&#xff09;-CSDN博客 Spring源码分析之事件机制——观察者模式&#xff08;二&#xff09;-CSDN博客 Spring源码分析之事件机制…

Spring Security(maven项目) 3.0.2.4版本

前言&#xff1a; 通过实践而发现真理&#xff0c;又通过实践而证实真理和发展真理。从感性认识而能动地发展到理性认识&#xff0c;又从理性认识而能动地指导革命实践&#xff0c;改造主观世界和客观世界。实践、认识、再实践、再认识&#xff0c;这种形式&#xff0c;循环往…

stm32 移植RTL8201F(正点原子例程为例)

最近在工作中需要使用RTL8201F&#xff0c;在网上找了很多帖子&#xff0c;没有找到合适的&#xff0c;自己翻资料移植了一个。 模板工程使用的是正点原子的f407探索版的例程&#xff0c;原子使用的是LAN8720,需要把他的驱动修改成为我们自己用的RTL8201F。 1.将PHY_TYPE改成我…

Unity学习笔记(四)如何实现角色攻击、组合攻击

前言 本文为Udemy课程The Ultimate Guide to Creating an RPG Game in Unity学习笔记 实现动画 首先实现角色移动的动画&#xff0c;动画的实现过程在第二篇&#xff0c;这里仅展示效果 attack1 触发攻击动画 实现脚本 接下来我们通过 Animator 编辑动画之间的过渡&#…

redis的集群模式与ELK基础

一、redis的集群模式 1.主从复制 &#xff08;1&#xff09;概述 主从模式&#xff1a;这是redis高可用的基础&#xff0c;哨兵和集群都是建立在此基础之上。 主从模式和数据库的主从模式是一样的&#xff0c;主负责写入&#xff0c;然后把写入的数据同步到从服务器&#xff…

一套比较简单的仓储系统

自己编写的一套比较简单的仓储系统&#xff0c;多仓库&#xff0c;入库、出库、明细、统计等相关功能 基于偌依的单体架构&#xff1a;springbootvueuniapp 后端&#xff1a;https://download.csdn.net/download/qq_30641447/90214834 前端&#xff1a;https://download.csdn…

网络IP协议

IP&#xff08;Internet Protocol&#xff0c;网际协议&#xff09;是TCP/IP协议族中重要的协议&#xff0c;主要负责将数据包发送给目标主机。IP相当于OSI&#xff08;图1&#xff09;的第三层网络层。网络层的主要作用是失陷终端节点之间的通信。这种终端节点之间的通信也叫点…

设计模式 创建型 原型模式(Prototype Pattern)与 常见技术框架应用 解析

原型模式&#xff08;Prototype Pattern&#xff09;是一种创建型设计模式&#xff0c;其核心思想在于通过复制现有的对象&#xff08;原型&#xff09;来创建新的对象&#xff0c;而非通过传统的构造函数或类实例化方式。这种方式在需要快速创建大量相似对象时尤为高效&#x…

MySQL(二)MySQL DDL数据库定义语言

1. MySQL DDL数据库定义语言 1.1. MySQL定义语言 进入MySQL mysql -u root -p(回车后输入密码&#xff0c;即可进入mysq1)1.1.1. 数据库操作 &#xff08;1&#xff09;查看数据库 mysql>show databases;注:MySQL语句分隔符为“&#xff1b;”   mysql库很重要它里面有…

前端页面上传文件:解决 ERR_UPLOAD_FILE_CHANGED

文章目录 引言I 问题 ERR_UPLOAD_FILE_CHANGED问题重现步骤原因II 解决方法将文件转换为base64再转回file检测文件内容是否发生变更III 知识扩展发送一个包含文件和文本的multipart/form-data请求签名优化引言 文件上传应用场景:船舶设备的新增导入(基础信息:出厂编号)船舶…

学术写作中的各种流程图如何利用Kimi进行辅助构建?

目录 1.学术论文中的流程图 2.一些小实践 3.论文中严谨的实践流程 近期小编在思考使用AI工具制作流程图和思维导图&#xff0c;结果发现Kimi现在支持流程图了&#xff0c;Kimi在学术写作中的应用变得更加广泛和深入。随着AIGC技术的不断进步&#xff0c;Kimi的功能将更加强大…

竞品分析对于ASO优化的重要性

产品要想在拥有上千万款App的App Store中脱颖而出的话&#xff0c;要有绝对优势和运营方案&#xff0c;才有可能获得用户的关注。我们要分析和自身产品相似的功能&#xff0c;了解用户获取的途径等&#xff0c;从中获取对竞品有利的因素&#xff0c;明确自身产品的增加和优化方…

什么是485专用屏蔽线

文章目录 一,485屏蔽线基本概念二,485屏蔽线结构及工作原理1、结构2、工作原理三,485屏蔽线的应用一,485屏蔽线基本概念 485屏蔽线,顾名思义,是一种应用于RS-485通信系统的屏蔽线缆。RS_485是一种常用的有线通信协议,具有长距离、高速率、低成本等优点,广泛应用于工业自…

JavaScript BOMDOM

BOM window、document、location、navigator 和 screen等&#xff0c;把它们统称为BOM&#xff08;Browser Object Model&#xff0c;浏览器对象模型&#xff09; window对象 window对象位于BOM的顶层。由浏览器创建&#xff0c;也对应JavaScript本地对象Global &#xff1…

nginx高可用集群搭建

本文介绍nginx高可用集群的搭建。利用keepalived实时检查nginx进程是否存活、keepalived的虚拟ip技术&#xff0c;达到故障转移的目的。终端用户通过访问虚拟ip&#xff0c;感知不到实际发生的故障。架构图如下&#xff1a; 0、环境 Ubuntu&#xff1a;22.04.2 ltsnginx: 1.…