zuul實現模塊異常統一攔截返回


參考地址:https://www.cnblogs.com/linjiqin/p/10202085.html

zuul網關中根據過濾器的生命周期有以下類型的過濾器:

a、pre: 這種過濾器在請求被路由之前調用。可利用這種過濾器實現身份驗證、在集群中選擇請求的微服務,記錄調試信息等。

b、routing: 這種過濾器將請求路由到微服務。這種過濾器用於構建發送給微服務的請求,並使用apache httpclient或netflix ribbon請求微服務。

c、post: 這種過濾器在路由到微服務以后執行。這種過濾器可用來為響應添加標准的http header、收集統計信息和指標、將響應從微服務發送給客戶端等。

e、error: 在其他階段發送錯誤時執行該過濾器

除了默認的過濾器類型,zuul還允許創建自定義的過濾器類型。例如,可以定制一種static類型的過濾器,直接在zuul中生成響應,而不將請求轉發到后端的微服務。

zuul請求的生命周期如下圖,該圖詳細描述了各種類型的過濾器的執行順序。

1、自定義pre過濾器@Component@Slf4j

public class MyZuulFilter extends ZuulFilter {

//過濾器類型 @Override
public String filterType() { return "pre"; } //zuul-core中的FilterLoader.java的getFilterByType中按類型pre、route、post取Filter后,再按照FilterOrder進行排序。
//先執行pre>routing>post 然后再在同類型的過濾器按照order大小執行,越小的越先被執行
@Override
public int filterOrder() { return 0; }
//過濾器是否執行,false不執行 @Override
public boolean shouldFilter() { return true; }
//自定義執行邏輯 @Override
public Object run() throws ZuulException { RequestContext requestContext = RequestContext.getCurrentContext(); HttpServletRequest request = requestContext.getRequest(); log.info("自定義zuulFilter:" + request.getRequestURI()); return null; } }

2、自定義error過濾器

/** * @classname: MyErrorFilter * @desc: 異常過濾器:當請求發送異常時,調用該過濾器 * @author: YZ * @date: 2020/5/26 14:14 * @version: 1.0 **/ @Component @Slf4j public class MyErrorFilter extends SendErrorFilter { @Override public Object run() { RequestContext ctx = RequestContext.getCurrentContext(); ZuulException e = (ZuulException) findZuulException(ctx.getThrowable()).getThrowable(); log.error("請求失敗:", e); ctx.remove("throwable"); ctx.set("message", e.getMessage()); return null; } }

3、自定義post過濾器

該過濾器只要設置為true,就一定會執行(即使執行了error過濾器),在這里實現結果統一封裝返回。

  1 /**
  2  * @classname: MyErrorFilter
  3  * @desc: 后置過濾器:檢驗請求是否成功
  4  * @author: YZ
  5  * @date: 2020/5/26 14:14
  6  * @version: 1.0
  7  **/
  8 @Component
  9 @Slf4j
 10 public class MyPostFilter extends ZuulFilter {
 11 
 12 
 13     @Autowired
 14     private SendResponseFilter sendResponseFilter;
 15 
 16     @Override
 17     public String filterType() {
 18         return FilterConstants.POST_TYPE;
 19     }
 20 
 21     @Override
 22     public int filterOrder() {
 23         return FilterConstants.SEND_RESPONSE_FILTER_ORDER;
 24     }
 25 
 26     @Override
 27     public boolean shouldFilter() {
 28         return true;
 29     }
 30 
 31     @Override
 32     public Object run() {
 33         RequestContext ctx = RequestContext.getCurrentContext();
 34         HttpServletResponse response = ctx.getResponse();
 35         //只處理非200
 36         if (response.getStatus() != HttpStatus.OK.value()) {
 37             if (response.getStatus() != HttpStatus.UNAUTHORIZED.value()) {
 38                 //返回狀態非401的都改為200
 39                 response.setStatus(HttpStatus.OK.value());
 40             }
 41             response.setHeader("Content-Type", "application/json");
 42             Object message = ctx.get("message");
 43             InputStream is;
 44             InputStreamReader ir;
 45             BufferedReader streamReader;
 46             List<Closeable> closeables = null;
 47             String msg = null;
 48             try (OutputStream out = response.getOutputStream()) {
 49                 if (null != message) {
 50                     msg = message.toString();
 51                 } else {
 52                     closeables = new ArrayList<>(3);
 53                     is = ctx.getResponseDataStream();
 54                     closeables.add(is);
 55                     ir = new InputStreamReader(is);
 56                     closeables.add(ir);
 57                     streamReader = new BufferedReader(ir);
 58                     closeables.add(streamReader);
 59 
 60                     StringBuilder respomseStrBuilder = new StringBuilder();
 61                     String inputStr = "";
 62                     while ((inputStr = streamReader.readLine()) != null) {
 63                         respomseStrBuilder.append(inputStr);
 64                     }
 65                     JSONObject jsonObject = JSONObject.parseObject(respomseStrBuilder.toString());
 66                     JSONArray errors;
 67                     //獲取錯誤信息
 68                     if (null != (errors = jsonObject.getJSONArray("errors"))) {
 69                         String defaultMessage = errors.getJSONObject(0).getString("defaultMessage");
 70                         if (null != defaultMessage) {
 71                             msg = defaultMessage;
 72                         }
 73                     }
 74                     if (null == msg) {
 75                         msg = jsonObject.getString("message");
 76                     }
 77                     if (null == msg) {
 78                         msg = jsonObject.getString("error_description");
 79                     }
 80                     log.error("請求失敗:{}", msg);
 81                 }
 82                 IOUtils.write(JSON.toJSONString(ResponseData.failed("請求失敗:" + msg)).getBytes(StandardCharsets.UTF_8), out);
 83             } catch (IOException e) {
 84                 log.error("請求失敗:", e);
 85             } finally {
 86                 //關閉流
 87                 if (!CollectionUtil.isEmpty(closeables)) {
 88                     closeables.forEach(closeable -> {
 89                         if (null != closeable) {
 90                             try {
 91                                 closeable.close();
 92                             } catch (IOException e) {
 93                             }
 94                         }
 95                     });
 96                 }
 97             }
 98         } else {
 99             //使用默認的post攔截器
100             sendResponseFilter.run();
101         }
102         return null;
103     }
104 
105 }
View Code

4、禁用zuul默認的過濾器

即使自定義了過濾器,如果不經用zuul的默認過濾器,默認過濾器也會被執行,造成結果被篡改。

禁用語法:zuul.filter名稱.disable=true

#禁用指定過濾器 zuul: SendResponseFilter: post: disable: true SendErrorFilter: error: disable: true

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM