Java之api网关断言及过滤器案例讲解
目录
- 一、什么是api网关?
- 二、常见的api网关
- 三、使用步骤
- 1.Spring Cloud Gateway
- 2.优缺点
- 3.传统的过滤器
- 4.使用gateway
- 4.1module
- 4.2添加pom依赖
- 4.3yaml配置
- 4.4主程序开启注解@EnableDiscoveryClient
- 四、执行流程
- 五、断言
- 5.1: 自定义断言
- 5.2: 过滤器
一、什么是api网关? 所谓的API网关,就是指后台系统的统一入口,它封装了应用程序的内部结构,为客户端提供统一 路由服务,一些与业务本身功能无关的公共逻辑可以在这里实现,诸如认证、鉴权、监控、路由转发等等。
说白了就是通过网关找服务。
文章图片
文章图片
二、常见的api网关 Ngnix+lua
使用nginx的反向代理和负载均衡可实现对api服务器的负载均衡及高可用lua是一种脚本语言,可以来编写一些简单的逻辑, nginx支持lua脚本Kong
基于Nginx+Lua开发,性能高,稳定,有多个可用的插件(限流、鉴权等等)可以开箱即用。问题:只支持Http协议; 二次开发,自由扩展困难; 提供管理API,缺乏更易用的管控、配置方式。
Zuul Netflix开源的网关,功能丰富,使用JAVA开发,易于二次开发问题:缺乏管控,无法动态配置; 依赖组件较多; 处理Http请求依赖的是Web容器,性能不如Nginx
Spring Cloud Gateway
Spring公司为了替换Zuul而开发的网关服务,将在下面具体介绍。
三、使用步骤
文章图片
1.Spring Cloud Gateway
Spring Cloud Gateway是Spring公司基于Spring 5.0,Spring Boot 2.0 和 Project Reactor 等技术
开发的网关,它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。它的目标是替代
Netflix Zuul,其不仅提供统一的路由方式,并且基于 Filter 链的方式提供了网关基本的功能,例如:安
全,监控和限流。
2.优缺点
优点
性能强劲:是第一代网关Zuul的1.6倍
功能强大:内置了很多实用的功能,例如转发、监控、限流等
设计优雅,容易扩展
缺点
其实现依赖Netty与WebFlux,不是传统的Servlet编程模型,学习成本高
不能将其部署在Tomcat、Jetty等Servlet容器里,只能打成jar包执行
需要Spring Boot 2.0及以上的版本,才支持
3.传统的过滤器
代码如下(示例):
@WebFilter(filterName="MyFliter",urlPatterns="/api/share/*")public class MyFliter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {System.out.println(""); }@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {System.out.println("filter 进入之前"); filterChain.doFilter(servletRequest,servletResponse); System.out.println("filter 进入之后"); }@Overridepublic void destroy() {}}//在主程序处加上注解//@ServletComponentScan("过滤器包名")
4.使用gateway
4.1module
文章图片
4.2添加pom依赖 代码如下(示例):
springcloud_nacoscom.csdn 1.0-SNAPSHOT 4.0.0 springcloud_gatewayorg.springframework.boot spring-boot-starter-data-redis-reactiveorg.springframework.cloud spring-cloud-starter-gatewaycom.alibaba.cloud spring-cloud-starter-alibaba-nacos-discoverycom.csdn springcloud_common${project.version} org.springframework.boot spring-boot-starter-weborg.springframework.boot spring-boot-maven-plugin
4.3yaml配置 代码如下(示例):
server:port: 7000spring:application:name: api-gatewaycloud:nacos:discovery:server-addr: localhost:8848 # 将gateway注册到nacosgateway:discovery:locator:enabled: true # 让gateway从nacos中获取服务信息routes:- id: share-6002# 只要唯一标识就行uri: lb://share-6002#真是的地址order: 1predicates:# 满足断言中的条件才理由- Path=/api/share/**,/admin/share/**- id: user-6001# 只要唯一标识就行uri: lb://user-6001#真是的地址order: 1predicates:# 满足断言中的条件才理由- Path=/api/user/**,/admin/user/**
4.4主程序开启注解@EnableDiscoveryClient @EnableDiscoveryClient和@EnableEurekaClient共同点就是:都是能够让注册中心能够发现,扫描到该服务。
@EnableEurekaClient只适用于Eureka作为注册;@EnableDiscoveryClient 可以是其他注册中心。
代码如下(示例):
@SpringBootApplication@EnableDiscoveryClientpublic class GatewayApplication {public static void main(String[] args) {SpringApplication.run(GatewayApplication.class,args); }}
四、执行流程 1:基本概念
路由(Route)是 gateway中最基本的组件之一,表示一个具体的路由信息载体。主要定义了下面几个信息:
- | - |
---|---|
id | 路由标识符,区别于其他 Route |
uri | 路由指向的目的地uri,即客户端请求最终被转发到的微服务。 |
order | 用于多个Route 之间的排序,数值越小排序越靠前,匹配优先级越高。 |
predicate | 断言的作用是进行条件判断,只有断言都返回真,才会真正的执行路由。 |
filter | 过滤器用于修改请求和响应信息。 |
文章图片
DispatcherHandler:所有请求的调度器,负载请求分发
RoutePredicateHandlerMapping:路由谓语匹配器,用于路由的查找,以及找到路由后返回对应的WebHandler,DispatcherHandler会依次遍历HandlerMapping集合进行处理
FilteringWebHandler:使用Filter链表处理请求的WebHandler ,
RoutePredicateHandlerMapping找到路由后返回对应的FilteringWebHandler对请求进行处理,FilteringWebHandler负责组装Filter链表并调用链表处理请求。
五、断言 Predicate(断言, 谓词) 用于进行条件判断,只有断言都返回真,才会真正的执行路由。
断言就是说: 在 什么条件下 才能进行路由转发
链接: https://www.jb51.net/article/219232.htm
5.1: 自定义断言
添加自定义断言类
package gateway.pradicate; import com.alibaba.nacos.common.utils.StringUtils; import lombok.Data; import lombok.NoArgsConstructor; import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory; import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import java.util.Arrays; import java.util.List; import java.util.function.Predicate; @Componentpublic class AgeRoutePredicateFactory extends AbstractRoutePredicateFactory {// 1: 配置类,用于接收配置文件中的对应参数@Data@NoArgsConstructorpublic static class Config {private int minAge; //18 对应断言配置中的第一个参数private int maxAge; //60 对应断言配置中的第二个参数}// 2: 构造函数public AgeRoutePredicateFactory() {super(Config.class); }//3: 读取配置文件的中参数值 给他赋值到配置类中的属性上public List shortcutFieldOrder() {//这个位置的顺序必须跟配置文件中的值的顺序对应return Arrays.asList("minAge", "maxAge"); }//4: 断言逻辑public Predicate apply(Config config) {return new Predicate() {@Overridepublic boolean test(ServerWebExchange serverWebExchange) {// 4.1 接收前台传入的age参数String ageStr = serverWebExchange.getRequest().getQueryParams().getFirst("Age"); //4.2 先判断是否为空if (StringUtils.isNotEmpty(ageStr)) {//3 如果不为空,再进行路由逻辑判断int age = Integer.parseInt(ageStr); if (age < config.getMaxAge() && age > config.getMinAge()) {return true; } else {return false; }}return false; }}; }}
在需要判断的的routes下配置
文章图片
5.2: 过滤器
链接: https://www.cnblogs.com/fx-blog/p/11751977.html.
分类:局部过滤器(作用在某一个路由上)全局过滤器(作用全部路由上)Gateway的Filter从作用范围可分为两种: GatewayFilter与GlobalFilter。GatewayFilter:应用到单个路由或者一个分组的路由上。
GlobalFilter:应用到所有的路由上。
文章图片
内置过滤器举例:
文章图片
注意要从网关访问
自定义局部过滤器
文章图片
添加自定义Log配置
@Component@Slf4jpublic class LogGatewayFilterFactoryextends AbstractGatewayFilterFactory{//1: 配置类 接收配置参数@Data@NoArgsConstructorpublic static class Config {private boolean consoleLog; }//2: 构造函数【固定写法】public LogGatewayFilterFactory() {super(Config.class); }//3: 读取配置文件中的参数 赋值到 配置类中@Overridepublic List shortcutFieldOrder() {return Arrays.asList("consoleLog"); }//4: 过滤器逻辑@Overridepublic GatewayFilter apply(Config config) {return new GatewayFilter() {Long start = System.currentTimeMillis(); @Overridepublic Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {// 进入服务之前if (config.isConsoleLog()) {log.info("{} 进入 {}",new Date(), exchange.getRequest().getPath()); }// 调用服务 并且定义服务回来之后的逻辑// 注意 如果此时仅仅只是需要进入之前的验证不需要服务执行完之后的逻辑 可以 return chain.filter(exchange)即可return chain.filter(exchange).then(Mono.fromRunnable(()->{if (config.isConsoleLog()) {Long end = System.currentTimeMillis(); log.info("{} 退出 {}. 共耗时:{}",new Date(), exchange.getRequest().getPath(),(end-start)); }})); }}; }}
全局过滤器
全局过滤器作用于所有路由, 无需配置。通过全局过滤器可以实现对权限的统一校验,安全性验证等功
文章图片
自定义全局过滤器
//自定义全局过滤器需要实现GlobalFilter和Ordered接口@Componentpublic class MyGloablFilter implements GlobalFilter, Ordered {// 过滤逻辑@Overridepublic Monofilter(ServerWebExchange exchange, GatewayFilterChain chain) {// 1 进入之前controllerSystem.out.println("进入之前 在 MyGloablFilter"); // 2 放行return chain.filter(exchange).then(Mono.fromRunnable(() -> {// 在回调中写 返回的逻辑responseSystem.out.println("从controller 回来之后"); })); //3 回调}// 返回的数字越小 就越先起作用@Overridepublic int getOrder() {return 0; }}
到此这篇关于Java之api网关断言及过滤器案例讲解的文章就介绍到这了,更多相关Java之api网关断言及过滤器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
推荐阅读
- JAVA(抽象类与接口的区别&重载与重写&内存泄漏)
- PMSJ寻平面设计师之现代(Hyundai)
- 太平之莲
- 闲杂“细雨”
- 七年之痒之后
- 深入理解Go之generate
- 由浅入深理解AOP
- 期刊|期刊 | 国内核心期刊之(北大核心)
- 生活随笔|好天气下的意外之喜
- 感恩之旅第75天