zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    常用FPGA功能块记录
    鸿蒙相关
    微波相关
    Python库大全
    C#环境实现代码的自动生成编译
    STM32相关
    硬件相关
    C# 获取枚举中文注释
    C# 获取自定义特性值
    Asp.Net Core 中 Host 与 WebHost的区别
  • 原文地址:https://www.cnblogs.com/cq-yangzhou/p/13207260.html
Copyright © 2011-2022 走看看