网关和中心统一异常
背景
后端提供的服务,都是需要统一格式的,比如都需要返回错误码,错误信息,全局流水等等。那么在后端系统中,如果抛了异常不处理的话,这些格式就没法控制,今天讲讲springCloudGateway和springboot服务怎么在抛异常的时候,统一格式。springCloudGateway网关
网关分为限流异常和业务异常限流异常
网关有限流的功能,那么在限流的时候,需要对返回做处理(这里用的sentinel做的限流)
首先我们有个配置类@Configuration public class SentinelException { private final List viewResolvers; private final ServerCodecConfigurer serverCodecConfigurer; public SentinelException(ObjectProvider> viewResolversProvider, ServerCodecConfigurer serverCodecConfigurer) { this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList); this.serverCodecConfigurer = serverCodecConfigurer; } @Bean @Order(Ordered.HIGHEST_PRECEDENCE) public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() { return new SentinelGatewayExceptionHandler(viewResolvers, serverCodecConfigurer); } @Bean @Order(Ordered.HIGHEST_PRECEDENCE) public GlobalFilter sentinelGatewayFilter() { return new SentinelGatewayFilter(); } }
然后新建一个SentinelGatewayExceptionHandler类继承SentinelGatewayBlockExceptionHandler,重写handle方法@Slf4j public class SentinelGatewayExceptionHandler extends SentinelGatewayBlockExceptionHandler { private List viewResolvers; private List> messageWriters; public SentinelGatewayExceptionHandler(List viewResolvers, ServerCodecConfigurer serverCodecConfigurer) { super(viewResolvers, serverCodecConfigurer); this.viewResolvers = viewResolvers; this.messageWriters = serverCodecConfigurer.getWriters(); } @Override public Mono handle(ServerWebExchange serverWebExchange, Throwable throwable) { if (serverWebExchange.getResponse().isCommitted()) { return Mono.error(throwable); } if (!BlockException.isBlockException(throwable)) { return Mono.error(throwable); } return handleBlockedRequest(serverWebExchange, throwable) .flatMap(response -> writeResponse(response, serverWebExchange)); } private Mono handleBlockedRequest(ServerWebExchange exchange, Throwable throwable) { return GatewayCallbackManager.getBlockHandler().handleRequest(exchange, throwable); } private final Supplier contextSupplier = () -> new ServerResponse.Context() { @Override public List> messageWriters() { return SentinelGatewayExceptionHandler.this.messageWriters; } @Override public List viewResolvers() { return SentinelGatewayExceptionHandler.this.viewResolvers; } }; private Mono writeResponse(ServerResponse response, ServerWebExchange exchange) { MDC.clear(); log.error("交易【{}】在【{}】时间被限制,请检查是否有大流量进入", exchange.getRequest().getPath(), DateUtil.format(new Date(), CakeConstants.FORMAT_TIME)); ServerHttpResponse resp = exchange.getResponse(); resp.getHeaders().add("Content-Type", "application/json;charset=UTF-8"); Map map = new HashMap(); String json = JSON.toJSONString(map, CakeConstants.FORMAT_TIME); DataBuffer buffer = resp.bufferFactory().wrap(json.getBytes(StandardCharsets.UTF_8)); return resp.writeWith(Mono.just(buffer)); }
Map map = new HashMap();这里的map就是定义的返回格式,随便自己定义,返回的json数据。业务异常
网关可能发生业务异常,那么我们也要做处理。新建一个GlobalErrorWebExceptionHandler类,实现ErrorWebExceptionHandler接口,重写handle方法,这里我就不贴所有代码了。@Slf4j @Order(-1) @Configuration @RequiredArgsConstructor(onConstructor = @__(@Autowired)) public class GlobalErrorWebExceptionHandler implements ErrorWebExceptionHandler { @SneakyThrows @Override public Mono handle(ServerWebExchange exchange, Throwable ex) { ServerHttpResponse response = exchange.getResponse(); response.getHeaders().setContentType(MediaType.APPLICATION_JSON); return response.writeWith(Mono.fromSupplier(() -> { DataBufferFactory bufferFactory = response.bufferFactory(); try { return bufferFactory.wrap(mapper.writeValueAsBytes("返回数据,自定义")); } catch (Exception e) { log.info("返回失败"); return bufferFactory.wrap(JSON.toJSONBytes("返回数据,自定义")); } })); }springboot服务
springboot分为流控异常,业务异常,还有404这些。流控异常
新建一个SentinelBootException类,实现BlockExceptionHandler,重写handle方法@Slf4j @Component public class SentinelBootException implements BlockExceptionHandler { @Override public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, BlockException e) throws Exception { MDC.clear(); CenterQueryResponse responseData = new CenterQueryResponse(); httpServletResponse.setStatus(200); httpServletResponse.setContentType("application/json;charset=utf-8"); PrintWriter out = httpServletResponse.getWriter(); out.print(JSON.toJSONString(responseData, CakeConstants.FORMAT_TIME)); out.flush(); out.close(); } }
responseData对象就是自定义返回的数据,大家按照自己项目的定义就行。404等处理
新建TransferNotFindController类,实现ErrorController接口,对/error路径进行处理。@RestController public class TransferNotFindController implements ErrorController { private static final Logger log = LoggerFactory.getLogger(TransferNotFindController.class); /** * 默认错误 */ private static final String path_default = "/error"; @RequestMapping(value = path_default, produces = {MediaType.APPLICATION_JSON_VALUE}) public CenterQueryResponse handleError(HttpServletRequest request) { CenterQueryResponse responseData = new CenterQueryResponse(); log.info("交易不存在[{}]", JSON.toJSONString(responseData, CakeConstants.FORMAT_TIME)); return responseData; } }
CenterQueryResponse对象就是返回的数据。大家根据项目自行定义。业务异常
这部分比较麻烦,我是有对controller成做AOP切面处理的,我用了try catch做了一些异常处理,这部分就不写了,大家可以自己去处理,在catch里面对异常处理。还有一部分是全局异常处理,利用的是@ControllerAdvice注解和@ExceptionHandler注解。先定义一个异常类PgException继承RuntimeException。@Data @NoArgsConstructor @AllArgsConstructor public class PgException extends RuntimeException { private String code; private String msg; public PgException(String code, String msg) { this.code = code; this.msg = msg; } @Override public String getMessage() { return this.msg; } @Override public String toString() { return "Exception(code=" + this.getCode() + ", message=" + this.getMsg() + ")"; } }
这里面有个地方注意一下,重写了getMessage,为什么要重写,因为在日志里你不重写的话,那么异常信息打印出来都是null,重写了,你打印的异常信息就是你的错误信息。
然后新建PgExceptionHandler类,这里的代码没完整贴出来。@Slf4j @ControllerAdvice public class PgExceptionHandler { @ExceptionHandler(PgException.class) @ResponseBody public CenterCommandResponse handlePgException(PgException ex) { CenterCommandResponse centerCommandResponse = new CenterCommandResponse(); RequestContext.remove(); return centerCommandResponse; } @ExceptionHandler(Exception.class) @ResponseBody public CenterCommandResponse handleException(Exception ex) { CenterCommandResponse centerCommandResponse = new CenterCommandResponse(); … return centerCommandResponse; } }
CenterCommandResponse就是要返回的数据,大家可以根据项目自行定义。
网关和服务应用的异常处理就到这了,基本包含了当前所有的异常场景了,后续还有别的再加吧。再贴个我的异常返回图。
异常返回信息
牛!火箭军战士用挖掘机吊水瓶火箭军战士操作挖掘机有多精准?近日,在火箭军某部机械训练场上,操作手操纵挖掘机,吊起了矿泉水瓶!(马阿强董岸松王思雨)视频加载中更多精彩资讯请在应用市场下载央广网客户端。欢迎提供新
小孩犯错,不认错要打手板那大人硬是不认错呢?大人教育小孩,总说有错就要认,认了好好改小孩如果不服气,还会被打手板。可真到了成年人的世界,你发现,不认错的大有人在你看美国,就喜欢驴象互相甩锅,不管多大的问题,都是在野的一方使绊
怀孕便秘篇女性怀孕以后,是非常容易便秘的。1怀孕以后,体内激素的变化,孕酮使得胃肠蠕动变慢,导致食物通过胃肠道的时间明显的延长,引起便秘。2怀孕以后,活动量明显减少,大部分时间是坐着或者躺着
爸爸在你身后女儿今年18了,上了大学,学会了独自买机票,独自登机,独自回家。回忆起十一年前她刚上小学的时候,第一次独自走路上学的场景。感受颇多,那年她七岁。女儿胆小,天生的,看见小虫子会大叫,
6千万国人的炸弹软性毒品槟榔,有人在辩解,有人浑然不对于每一位湖南人来说,在闲暇时分,嘴中嚼一些槟榔小零食,也是再普通不过的事情了。然而,在最近几年的时间当中,关于槟榔的负面报导越来越多,这引起了爱好健康人士的普遍关注。因为槟榔内含
争议!世乒赛预选赛被质疑,多位名将已退赛,球迷毫无锻炼价值2023年德班世乒赛的亚洲区预选赛已经开打,然而争议之声也随之到来,许多球迷都对这个赛事提出质疑,认为其毫无锻炼的价值,国乒基本就是去砍瓜切菜的。这也难怪,世预赛还没开打,林昀儒庄
输不起!杜锋炮轰裁判主队罚篮全是排名前列这个球其实不用打了1月8日消息,7日CBA常规赛中,广东宏远以103114不敌浙江,被终结了13连胜。赛后,宏远主教练杜锋在新闻发布会上炮轰裁判照顾主场作战的浙江队。本场比赛,广东队和浙江队的罚篮数
浙江终结广东十三连胜原因揭晓!球迷第二次发声,这回说了真话浙江男篮终结广东男篮十三连胜原因揭晓!球迷第二次发声,这回说了真话。网友热议一针见血地指出广东男篮三少进攻迷失了,劲都用在防守上了,广东内线还是不行了,易建联的体能面对浙江真的顶不
詹姆斯37分4人20湖人背靠背2分险胜国王赛季五连胜北京时间1月8日,湖人背靠背客场挑战国王队。经过4节苦战,湖人队最终以136134,2分险胜国王,取得五连胜,2023年湖人取得全胜战绩,可以说是2023年的王!本场比赛,湖人队延
林心如,走到今天,真不能怪别人!引言2020年3月周杰给武汉抗疫医疗者捐了2万斤大米,事后为何被键盘侠狂轰,做好事的周杰为何成了过街老鼠。其中被传得比较热门的质疑是1。周杰捐米是为了作秀,博眼球。2。既然说捐大米
与孙悦分居2年,36岁陈露定居美国,约会小鲜肉,疑似公布新恋情与孙悦分居2年,陈露定居美国约会小鲜肉,1米8大长腿,身材傲人孙悦,曾经的中国男篮主力后卫,与白富美陈露的牵手,也曾经被誉为金童玉女组合。不过近段时间有消息透露,两个人的婚姻疑似走
暖她一整天是什么梗暖她一整天,这是一些营销号最爱用的词,比如女生说早呀,傻子才回早,高情商回复暖她一整天。看起来似乎没有毛病,虽然标题夸张了点,但也能接受,毕竟高情商回复,会说话一点,确实会让对方感
娱乐播报景甜陈都灵那英宁静黄轩何超莲王源张智霖1。陈都灵最近又在谈一个民国剧。2。景甜3年内不能代言广告。景甜因为代言了涉嫌违法的广告被罚788。12万元,并且在未来三年内不得代言任何广告。作为公众人物,一言一行都备受关注,希
金莎素颜出镜报平安!声音嘶哑颈部贴膏药,穿一身睡衣头发油腻还有多少人记得十八岁的天空中的蓝菲琳和唱着被风吹过的夏天的那个姑娘,别看现在的她已经39岁了,可是她依旧是万千人心目中的女神,哪怕是过了这么多年,依然会记得在青春当中,在我们的记忆
陈佩斯四个孙子齐曝光,晚上睡觉抢爸爸,四小娃长相宛如复制粘贴饿了吗?戳右边关注我们,每天给您送上最新出炉的娱乐硬核大餐!5月28日,陈佩斯的儿子陈大愚在社交平台上晒娃,并澄清自己与老婆一共生了三胎,头两个女儿是相隔几年后生的,只有两个儿子是
天热喝啤酒,不管有钱没钱,这4种啤酒要少喝,没酒味还上头如果你也喜欢美食,点击关注,每天不断更新精彩内容!导语天热喝啤酒,不管有钱没钱,这4种啤酒要少喝,没酒味还上头!一说到啤酒,相信大家也知道,每年到了当下这个季节的时候,天气越来越燥
汽车年检改革,取消十五年车辆一年两审等呼声大文宝拉车主对汽车年检积怨已久,汽车年检改革应顺应时代发展,听取百姓心声。汽车在年检时会进行十分详细的检查,细致到汽车零件的检查。年检的本质就是为了保障道路安全,防患于未然。当年检没
时隔6年,菲律宾重提南海仲裁,但称不会与华开战,中方回应日前,菲律宾国会正式宣布费迪南德罗慕尔德兹马科斯当选新一任总统,并将在6月30日宣誓就职。值得注意的是,在当选的次日,马科斯就对南海事务做出了重要表态。据观察者网5月27日报道,搁
7种泼辣花,天热快扦插,生根快窜花多,插多少活多少五月之后,天气越来越炎热了,有些花卉植物在夏天里会大放光彩,长势飞速,开花繁多。这些喜欢炎热季节的花卉植物,在夏天里越热长得越好,也越容易扦插。修剪下来的枝条儿千万不要丢掉,随便扦
谁不害怕不确定性2022年4月经济数据全面下滑,技术上确定经济衰退。新冠疫情在示虐,俄乌战争在持续,石油粮食在涨价,美国加息在进行,地产企业在暴雷,上海北京在封城,美国制裁在加大现在的最大困难是不
世界顶尖防空系统要退休,以色列激光炮有多厉害?牢不可破?世界顶级防空系统即将退役。以色列的激光枪到底有多厉害?牢不可破?几团火焰直冲云霄,在空中爆炸。这不是双踢,是以色列的铁穹防空系统,拦截从某处发射的火箭弹。看到这一幕,相信很多人都会
上海公布中小学生返校复学的相关安排光明日报全媒体记者孟歆迪在5月26日的上海市疫情防控工作新闻发布会上,上海市教委副主任杨振峰表示,综合考虑疫情防控形势学校复学前的准备工作进展以及考生线下学习的必要时间等因素,经慎