API网关的实现---3 zuul网关Filter处理流程及异常处理

上一篇介绍了java网关Zuul的简单使用,进行请求路由转发和过滤器的基本操作。

这一篇主要看一下它的过滤器Filter的工作流程及异常处理。

首先看到Filter的四个方法,FilterType,filterOrder,shouldFilter,run。

filterType代表过滤类型

PRE: 该类型的filters在Request routing到源web-service之前执行。用来实现Authentication、选择源服务地址等
ROUTING:该类型的filters用于把Request routing到源web-service,源web-service是实现业务逻辑的服务。这里使用HttpClient请求web-service。
POST:该类型的filters在ROUTING返回Response后执行。用来实现对Response结果进行修改,收集统计数据以及把Response传输会客户端。
ERROR:上面三个过程中任何一个出现错误都交由ERROR类型的filters进行处理。

主要关注 pre、post和error。分别代表前置过滤,后置过滤和异常过滤。

如果你的filter是pre的,像上一篇那种,就是指请求先进入pre的filter类,你可以进行一些权限认证,日志记录,或者额外给Request增加一些属性供后续的filter使用。pre会优先按照order从小到大执行,然后再去执行请求转发到业务服务。

再说post,如果type为post,那么就会执行完被路由的业务服务后,再进入post的filter,在post的filter里,一般做一些日志记录,或者额外增加response属性什么的。

最后error,如果在上面的任何一个地方出现了异常,就会进入到type为error的filter中。

filterOrder代表过滤器顺序

这个不多说,试一下就知道了。

shouldFilter代表这个过滤器是否生效

true代表生效,false代表不生效。那么什么情况下使用不生效呢,不生效干嘛还要写这个filter类呢?

其实是有用的,有时我们会动态的决定让不让一个filter生效,譬如我们可能根据Request里是否携带某个参数来判断是否需要生效,或者我们需要从上一个filter里接收某个数据来决定,再或者我们希望能手工控制是否生效(使用如Appolo之类的配置中心,来动态设置该字段)。

Run方法

这个是主要的处理逻辑的地方,我们做权限控制、日志等都是在这里。

下图是filter的执行顺序。

异常过滤器

[java] view plain copy  print?

  1. package com.tianyalei.testzuul;  
  2.   
  3. import com.netflix.zuul.ZuulFilter;  
  4. import com.netflix.zuul.context.RequestContext;  
  5. import org.slf4j.Logger;  
  6. import org.slf4j.LoggerFactory;  
  7. import org.springframework.stereotype.Component;  
  8.   
  9. @Component  
  10. public class ErrorFilter extends ZuulFilter {  
  11.   
  12.     private static Logger log = LoggerFactory.getLogger(ErrorFilter.class);  
  13.   
  14.     @Override  
  15.     public String filterType() {  
  16.         //异常过滤器  
  17.         return "error";  
  18.     }  
  19.   
  20.     @Override  
  21.     public int filterOrder() {  
  22.         //优先级,数字越大,优先级越低  
  23.         return 0;  
  24.     }  
  25.   
  26.     @Override  
  27.     public boolean shouldFilter() {  
  28.         //是否执行该过滤器,true代表需要过滤  
  29.         return true;  
  30.     }  
  31.   
  32.     @Override  
  33.     public Object run() {  
  34.         RequestContext ctx = RequestContext.getCurrentContext();  
  35.   
  36.         log.info("进入异常过滤器");  
  37.   
  38.         System.out.println(ctx.getResponseBody());  
  39.   
  40.         ctx.setResponseBody("出现异常");  
  41.   
  42.         return null;  
  43.   
  44.     }  
  45.   
  46. }  

定义好之后,直接测试看看

可以看到结果就是按照上面说的顺序在执行。

但是最终给用户呈现这样一个界面就不合适的,我们应该去处理这个"/error"映射的问题。

所以我再定义一个Controller

[java] view plain copy  print?

  1. package com.tianyalei.testzuul;  
  2.   
  3. import org.springframework.boot.autoconfigure.web.ErrorController;  
  4. import org.springframework.web.bind.annotation.RequestMapping;  
  5. @RestController  
  6. public class ErrorHandlerController implements ErrorController {  
  7.   
  8.     /** 
  9.      * 出异常后进入该方法,交由下面的方法处理 
  10.      */  
  11.     @Override  
  12.     public String getErrorPath() {  
  13.         return "/error";  
  14.     }  
  15.   
  16.     @RequestMapping("/error")  
  17.     public String error() {  
  18.         return "出现异常";  
  19.     }  
  20. }  

在"/error"方法里返回你想给客户端返回的值即可。

猜你喜欢

转载自blog.csdn.net/happyAliceYu/article/details/79046322