Spring Cloud(七)服务网关 Zuul Filter 使用

2024-08-21 06:48

本文主要是介绍Spring Cloud(七)服务网关 Zuul Filter 使用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Spring Cloud(七)服务网关 Zuul Filter 使用

上一篇文章中,讲了Zuul 转发,动态路由,负载均衡,等等一些Zuul 的特性,这个一篇文章,讲Zuul Filter 使用,关于网关的作用,这里就不再次赘述了,重点是zuul的Filter ,我们可以实现安全控制,比如,只有请求参数中有token和密码的客户端才能访问服务端的资源。那么如何来实现Filter了?

Spring Cloud Zuul

zuul 执行流程

执行流程图

Zuul大部分功能都是通过过滤器来实现的。Zuul中定义了四种标准过滤器类型,这些过滤器类型对应于请求的典型生命周期。

PRE:这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等。

ROUTING:这种过滤器将请求路由到微服务。这种过滤器用于构建发送给微服务的请求,并使用Apache HttpClient或Netfilx Ribbon请求微服务。

OST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等。

ERROR:在其他阶段发生错误时执行该过滤器。

除了默认的过滤器类型,Zuul还允许我们创建自定义的过滤器类型。例如,我们可以定制一种STATIC类型的过滤器,直接在Zuul中生成响应,而不将请求转发到后端的微服务。

准备工作

我们先拿之前两篇文章,构建的两个微服务代码为基础,进行下面的操作

建议先阅读以下两篇文章

Spring Cloud(四) 服务提供者 Eureka + 服务消费者 Feign
Spring Cloud(三) 服务提供者 Eureka + 服务消费者(rest + Ribbon)

http://www.ymq.io/2017/12/06/spring-cloud-feign/

http://www.ymq.io/2017/12/05/spring-cloud-ribbon-rest/

Eureka Service

导入第三篇文章中的项目:作为服务注册中心

spring-cloud-eureka-service

Eureka Provider

导入第三篇文章中的项目:作为服务的提供者

spring-cloud-eureka-provider-1
spring-cloud-eureka-provider-2
spring-cloud-eureka-provider-3

简单使用

新建项目 spring-cloud-zuul-filter

添加依赖

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>

开启服务注册

在程序的启动类 ZuulFilterApplication 通过 @EnableZuulProxy 开启 Zuul 服务网关

package io.ymq.example.zuul.filter;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
import org.springframework.context.annotation.Bean;@EnableZuulProxy
@SpringBootApplication
public class ZuulFilterApplication {public static void main(String[] args) {SpringApplication.run(ZuulFilterApplication.class, args);}
}

添加配置

配置文件 application.yml

spring:application:name: zuul-service-filterserver:port: 9000zuul:routes:api:path: /**serviceId: eureka-providereureka:client:serviceUrl:defaultZone: http://localhost:8761/eureka/

TokenFilter

ZuulFilter 是Zuul中核心组件,通过继承该抽象类,覆写几个关键方法达到自定义调度请求的作用

TokenFilter 过滤器

package io.ymq.example.zuul.filter;import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import javax.servlet.http.HttpServletRequest;/*** 描述: 过滤器 token** @author yanpenglei* @create 2017-12-11 14:38**/
public class TokenFilter extends ZuulFilter {private final Logger LOGGER = LoggerFactory.getLogger(TokenFilter.class);@Overridepublic String filterType() {return "pre"; // 可以在请求被路由之前调用}@Overridepublic int filterOrder() {return 0; // filter执行顺序,通过数字指定 ,优先级为0,数字越大,优先级越低}@Overridepublic boolean shouldFilter() {return true;// 是否执行该过滤器,此处为true,说明需要过滤}@Overridepublic Object run() {RequestContext ctx = RequestContext.getCurrentContext();HttpServletRequest request = ctx.getRequest();LOGGER.info("--->>> TokenFilter {},{}", request.getMethod(), request.getRequestURL().toString());String token = request.getParameter("token");// 获取请求的参数if (StringUtils.isNotBlank(token)) {ctx.setSendZuulResponse(true); //对请求进行路由ctx.setResponseStatusCode(200);ctx.set("isSuccess", true);return null;} else {ctx.setSendZuulResponse(false); //不对其进行路由ctx.setResponseStatusCode(400);ctx.setResponseBody("token is empty");ctx.set("isSuccess", false);return null;}}}

PasswordFilter

ZuulFilter 是Zuul中核心组件,通过继承该抽象类,覆写几个关键方法达到自定义调度请求的作用

PasswordFilter 过滤器

package io.ymq.example.zuul.filter;import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import javax.servlet.http.HttpServletRequest;/*** 描述: 过滤器 Password** @author yanpenglei* @create 2017-12-11 15:40**/
public class PasswordFilter extends ZuulFilter {private final Logger LOGGER = LoggerFactory.getLogger(TokenFilter.class);@Overridepublic String filterType() {return "post"; // 请求处理完成后执行的filter}@Overridepublic int filterOrder() {return 1; // 优先级为0,数字越大,优先级越低}@Overridepublic boolean shouldFilter() {RequestContext ctx = RequestContext.getCurrentContext();return (boolean) ctx.get("isSuccess");// 判断上一个过滤器结果为true,否则就不走下面过滤器,直接跳过后面的所有过滤器并返回 上一个过滤器不通过的结果。}@Overridepublic Object run() {RequestContext ctx = RequestContext.getCurrentContext();HttpServletRequest request = ctx.getRequest();LOGGER.info("--->>> PasswordFilter {},{}", request.getMethod(), request.getRequestURL().toString());String username = request.getParameter("password");if (null != username && username.equals("123456")) {ctx.setSendZuulResponse(true);ctx.setResponseStatusCode(200);ctx.set("isSuccess", true);return null;} else {ctx.setSendZuulResponse(false);ctx.setResponseStatusCode(400);ctx.setResponseBody("The password cannot be empty");ctx.set("isSuccess", false);return null;}}
}

开启过滤器

在程序的启动类 ZuulFilterApplication 添加 Bean

@Bean
public TokenFilter tokenFilter() {return new TokenFilter();
}@Bean
public PasswordFilter PasswordFilter() {return new PasswordFilter();
}

filterType

filterType:返回一个字符串代表过滤器的类型,在zuul中定义了四种不同生命周期的过滤器类型,具体如下:

  • pre:路由之前
  • routing:路由之时
  • post: 路由之后
  • error:发送错误调用
  • filterOrder:过滤的顺序
  • shouldFilter:这里可以写逻辑判断,是否要过滤,本文true,永远过滤。
  • run:过滤器的具体逻辑。可用很复杂,包括查sql,nosql去判断该请求到底有没有权限访问。

测试服务

依次启动项目:

spring-cloud-eureka-service
spring-cloud-eureka-provider-1
spring-cloud-eureka-provider-2
spring-cloud-eureka-provider-3
spring-cloud-zuul-filter

启动该工程后,访问服务注册中心,查看服务是否都已注册成功:http://localhost:8761/

查看各个服务注册状态

查看 eureka 监控,看服务是否都注册成功

token 测试

访问:http://127.0.0.1:8761/

步骤一 提示 token is empty

访问:http://127.0.0.1:9000/

浏览器访问

步骤二 加上token ?token=token-uuid ,已经验证通过了,提示 The password cannot be empty

访问:http://127.0.0.1:9000/?token=token-uuid

token is empty

password 测试

![The password cannot be empty][3]

加上tokenpassword &password=123456 ,已经验证通过

访问:http://127.0.0.1:9000/?token=token-uuid&password=123456

F5 刷新,每次都验证通过,并且负载均衡

Hello Zuul

源码下载

GitHub:https://github.com/souyunku/spring-cloud-examples/tree/master/spring-cloud-zuul-filter

码云:https://gitee.com/souyunku/spring-cloud-examples/tree/master/spring-cloud-zuul-filter

Contact

  • 作者:鹏磊
  • 出处:http://www.ymq.io
  • Email:admin@souyunku.com
  • 版权归作者所有,转载请注明出处
  • Wechat:关注公众号,搜云库,专注于开发技术的研究与知识分享

关注公众号-搜云库

这篇关于Spring Cloud(七)服务网关 Zuul Filter 使用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1092429

相关文章

Java中流式并行操作parallelStream的原理和使用方法

《Java中流式并行操作parallelStream的原理和使用方法》本文详细介绍了Java中的并行流(parallelStream)的原理、正确使用方法以及在实际业务中的应用案例,并指出在使用并行流... 目录Java中流式并行操作parallelStream0. 问题的产生1. 什么是parallelS

Linux join命令的使用及说明

《Linuxjoin命令的使用及说明》`join`命令用于在Linux中按字段将两个文件进行连接,类似于SQL的JOIN,它需要两个文件按用于匹配的字段排序,并且第一个文件的换行符必须是LF,`jo... 目录一. 基本语法二. 数据准备三. 指定文件的连接key四.-a输出指定文件的所有行五.-o指定输出

Java中Redisson 的原理深度解析

《Java中Redisson的原理深度解析》Redisson是一个高性能的Redis客户端,它通过将Redis数据结构映射为Java对象和分布式对象,实现了在Java应用中方便地使用Redis,本文... 目录前言一、核心设计理念二、核心架构与通信层1. 基于 Netty 的异步非阻塞通信2. 编解码器三、

Linux jq命令的使用解读

《Linuxjq命令的使用解读》jq是一个强大的命令行工具,用于处理JSON数据,它可以用来查看、过滤、修改、格式化JSON数据,通过使用各种选项和过滤器,可以实现复杂的JSON处理任务... 目录一. 简介二. 选项2.1.2.2-c2.3-r2.4-R三. 字段提取3.1 普通字段3.2 数组字段四.

Linux kill正在执行的后台任务 kill进程组使用详解

《Linuxkill正在执行的后台任务kill进程组使用详解》文章介绍了两个脚本的功能和区别,以及执行这些脚本时遇到的进程管理问题,通过查看进程树、使用`kill`命令和`lsof`命令,分析了子... 目录零. 用到的命令一. 待执行的脚本二. 执行含子进程的脚本,并kill2.1 进程查看2.2 遇到的

SpringBoot基于注解实现数据库字段回填的完整方案

《SpringBoot基于注解实现数据库字段回填的完整方案》这篇文章主要为大家详细介绍了SpringBoot如何基于注解实现数据库字段回填的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以了解... 目录数据库表pom.XMLRelationFieldRelationFieldMapping基础的一些代

一篇文章彻底搞懂macOS如何决定java环境

《一篇文章彻底搞懂macOS如何决定java环境》MacOS作为一个功能强大的操作系统,为开发者提供了丰富的开发工具和框架,下面:本文主要介绍macOS如何决定java环境的相关资料,文中通过代码... 目录方法一:使用 which命令方法二:使用 Java_home工具(Apple 官方推荐)那问题来了,

Java HashMap的底层实现原理深度解析

《JavaHashMap的底层实现原理深度解析》HashMap基于数组+链表+红黑树结构,通过哈希算法和扩容机制优化性能,负载因子与树化阈值平衡效率,是Java开发必备的高效数据结构,本文给大家介绍... 目录一、概述:HashMap的宏观结构二、核心数据结构解析1. 数组(桶数组)2. 链表节点(Node

Java AOP面向切面编程的概念和实现方式

《JavaAOP面向切面编程的概念和实现方式》AOP是面向切面编程,通过动态代理将横切关注点(如日志、事务)与核心业务逻辑分离,提升代码复用性和可维护性,本文给大家介绍JavaAOP面向切面编程的概... 目录一、AOP 是什么?二、AOP 的核心概念与实现方式核心概念实现方式三、Spring AOP 的关

详解SpringBoot+Ehcache使用示例

《详解SpringBoot+Ehcache使用示例》本文介绍了SpringBoot中配置Ehcache、自定义get/set方式,并实际使用缓存的过程,文中通过示例代码介绍的非常详细,对大家的学习或者... 目录摘要概念内存与磁盘持久化存储:配置灵活性:编码示例引入依赖:配置ehcache.XML文件:配置