一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|JavaScript|易語(yǔ)言|

服務(wù)器之家 - 編程語(yǔ)言 - Java教程 - Spring Cloud Gateway全局異常處理的方法詳解

Spring Cloud Gateway全局異常處理的方法詳解

2021-06-03 11:53猿天地 Java教程

這篇文章主要給大家介紹了關(guān)于Spring Cloud Gateway全局異常處理的相關(guān)資料,需要的朋友可以參考下

前言

spring cloud gateway是spring官方基于spring 5.0,spring boot 2.0和project reactor等技術(shù)開發(fā)的網(wǎng)關(guān),spring cloud gateway旨在為微服務(wù)架構(gòu)提供一種簡(jiǎn)單而有效的統(tǒng)一的api路由管理方式。spring cloud gateway作為spring cloud生態(tài)系中的網(wǎng)關(guān),目標(biāo)是替代netflix zuul,其不僅提供統(tǒng)一的路由方式,并且基于filter鏈的方式提供了網(wǎng)關(guān)基本的功能,例如:安全,監(jiān)控/埋點(diǎn),和限流等。

Spring Cloud Gateway全局異常處理的方法詳解

spring cloud gateway 的特征:

  • 基于 spring framework 5,project reactor 和 spring boot 2.0動(dòng)態(tài)路由
  • predicates 和 filters 作用于特定路由
  • 集成 hystrix 斷路器
  • 集成 spring cloud discoveryclient
  • 易于編寫的 predicates 和 filters
  • 限流
  • 路徑重寫

spring cloud gateway中的全局異常處理不能直接用@controlleradvice來處理,通過跟蹤異常信息的拋出,找到對(duì)應(yīng)的源碼,自定義一些處理邏輯來符合業(yè)務(wù)的需求。

網(wǎng)關(guān)都是給接口做代理轉(zhuǎn)發(fā)的,后端對(duì)應(yīng)的都是rest api,返回?cái)?shù)據(jù)格式都是json。如果不做處理,當(dāng)發(fā)生異常時(shí),gateway默認(rèn)給出的錯(cuò)誤信息是頁(yè)面,不方便前端進(jìn)行異常處理。

需要對(duì)異常信息進(jìn)行處理,返回json格式的數(shù)據(jù)給客戶端。下面先看實(shí)現(xiàn)的代碼,后面再跟大家講下需要注意的地方。
自定義異常處理邏輯:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
package com.cxytiandi.gateway.exception;
 
import java.util.hashmap;
import java.util.map;
 
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.web.reactive.function.server.requestpredicates;
import org.springframework.web.reactive.function.server.routerfunction;
import org.springframework.web.reactive.function.server.routerfunctions;
import org.springframework.web.reactive.function.server.serverrequest;
import org.springframework.web.reactive.function.server.serverresponse;
 
/**
 * 自定義異常處理
 *
 * <p>異常時(shí)用json代替html異常信息<p>
 *
 * @author yinjihuan
 *
 */
public class jsonexceptionhandler extends defaulterrorwebexceptionhandler {
 
 public jsonexceptionhandler(errorattributes errorattributes, resourceproperties resourceproperties,
 errorproperties errorproperties, applicationcontext applicationcontext) {
 super(errorattributes, resourceproperties, errorproperties, applicationcontext);
 }
 
 /**
 * 獲取異常屬性
 */
 @override
 protected map<string, object> geterrorattributes(serverrequest request, boolean includestacktrace) {
 int code = 500;
 throwable error = super.geterror(request);
 if (error instanceof org.springframework.cloud.gateway.support.notfoundexception) {
 code = 404;
 }
 return response(code, this.buildmessage(request, error));
 }
 
 /**
 * 指定響應(yīng)處理方法為json處理的方法
 * @param errorattributes
 */
 @override
 protected routerfunction<serverresponse> getroutingfunction(errorattributes errorattributes) {
 return routerfunctions.route(requestpredicates.all(), this::rendererrorresponse);
 }
 
 /**
 * 根據(jù)code獲取對(duì)應(yīng)的httpstatus
 * @param errorattributes
 */
 @override
 protected httpstatus gethttpstatus(map<string, object> errorattributes) {
 int statuscode = (int) errorattributes.get("code");
 return httpstatus.valueof(statuscode);
 }
 
 /**
 * 構(gòu)建異常信息
 * @param request
 * @param ex
 * @return
 */
 private string buildmessage(serverrequest request, throwable ex) {
 stringbuilder message = new stringbuilder("failed to handle request [");
 message.append(request.methodname());
 message.append(" ");
 message.append(request.uri());
 message.append("]");
 if (ex != null) {
 message.append(": ");
 message.append(ex.getmessage());
 }
 return message.tostring();
 }
 
 /**
 * 構(gòu)建返回的json數(shù)據(jù)格式
 * @param status 狀態(tài)碼
 * @param errormessage 異常信息
 * @return
 */
 public static map<string, object> response(int status, string errormessage) {
 map<string, object> map = new hashmap<>();
 map.put("code", status);
 map.put("message", errormessage);
 map.put("data", null);
 return map;
 }
 
}

覆蓋默認(rèn)的配置:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
package com.cxytiandi.gateway.exception;
 
import java.util.collections;
import java.util.list;
 
import org.springframework.beans.factory.objectprovider;
import org.springframework.boot.autoconfigure.web.resourceproperties;
import org.springframework.boot.autoconfigure.web.serverproperties;
import org.springframework.boot.context.properties.enableconfigurationproperties;
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.result.view.viewresolver;
 
/**
 * 覆蓋默認(rèn)的異常處理
 *
 * @author yinjihuan
 *
 */
@configuration
@enableconfigurationproperties({serverproperties.class, resourceproperties.class})
public class errorhandlerconfiguration {
 
 private final serverproperties serverproperties;
 
 private final applicationcontext applicationcontext;
 
 private final resourceproperties resourceproperties;
 
 private final list<viewresolver> viewresolvers;
 
 private final servercodecconfigurer servercodecconfigurer;
 
 public errorhandlerconfiguration(serverproperties serverproperties,
          resourceproperties resourceproperties,
          objectprovider<list<viewresolver>> viewresolversprovider,
          servercodecconfigurer servercodecconfigurer,
          applicationcontext applicationcontext) {
  this.serverproperties = serverproperties;
  this.applicationcontext = applicationcontext;
  this.resourceproperties = resourceproperties;
  this.viewresolvers = viewresolversprovider.getifavailable(collections::emptylist);
  this.servercodecconfigurer = servercodecconfigurer;
 }
 
 @bean
 @order(ordered.highest_precedence)
 public errorwebexceptionhandler errorwebexceptionhandler(errorattributes errorattributes) {
  jsonexceptionhandler exceptionhandler = new jsonexceptionhandler(
    errorattributes,
    this.resourceproperties,
    this.serverproperties.geterror(),
    this.applicationcontext);
  exceptionhandler.setviewresolvers(this.viewresolvers);
  exceptionhandler.setmessagewriters(this.servercodecconfigurer.getwriters());
  exceptionhandler.setmessagereaders(this.servercodecconfigurer.getreaders());
  return exceptionhandler;
 }
}

注意點(diǎn)

異常時(shí)如何返回json而不是html?

在org.springframework.boot.autoconfigure.web.reactive.error.defaulterrorwebexceptionhandler中的getroutingfunction()方法就是控制返回格式的,原代碼如下:

?
1
2
3
4
5
6
@override
protected routerfunction<serverresponse> getroutingfunction(
 errorattributes errorattributes) {
  return routerfunctions.route(acceptstexthtml(), this::rendererrorview)
 .androute(requestpredicates.all(), this::rendererrorresponse);
}

這邊優(yōu)先是用html來顯示的,想用json的改下就可以了,如下:

?
1
2
3
protected routerfunction<serverresponse> getroutingfunction(errorattributes errorattributes) {
 return routerfunctions.route(requestpredicates.all(), this::rendererrorresponse);
}

gethttpstatus需要重寫

原始的方法是通過status來獲取對(duì)應(yīng)的httpstatus的,代碼如下:

?
1
2
3
4
protected httpstatus gethttpstatus(map<string, object> errorattributes) {
 int statuscode = (int) errorattributes.get("status");
 return httpstatus.valueof(statuscode);
}

如果我們定義的格式中沒有status字段的話,這么就會(huì)報(bào)錯(cuò),找不到對(duì)應(yīng)的響應(yīng)碼,要么返回?cái)?shù)據(jù)格式中增加status子段,要么重寫,我這邊返回的是code,所以要重寫,代碼如下:

?
1
2
3
4
5
@override
protected httpstatus gethttpstatus(map<string, object> errorattributes) {
 int statuscode = (int) errorattributes.get("code");
 return httpstatus.valueof(statuscode);
}

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對(duì)服務(wù)器之家的支持。

原文鏈接:https://juejin.im/post/5bbad1405188255c4a7137e1

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 轻轻色在线视频中文字幕 | 2019亚洲男人天堂 | 免费的伦理片 | 四虎精品成人a在线观看 | 日本午夜大片免费观看视频 | 小早川怜子亚洲综合中文字幕 | 国产日韩欧美在线观看不卡 | 国产三级精品久久三级国专区 | 女人叉开腿让男人桶 | 暖暖 免费 高清 日本 中文 | 亚洲AV无码乱码在线观看浪潮 | 动漫美女人物被黄漫小说 | 草莓茄子丝瓜番茄小蝌蚪 | 国产99区 | 久热这里在线精品 | 无颜之月5集全免费看无删除 | ts视频在线观看 | 隔壁老王国产精品福利 | 日韩欧美亚洲每日更新网 | 美女视频ww8888网网 | 91对白在线 | 大香焦在线观看 | 天堂avav | 成人私人影院在线版 | 亚洲大爷操 | 欧美精品国产一区二区 | 激情影院免费观看 | 91制片厂制作果冻传媒2021 | 午夜影院一区二区三区 | 欧美疯狂做爰xx | 免费高清观看 | 日韩网新片免费 | 91精品91| 久久综合狠狠综合狠狠 | 欧美午夜视频一区二区 | xnxx18美女 | 操人网| 北条麻妃一区 | 四虎网址大全 | 碰91精品国产91久久婷婷 | 四虎精品永久免费 |