Spring Cloud Zuul过滤器先容及利用(通报数据、拦截请求和异常处理惩罚)

发布于2021-02-15 16:34    文章来源:网络整理

在教程《Zuul网关的先容及利用》中一开始就先容过,Zuul 可以实现许多高级的成果,好比限流、认证等。想要实现这些成果,必需要基于 Zuul 给我们提供的焦点组件“过滤器”。下面我们一起来相识一下 Zuul 的过滤器
过滤器范例 Zuul 中的过滤器跟我们之前利用的 javax.servlet.Filter 纷歧样,javax.servlet.Filter 只有一种范例,可以通过设置 urlPatterns 来拦截对应的请求。

而 Zuul 中的过滤器总共有 4 种范例,且每种范例都有对应的利用场景。 1)pre 可以在请求被路由之前挪用。合用于身份认证的场景,认证通事后再继承执行下面的流程。
2)route 在路由请求时被挪用。合用于灰度宣布场景,在将要路由的时候可以做一些自界说的逻辑。
3)post 在 route 和 error 过滤器之后被挪用。这种过滤器将请求路由达到详细的处事之后执行。合用于需要添加响应头,记录响应日志等应用场景。
4)error 处理惩罚请求时产生错误时被挪用。在执行进程中发送错误时会进入 error 过滤器,可以用来统一记录错误信息。 请求生命周期 可以通过图 1 看出整个过滤器的执行生命周期,此图来自 Zuul GitHub wiki 主页。

过滤器生命周期


图 1  过滤器生命周期


通过上面的图可以清楚地知道整个执行的顺序,请求发过来首先到 pre 过滤器,再到 routing 过滤器,最后到 post 过滤器,任何一个过滤器有异常城市进入 error 过滤器。

通过 com.netflix.zuul.http.ZuulServlet 也可以看出完整执行顺序,ZuulServlet 雷同 Spring-Mvc 的 DispatcherServlet,所有的 Request 都要颠末 ZuulServlet 的处理惩罚。

ZuulServlet 源码如下所示: @Override public void service(javax.servlet.ServletRequest servletRequest, javax.servlet.ServletResponse servletResponse) throws ServletException, IOException { try { init((HttpServletRequest) servletRequest, (HttpServletResponse) servletResponse); RequestContext context = RequestContext.getCurrentContext(); context.setZuulEngineRan(); try { preRoute(); } catch (ZuulException e) { error(e); postRoute(); return; } try { route(); } catch (ZuulException e) { error(e); postRoute(); return; } try { postRoute(); } catch (ZuulException e) { error(e); return; } } catch (Throwable e) { error(new ZuulException(e, 500, "UNHANDLED_EXCEPTION_" + e.getClass().getName())); } finally { RequestContext.getCurrentContext().unset(); } } 利用过滤器 我们建设一个 pre 过滤器,来实现 IP 黑名单的过滤操纵,代码如下所示。 public class IpFilter extends ZuulFilter { // IP黑名单列表 private List<String> blackIpList = Arrays.asList("127.0.0.1"); public IpFilter() { super(); } @Override public boolean shouldFilter() { return true } @Override public String filterType() { return "pre"; } @Override public int filterOrder() { return 1; } @Override public Object run() { RequestContext ctx = RequestContext.getCurrentContext(); String ip = IpUtils.getIpAddr(ctx.getRequest()); // 在黑名单中禁用 if (StringUtils.isNotBlank(ip) && blackIpList.contains(ip)) { ctx.setSendZuulResponse(false); ResponseData data = ResponseData.fail("犯科请求 ", ResponseCode.NO_AUTH_CODE.getCode()); ctx.setResponseBody(JsonUtils.toJson(data)); ctx.getResponse().setContentType("application/json; charset=utf-8"); return null; } return null; } } 由代码可知,自界说过滤器需要担任 ZuulFilter,而且需要实现下面几个要领: 1)shouldFilter 是否执行该过滤器,true 为执行,false 为不执行,这个也可以操作设置中心来实现,到达动态的开启和封锁过滤器。
2)filterType 过滤器范例,可选值有 pre、route、post、error。
3)filterOrder 过滤器的执行顺序,数值越小,优先级越高。
4)run 执行本身的业务逻辑,本段代码中是通过判定请求的 IP 是否在黑名单中,抉择是否举办拦截。blackIpList 字段是 IP 的黑名单,判定条件创立之后,通过配置 ctx.setSendZuulResponse(false),汇报 Zuul 不需要将当前请求转发到后端的处事了。通过 setResponseBody 返回数据给客户端。

过滤器界说完成之后我们需要设置过滤器才气生效,IP 过滤器设置代码如下所示。 @Configuration public class FilterConfig { @Bean public IpFilter ipFilter() { return new IpFilter(); } } 过滤器禁用 有的场景下,我们需要禁用过滤器,此时可以采纳下面的两种方法来实现:

操作 shouldFilter 要领中的 return false 让过滤器不再执行

通过设置方法来禁用过滤器,名目为“zuul. 过滤器的类名.过滤器范例 .disable=true”。假如我们需要禁用“利用过滤器”部门中的 IpFilter,可以用下面的设置:

相关资讯