本文转载自:https://blog.csdn.net/tianyaleixiaowu/article/details/77893822

上一篇介绍了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的执行顺序。
直接用一个简单的示例来看看结果
第一个前置过滤器
package com.tianyalei.testzuul;  

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component; import javax.servlet.http.HttpServletRequest; @Component
public class AccessFilter extends ZuulFilter { private static Logger log = LoggerFactory.getLogger(AccessFilter.class); @Override
public String filterType() {
//前置过滤器
return "pre";
} @Override
public int filterOrder() {
//优先级,数字越大,优先级越低
return 0;
} @Override
public boolean shouldFilter() {
//是否执行该过滤器,true代表需要过滤
return true;
} @Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest(); log.info("send {} request to {}", request.getMethod(), request.getRequestURL().toString()); //获取传来的参数accessToken
Object accessToken = request.getParameter("accessToken");
if(accessToken == null) {
log.warn("access token is empty");
//过滤该请求,不往下级服务去转发请求,到此结束
ctx.setSendZuulResponse(false);
ctx.setResponseStatusCode(401);
ctx.setResponseBody("{\"result\":\"accessToken为空!\"}");
ctx.getResponse().setContentType("text/html;charset=UTF-8");
return null;
}
//如果有token,则进行路由转发
log.info("access token ok");
//这里return的值没有意义,zuul框架没有使用该返回值
return null;
} }

第二个前置过滤器

package com.tianyalei.testzuul;  

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component; import javax.servlet.http.HttpServletRequest; @Component
public class SecondFilter extends ZuulFilter { private static Logger log = LoggerFactory.getLogger(SecondFilter.class); @Override
public String filterType() {
//前置过滤器
return "pre";
} @Override
public int filterOrder() {
//优先级,数字越大,优先级越低
return 1;
} @Override
public boolean shouldFilter() {
//是否执行该过滤器,true代表需要过滤
return true;
} @Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest(); log.info("second过滤器"); return null; } }

后置过滤器

package com.tianyalei.testzuul;  

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component; @Component
public class PostFilter extends ZuulFilter { private static Logger log = LoggerFactory.getLogger(PostFilter.class); @Override
public String filterType() {
//后置过滤器
return "post";
} @Override
public int filterOrder() {
//优先级,数字越大,优先级越低
return 0;
} @Override
public boolean shouldFilter() {
//是否执行该过滤器,true代表需要过滤
return true;
} @Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
log.info("进入post过滤器");
System.out.println(ctx.getResponseBody()); ctx.setResponseBody("post后置数据"); int i = 1 / 0; return null; } }

异常过滤器

package com.tianyalei.testzuul;  

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component; @Component
public class ErrorFilter extends ZuulFilter { private static Logger log = LoggerFactory.getLogger(ErrorFilter.class); @Override
public String filterType() {
//异常过滤器
return "error";
} @Override
public int filterOrder() {
//优先级,数字越大,优先级越低
return 0;
} @Override
public boolean shouldFilter() {
//是否执行该过滤器,true代表需要过滤
return true;
} @Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext(); log.info("进入异常过滤器"); System.out.println(ctx.getResponseBody()); ctx.setResponseBody("出现异常"); return null; } }

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

可以看到结果就是按照上面说的顺序在执行。
但是最终给用户呈现这样一个界面就不合适的,我们应该去处理这个"/error"映射的问题。
所以我再定义一个Controller
package com.tianyalei.testzuul;  

import org.springframework.boot.autoconfigure.web.ErrorController;
import org.springframework.web.bind.annotation.RequestMapping;
@RestController
public class ErrorHandlerController implements ErrorController { /**
* 出异常后进入该方法,交由下面的方法处理
*/
@Override
public String getErrorPath() {
return "/error";
} @RequestMapping("/error")
public String error() {
return "出现异常";
}
}

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

zuul网关Filter处理流程及异常处理的更多相关文章

  1. Spring Cloud Zuul网关 Filter、熔断、重试、高可用的使用方式。

    时间过的很快,写springcloud(十):服务网关zuul初级篇还在半年前,现在已经是2018年了,我们继续探讨Zuul更高级的使用方式. 上篇文章主要介绍了Zuul网关使用模式,以及自动转发机制 ...

  2. Spring Cloud(十一):Spring Cloud Zuul网关 Filter、熔断、重试、高可用的使用方式

    上篇文章主要介绍了Zuul网关使用模式,以及自动转发机制,但其实Zuul还有更多的应用场景,比如:鉴权.流量转发.请求统计等等,这些功能都可以使用Zuul来实现. Zuul的核心 Filter是Zuu ...

  3. spring cloud深入学习(十二)-----Spring Cloud Zuul网关 Filter、熔断、重试、高可用的使用方式

    Zuul的核心 Filter是Zuul的核心,用来实现对外服务的控制.Filter的生命周期有4个,分别是“PRE”.“ROUTING”.“POST”.“ERROR”,整个生命周期可以用下图来表示. ...

  4. Spring cloud Zuul网关异常处理

    Spring cloud Zuul网关异常处理 一 异常测试: 1> 创建一个pre类型的过滤器,并在该过滤器的run方法实现中抛出一个异常.比如下面的实现,在run方法中调用的doSometh ...

  5. 最全面的改造Zuul网关为Spring Cloud Gateway(包含Zuul核心实现和Spring Cloud Gateway核心实现)

    前言: 最近开发了Zuul网关的实现和Spring Cloud Gateway实现,对比Spring Cloud Gateway发现后者性能好支持场景也丰富.在高并发或者复杂的分布式下,后者限流和自定 ...

  6. SpringCloud之Zuul网关原理及其配置

    Zuul是spring cloud中的微服务网关.网关: 是一个网络整体系统中的前置门户入口.请求首先通过网关,进行路径的路由,定位到具体的服务节点上. Zuul是一个微服务网关,首先是一个微服务.也 ...

  7. 14 微服务电商【黑马乐优商城】:day03-springcloud(Zuul网关)

    本项目的笔记和资料的Download,请点击这一句话自行获取. day01-springboot(理论篇) :day01-springboot(实践篇) day02-springcloud(理论篇一) ...

  8. 非常全面的讲解SpringCloud中Zuul网关原理及其配置,看它就够了!

    Zuul是spring cloud中的微服务网关.网关:是一个网络整体系统中的前置门户入口.请求首先通过网关,进行路径的路由,定位到具体的服务节点上. Zuul是一个微服务网关,首先是一个微服务.也是 ...

  9. SpringCloud Zuul网关的简单理解

    Zuul网关功能 请求路由.服务路由.请求过滤 请求路由 参数配置如下所示,所有能够配置path规则的请求,都会被zuul网关转发到对应的url上. zuul.routes.user-service. ...

随机推荐

  1. url的使用

    1.urls.py 默认是在主目录中,主路由配置文件,会包含最基本的地址映射,并且每个地址访问都必须要先经过该文件. 作用:通过 urls中定义好的地址找到对应的视图处理函数 urlpatterns ...

  2. [LeetCode&Python] Problem 783. Minimum Distance Between BST Nodes

    Given a Binary Search Tree (BST) with the root node root, return the minimum difference between the ...

  3. angular的点击添加

    首先是在js里面我们可以用clone来点击添加一些东西比如列表或者其他的div之类的,但是在angular里面怎么实现点击添加呢? 类似这种: 这样就尴尬了,最少我这样的菜鸟是不知道怎么去写的,网上好 ...

  4. dfs——n的全排列(回溯)

    #include <iostream> #include <cstring> #include <string> #include <map> #inc ...

  5. HashSet remove()

    HashSet继承自Set接口的方法:boolean remove(Object o); case1: public class ShortTest { public static void main ...

  6. visual studio + opencv + contrib

    经过一天的奋战,终把opencv给用起来了.我是用的工具是vs2017+opencv3.3 上午想用mingw+opencv,结果查了很多资料说gcc不支持opencv.我感觉很奇怪,支不支持以后再说 ...

  7. Redis 开发与运维

    Getting Start 高性能 性能优势的体现 C语言实现的内存管理 epoll的I/O多路复用技术+IO连接/关闭/读写通过事件实现异步的非阻塞IO TCP协议 单线程架构,不会因为高并发对服务 ...

  8. 【转】基于Map的简易记忆化缓存

    看到文章后,自己也想写一些关于这个方面的,但是觉得写的估计没有那位博主好,而且又会用到里面的许多东西,所以干脆转载.但是会在文章末尾写上自己的学习的的东西. 原文出处如下: http://www.cn ...

  9. day3 反射与动态代理

    import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Metho ...

  10. drone 1.0 新功能试用以及说明

    drone 1.0 rc 已经发布,新的功能很强大,界面比旧版本更加人性化,和git 的集成也更高了 测试环境准备 试用gogs 做为git 管理工具 docker-compose 文件 versio ...