Spring Cloud(Dalston.SR5)--Zuul 网关-过滤器
Spring Cloud 为 HTTP 请求的各个阶段提供了多个过滤器,这些过滤器的执行顺序由各自提供的一个 int 值决定,提供的值越小则优先级越高,默认的过滤器及优先级如下:
自定义过滤器
在默认过滤器的基础上,我们可以实现自己的自定义过滤器,自定义过滤器需要继承 com.netflix.zuul.ZuulFilter 类,并实现相关方法,说明如下:
- filterType:该函数需要返回一个字符串来代表过滤器的类型,而这个类型就是在HTTP请求过程中定义的各个阶段。在Zuul中默认定义了四种不同生命周期的过滤器类型,具体如下:
- pre:可以在请求被路由之前调用
- routing:在路由请求时候被调用
- post:在routing和error过滤器之后被调用
- error:处理请求时发生错误时被调用
- filterOrder:通过int值来定义过滤器的执行顺序,数值越小优先级越高
- shouldFilter:返回一个boolean类型来判断该过滤器是否要执行。我们可以通过此方法来指定过滤器的有效范围。
- run:过滤器的具体逻辑。在该函数中,我们可以实现自定义的过滤逻辑,来确定是否要拦截当前的请求,不对其进行后续的路由,或是在请求路由返回结果之后,对处理结果做一些加工等
Zuul 默认定义了四个不同的过滤器类型,它们覆盖了一个外部HTTP请求到达API网关,直到返回请求结果的全部生命周期。下图源自Zuul的官方WIKI中关于请求生命周期的图解,它描述了一个HTTP请求到达API网关之后,如何在各个不同类型的过滤器之间流转的详细过程如下:
我们可以看到,当外部 HTTP 请求到达 API 网关服务的时候,首先它会进入第一个阶段 pre,在这里它会被pre 类型的过滤器进行处理,该类型的过滤器主要目的是在进行请求路由之前做一些前置加工,比如请求的校验等。
在完成了 pre 类型的过滤器处理之后,请求进入第二个阶段 routing,也就是之前说的路由请求转发阶段,请求将会被 routing 类型过滤器处理,这里的具体处理内容就是将外部请求转发到具体服务实例上去的过程,当服务实例将请求结果都返回之后,routing 阶段完成,请求进入第三个阶段 post,此时请求将会被 post 类型的过滤器进行处理,这些过滤器在处理的时候不仅可以获取到请求信息,还能获取到服务实例的返回信息,所以在 post 类型的过滤器中,我们可以对处理结果进行一些加工或转换等内容。
另外,还有一个特殊的阶段error,该阶段只有在上述三个阶段中发生异常的时候才会触发,但是它的最后流向还是post类型的过滤器,因为它需要通过post过滤器将最终结果返回给请求客户端。
过滤器示例
- 验证过滤器
该过滤器会在 pre 阶段执行,并且其优先级为 1 在包装请求体后执行,其 shouldFilter 返回 true 表示任何情况都执行该过滤器,在 run 方法通过获取 HttpServletRequest 示例获取请求参数并进行验证,在验证失败的时候通过设置 HttpServletResponse 示例和 setSendZuulResponse(false) 来直接返回响应信息,而不进行后续过滤器处理。
package org.lixue.zuul;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class TokenPreZullFilter extends ZuulFilter{
@Override
public String filterType(){
return FilterConstants.PRE_TYPE;
}
@Override
public int filterOrder(){
return 1;
}
@Override
public boolean shouldFilter(){
return true;
}
@Override
public Object run(){
RequestContext ctx=RequestContext.getCurrentContext();
HttpServletRequest request=ctx.getRequest();
System.out.println(String.format("%s request to %s",request.getMethod(),request.getRequestURL().toString()));
String token=request.getParameter("token");
System.out.println("token:"+token);
if(token==null||!token.equals("success_token")){
//认证失败
System.out.println("token验证失败");
HttpServletResponse response=ctx.getResponse();
response.setCharacterEncoding("utf-8");//设置字符集
response.setContentType("text/html;charset=utf-8");//设置相应格式
response.setStatus(401);
ctx.setSendZuulResponse(false);//不进行路由
try{
response.getWriter().write("token验证失败");//响应体
}catch(IOExceptione){
System.out.println("responseio异常");
e.printStackTrace();
}
ctx.setResponse(response);
return null;
}
System.out.println("token验证成功");
return null;
}
}
- 过滤器配置类
为了让 Spring 容器知道过滤器的存在,需要对该类进行配置,创建过滤器配置类,使用注解 @Configuration 标注类,并使用 @Bean 注解标注返回过滤器的方法。
package org.lixue.zuul;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ZuulFilterConfiguration{
@Bean
public TokenPreZullFilter tokenPreZullFilter(){
return newTokenPreZullFilter();
}
}
- 测试验证
项目依赖一个 eureka-sserver、service-provider 服务,首先启动 eureka-server 和 service-provider 服务,然后启动 spring-cloud-zuul-microservices 服务,访问 http://localhost:9200/hello/speaks?names=123&token=success_token 地址,可以看到能正常返回,如下:
{"123":"Hello World 123 Port=8080"}
修改访问地址,移除 token 参数或者修改参数值 http://localhost:9200/hello/speaks?names=123&token=success_token999 这时会返回 token 验证失败的错误,并且没有执行后续的路由处理。
Spring Cloud(Dalston.SR5)--Zuul 网关-过滤器的更多相关文章
- Spring Cloud(Dalston.SR5)--Zuul 网关-微服务集群
通过 url 映射的方式来实现 zuul 的转发有局限性,比如每增加一个服务就需要配置一条内容,另外后端的服务如果是动态来提供,就不能采用这种方案来配置了.实际上在实现微服务架构时,服务名与服务实例地 ...
- Spring Cloud(Dalston.SR5)--Zuul 网关-路由配置
Spring Cloud 在 Zuul 的 routing 阶段实现了几个过滤器,这些过滤器决定如何进行路由工作. 简单路由(SimpleHostRoutingFilter) 该过滤器运行后,会将 H ...
- Spring Cloud(Dalston.SR5)--Zuul 网关
我们使用 Spring Cloud Netflix 中的 Eureka 实现了服务注册中心以及服务注册与发现:而服务间通过 Ribbon 或 Feign 实现服务的消费以及均衡负载:使用Hystrix ...
- Spring Cloud(Dalston.SR5)--Zuul 网关-Hystrix 回退
当我们对网关进行配置让其调用集群的服务时,将会执行 Ribbon 路由过滤器,该过滤器在进行转发时会封装为一个 Hystrix 命令予以执行,Hystrix 命令具有容错的功能,如果"源服务 ...
- Spring Cloud(Dalston.SR5)--Config 集群配置中心
Spring Cloud Config 是一个全新的项目,用来为分布式系统中的基础设施和微服务应用提供集中化的外部配置支持,他分为服务端和客户端两个部分.服务端也称为分布式配置中心,是一个独立的微服务 ...
- Spring Cloud Dalston.SR5 BUG一记
使用Dalston.SR5版本的Zuul时, 发现Ribbon重试不能切换服务实例, 换成Edgware.SR3,同样的配置可以切换实例进行重试 还有个不升级所有Spring Cloud组件的方法,仅 ...
- Spring Cloud(Dalston.SR5)--Config 集群配置中心-刷新配置
远程 SVN 服务器上面的配置修改后,需要通知客户端来改变配置,需要增加 spring-boot-starter-actuator 依赖并将 management.security.enabled 设 ...
- Spring Cloud(Dalston.SR5)--Hystrix 监控
在服务调用者加入 Actuator ,可以对服务调用者的健康情况进行实时监控,例如,断路器是否打开.当前负载情况等. 服务调用者 需要增加 actuator依赖, 修改 POM.xml 中增加以下依赖 ...
- Spring Cloud(Dalston.SR5)--Feign 与 Hystrix 断路器整合
创建项目 要使 Feign 与 Hystrix 进行整合,我们需要增加 Feign 和 Hystrix 的依赖,修改 POM.xml 中增加以下依赖项如下: <?xmlversion=" ...
随机推荐
- Django 修改视图文件(views.py)并加载Django模块 + 利用render_to_response()简化加载模块 +locals()
修改视图代码,让它使用 Django 模板加载功能而不是对模板路径硬编码.返回 current_datetime 视图,进行如下修改: from django.template.loader impo ...
- [easyUI] autocomplete 简单自动完成以及ajax从服务器端完成
通过id取input标签对象,调用autocomplete方法 <script> var sources = [ "ActionScript", "Apple ...
- OpenStack笔记
*********virsh xml文件解读****************************** https://libvirt.org/format.html https://libvirt ...
- 使用Metasploit渗透攻击windows系统(二)
后渗透攻击: 介绍常用的一些命令: 查看进程:ps 查看当前进程号:getpid 查看系统信息:sysinfo 查看目标机是否为虚拟机:run post/windows/gather/checkvm ...
- Tomcat 中 jsp 中文乱码显示处理解决方案
原地址: http://blog.csdn.net/joyous/article/details/1504274 初学JSP,尤其是Tomcat环境(GlassFish默认UTF-8,则不存在此类问题 ...
- Vue(九) 自定义指令
前面介绍了许多 Vue 内置的指令,比如 v-if.v-show等,这些丰富的指令能满足我们绝大部分的业务需求,不过在需要一些特殊功能时,我们仍然希望对 DOM 进行底层的操作,这时就要用到自定义指令 ...
- Vue(二) 计算属性
模板内的表达式常用于简单的运算,当过长或逻辑复杂时,难以维护,计算属性就是解决该问题的 什么是计算属性 表达式如果过长,或逻辑更为复杂,就会变得臃肿甚至难以维护,比如: <div> {{ ...
- css清除常用默认样式表
/*公共样式*/ html, body, div, ul, li, h1, h2, h3, h4, h5, h6, p, dl, dt, dd, ol, form, input, textarea, ...
- Android : 跟我学Binder --- (3) C程序示例
目录: Android : 跟我学Binder --- (1) 什么是Binder IPC?为何要使用Binder机制? Android : 跟我学Binder --- (2) AIDL分析及手动实现 ...
- 18-09-21 numpy 的基础学习01
# 1关于numpy 的学习import numpy as np # 一 如何创建数组****# 1 有规律的一维数据的创建======# 1 range() 和arange() 区别 貌似没有区别l ...