zuul过滤器filter 的编写
通过上一节(zuul的各种配置)的学习,我们学会了zuul路由的各种配置,这一节我们来实现一下zuul的过滤器功能。那么为什么需要用到zuul的过滤器呢?我们知道zuul是我们实现外部系统统一访问的入口,那么我们就可以在 zuul 上实现 api的鉴权操作,实现微服务的统一鉴权、给微服务的响应增加额外的响应头等。
实现功能
1、在网关增加一个 pre 类型的过滤器完成一个简单的权限的校验
2、在网关增加一个 post 类型的过滤器完成增加一个相应头
3、禁用某个过滤器
代码结构
eureka-server
|- 服务注册中心
zuul
product-provider-8202
product-provider-8203
|- 服务提供者
product-consumer-8201
|- 服务消费者
product-gateway-filters-8205
|- 网关程序,演示 过滤器 的使用
代码和上一节的代码差不多,只是新建了一个网关程序,在网关中增加了过滤器。
zuul过滤器的四种类型
pre:
这种类型的过滤器在请求被路由到具体的服务之前进行调用,这个时候我们就可以进行权限的验证等等
route:
这种类型的过滤器将请求路由到具体的微服务。
post:
路由到微服务之后的处理,比如操作响应(Response),增加相应头、输出额外的内容
error:
当pre、route、post阶段发生异常时进行异常的处理
过滤器中各个方法的含义
@Override
public String filterType() {
}
@Override
public int filterOrder() {
}
@Override
public boolean shouldFilter() {
}
@Override
public Object run() {
return null;
}
filterType:
|- 表示过滤器的类型,即在那个阶段拦截,可以使用 FilterConstants 中的常量
filterOrder:
|- 过滤器的顺序,在同一组类型的过滤器中返回的值越小,越早执行。
>> pre 类型建议在 FilterConstants.PRE_DECORATION_FILTER_ORDER 之前执行
>> post 类型建议在 FilterConstants.SEND_RESPONSE_FILTER_ORDER 之前执行
shouldFilter:
|- true: 表示该过滤器执行 false:表示不执行该过滤器
run:
|- 执行具体的过滤器逻辑,返回值一般返回 null 即可。
在过滤器中,如果当前请求不合法,可以跑出异常或设置 RequestContext.getCurrentContext().setSendZuulResponse(false) 来阻止 route 类型的过滤器执行。
zuul过滤器的生命周期
一、官网zuul的请求生命周期图
解释:从上图可以看出,一次请求先经过 pre或 custom过滤器进行请求的预处理,然后通过 route 类型的过滤器将请求路由到据图的微服务,最终经过 post 类型的过滤器对响应数据进行处理。这三个阶段(pre、route、post)过程中发生了异常都会经过 error 类型的过滤器进行处理,error 处理完之后再次经过 post 类型的过滤器进行处理。
二、从代码(ZuulServlet)中看各个过滤器执行的顺序
代码编写
一、注册中心、服务提供者、服务消费者(略)
二、网关程序编写
①、引入 zuul 的依赖
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
② 启动类上增加 @EnableZuulProxy 注解
@SpringBootApplication
@EnableZuulProxy
@EnableDiscoveryClient
public class ProductGatewayZuulApplication8205 {
public static void main(String[] args) {
SpringApplication.run(ProductGatewayZuulApplication8205.class, args);
}
}
③、编写 pre 过滤器,进行权限判断
只要能从 request 中 获取到 token 的参数的值,那么认为通过,否则不通过。
package com.huan.study.zuul.filter;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.apache.commons.lang.StringUtils;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.cloud.netflix.zuul.util.ZuulRuntimeException;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
/**
* Token 认证前置过滤器
*
* @author huan.fu
* @date 2018/6/12 - 16:34
*/
@Component
public class TokenAuthenticationFilter extends ZuulFilter {
private static final String TOKEN_PARAMETER = "token";
@Override
public String filterType() {
// pre 类型的过滤器
return FilterConstants.PRE_TYPE;
}
@Override
public int filterOrder() {
// token 检验应该放在第一位来进行校验,因此需要放在最前面
return FilterConstants.SERVLET_DETECTION_FILTER_ORDER - 1;
}
@Override
public boolean shouldFilter() {
// 过滤器是否应该执行, true:表示应该执行 false:表示跳过这个过滤器执行
return true;
}
@Override
public Object run() {
RequestContext requestContext = RequestContext.getCurrentContext();
// 获取到 request
HttpServletRequest request = requestContext.getRequest();
// 判断请求参数中是否存在 token 参数
String token = request.getParameter(TOKEN_PARAMETER);
if (StringUtils.isBlank(token)) {
// 不进行路由 ===> 即 route 类型的过滤器不执行
requestContext.setSendZuulResponse(false);
throw new ZuulRuntimeException(new ZuulException(this.filterType() + ":" + this.getClass().getSimpleName(), HttpStatus.UNAUTHORIZED.value(), "token参数不可为空"));
}
return null;
}
}
注意:
1、RequestContext 为一个 ConcurrentHashMap, 并且里面的值是从 ThreadLocal 中获取的
2、可以从RequestContext中获取到 request 和 response 等等
3、requestContext.setSendZuulResponse(false) 会导致 route 类型的过滤器不进行执行。
4、如果不想自己写 error 类型的过滤器,那么默认由 SendErrorFilter 进行处理异常,如果我们想返回一个 401 的状态码给前台,出错的地方可以跑出一个 ZuulRuntimeException.
5、自己写的 过滤器 需要被 Spring 管理即可。
④、编写一个 post 类型的过滤器,增加一个额外的响应头
添加一个 new-header 的响应头
package com.huan.study.zuul.filter;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletResponse;
/**
* 添加一个新的相应头
*
* @author huan.fu
* @date 2018/6/12 - 18:01
*/
@Component
public class AddNewHeaderFilter extends ZuulFilter {
@Override
public String filterType() {
return FilterConstants.POST_TYPE;
}
@Override
public int filterOrder() {
return FilterConstants.SEND_RESPONSE_FILTER_ORDER - 1;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() {
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletResponse response = requestContext.getResponse();
response.addHeader("new-header", "new-header");
return null;
}
}
⑤、运行结果
禁用过滤器
有些时候我们可能想禁用某一类型的过滤器,比如异常返回的过滤器,每个公司可能都有自己异常返回的一套风格,如果我们不想使用 Zuul 默认的异常过滤器,那么就可以禁用掉这个过滤器。
语法格式:
zuul.<SimpleClassName>.<filterType>.disable=true
禁用 SendErrorFilter
zuul:
SendErrorFilter:
error:
disable: true
访问网关服务的 /filters 端点,看是否禁用掉
完整代码
网关层的代码: https://gitee.com/huan1993/spring-cloud-parent/tree/master/zuul
网关过滤器的代码: https://gitee.com/huan1993/spring-cloud-parent/tree/master/zuul/product-gateway-filters-8205
zuul过滤器filter 的编写的更多相关文章
- springCloud学习05之api网关服务zuul过滤器filter
前面学习了zuul的反向代理.负载均衡.fallback回退.这张学习写过滤器filter,做java web开发的对filter都不陌生,那就是客户端(如浏览器)发起请求的时候,都先经过过滤器fil ...
- 微服务网关Zuul过滤器Filter
Zuul本质 Zuul是一个网关,关于网关的介绍参考:亿级流量架构之网关设计思路.常见网关对比, 可知Zuul是一个业务网关, 而深入了解Zuul, 基本就是一系列过滤器的集合: Zuul的过滤器 下 ...
- Zuul之Filter详解
Zuul详解 官方文档:https://github.com/Netflix/zuul/wiki/How-it-Works Zuul的中心是一系列过滤器,能够在HTTP请求和响应的路由过程中执行一系列 ...
- 使用网关zuul过滤器登录鉴权
使用网关zuul过滤器登录鉴权 1.新建一个filter包 filte有很多种 pre.post. 2.新建一个类LoginFilter,实现ZuulFilter,重写 ...
- java之过滤器Filter
Java三大器之过滤器(Filter)的工作原理和代码演示 一.Filter简介 Filter也称之为过滤器,它是Servlet技术中最激动人心的技术之一,WEB开发人员通过Filter技术,对w ...
- 过滤器(Filter)和拦截器(Interceptor)
过滤器(Filter) Servlet中的过滤器Filter是实现了javax.servlet.Filter接口的服务器端程序.它依赖于servlet容器,在实现上,基于函数回调,它可以对几乎所有请求 ...
- Introduction of Servlet Filter(介绍javaweb组件之一过滤器filter)
javaweb的三大组件都需要交给web服务器运行,都需要在web.xml文件中配置. ①Servlet:javax.servlet.Servlet通过http协议接受客户端的请求,并作出响应的Jav ...
- Zuul过滤器
1.Zuul过滤器生命周期Zuul大部分功能都是通过过滤器来实现的,Zuul定义了4种标准的过滤器类型,这些过滤器类型对应于请求的典型生命周期.a.pre: 这种过滤器在请求被路由之前调用.可利用这种 ...
- zuul网关Filter处理流程及异常处理
本文转载自:https://blog.csdn.net/tianyaleixiaowu/article/details/77893822 上一篇介绍了java网关Zuul的简单使用,进行请求路由转发和 ...
随机推荐
- abp element 显示分页
App.vue添加组件 <template> <div id="app"> <dataTable></dataTable> < ...
- 如何在云效流水线 Flow中构建属于自己的NPM仓库
如何在云效流水线 Flow中构建属于自己的NPM仓库,Flow 通过各种构建组件,对各种语言提供了制品打包能力,让用户可以快速的使用流水线构建制品,并通过后续的部署任务进行部署.Flow 已经完成了与 ...
- 详解C3P0(数据库连接池)
详解C3P0(数据库连接池) 快速索引 一.基本定义 二.使用C3P0(数据库连接池)的必要性 1.JDBC传统模式开发存在的主要问题 三.数据库连接池的详细说明 四.使用连接池的明显优势 1.资源的 ...
- centos7 未启用swap导致内存使用率过高。
情况描述: 朋友在阿里云上有一台系统为CentOS7的VPS,内存为2GB,用于平时开发自己的项目时测试使用: 他在上面运行了5个docker实例,运行java程序:还有一个mysql服务: 上述5个 ...
- css3 横屏
@media screen and (orientation: portrait) { html{ width : 100vmin; height : 100vmax; } body{ width : ...
- Java基础系列(34)- 什么是数组
数组的定义 数组是相同类型数据的有序集合 数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成 其中,每一个数据称作一个数组元素,每个数组元素可以通过一个下标来访问它们
- redis代替mybatis做缓存
将redis作为缓存 <dependencies> <dependency> <groupId>org.springframework.boot</group ...
- windows2012安装django
第一步:下载python3.6.8或者到(https://www.python.org/downloads/release/python-368/)官网下载(Windows x86-64 execut ...
- 鸿蒙内核源码分析(源码结构篇) | 内核每个文件的含义 | 百篇博客分析OpenHarmony源码 | v18.04
百篇博客系列篇.本篇为: v18.xx 鸿蒙内核源码分析(源码结构篇) | 内核每个文件的含义 | 51.c.h .o 前因后果相关篇为: v08.xx 鸿蒙内核源码分析(总目录) | 百万汉字注解 ...
- 位运算符的用法 ----非(!),与(&),或(|),异或(^)
位运算符的用法 ----非(!),与(&),或(|),异或(^) 三种运算符均针对二进制 非!:是一元运算符.对一个二进制的整数按位取反,输入0则输出1,输入1则输出0. 例: 0100 -( ...