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 {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("filter 进入之前");
        filterChain.doFilter(servletRequest,servletResponse);
        System.out.println("filter 进入之后");
    }

    @Override
    public void destroy() {

    }
}

//在主程序处加上注解
//@ServletComponentScan("过滤器包名")

4.使用gateway

4.1module

4.2添加pom依赖

代码如下(示例):

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springcloud_nacos</artifactId>
        <groupId>com.csdn</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>springcloud_gateway</artifactId>
        <dependencies>
            <!--限流算法使用redis-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
            </dependency>
            <!--网关-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-gateway</artifactId>
            </dependency>
            <!--服务注册-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            </dependency>
            <dependency>
                <groupId>com.csdn</groupId>
                <artifactId>springcloud_common</artifactId>
                <version>${project.version}</version>
                <!--gateway 使用的是响应式的web编程模式  我们要把传统的web编程模型刨除-->
                <exclusions>
                    <exclusion>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-starter-web</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
        </dependencies>

        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>

            </plugins>
        </build>
    </project>

4.3yaml配置

代码如下(示例):

server:
  port: 7000
spring:
  application:
    name: api-gateway
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 # 将gateway注册到nacos
    gateway:
      discovery:
        locator:
          enabled: true # 让gateway从nacos中获取服务信息
      routes:
        - id: share-6002   # 只要唯一标识就行
          uri: lb://share-6002   #真是的地址
          order: 1
          predicates:      # 满足断言中的条件才理由
            - Path=/api/share/**,/admin/share/**
        - id: user-6001   # 只要唯一标识就行
          uri: lb://user-6001   #真是的地址
          order: 1
          predicates:      # 满足断言中的条件才理由
            - Path=/api/user/**,/admin/user/**

4.4主程序开启注解@EnableDiscoveryClient

@EnableDiscoveryClient和@EnableEurekaClient共同点就是:都是能够让注册中心能够发现,扫描到该服务。

@EnableEurekaClient只适用于Eureka作为注册;@EnableDiscoveryClient 可以是其他注册中心。
代码如下(示例):

@SpringBootApplication
@EnableDiscoveryClient
public 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;

@Component
public class AgeRoutePredicateFactory extends AbstractRoutePredicateFactory<AgeRoutePredicateFactory.Config> {

    // 1: 配置类,用于接收配置文件中的对应参数
    @Data
    @NoArgsConstructor
    public static class Config {
        private int minAge;//18 对应断言配置中的第一个参数
        private int maxAge;//60 对应断言配置中的第二个参数
    }
    // 2: 构造函数
    public AgeRoutePredicateFactory() {
        super(Config.class);
    }
    //3: 读取配置文件的中参数值 给他赋值到配置类中的属性上
    public List<String> shortcutFieldOrder() {
        //这个位置的顺序必须跟配置文件中的值的顺序对应
        return Arrays.asList("minAge", "maxAge");
    }
    //4: 断言逻辑
    public Predicate<ServerWebExchange> apply(Config config) {
        return new Predicate<ServerWebExchange>() {
            @Override
            public 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
@Slf4j
public class LogGatewayFilterFactory
        extends AbstractGatewayFilterFactory<LogGatewayFilterFactory.Config> {

    //1: 配置类 接收配置参数
    @Data
    @NoArgsConstructor
    public static class Config {
        private boolean consoleLog;
    }

    //2: 构造函数【固定写法】
    public LogGatewayFilterFactory() {
        super(Config.class);
    }

    //3: 读取配置文件中的参数 赋值到 配置类中
    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList("consoleLog");
    }

    //4: 过滤器逻辑
    @Override
    public GatewayFilter apply(Config config) {
        return new GatewayFilter() {
            Long start = System.currentTimeMillis();
            @Override
            public Mono<Void> 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接口														

@Component
public class MyGloablFilter implements GlobalFilter, Ordered {														

    // 过滤逻辑
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {														

        // 1 进入之前  controller
        System.out.println("进入之前 在 MyGloablFilter");
        // 2 放行
        return chain.filter(exchange).then(Mono.fromRunnable(() -> {
            // 在回调中写 返回的逻辑  response
            System.out.println("从controller 回来之后");
        }));
        //3 回调
    }
    // 返回的数字越小 就越先起作用
    @Override
    public int getOrder() {
        return 0;
    }
}

到此这篇关于Java之api网关断言及过滤器案例讲解的文章就介绍到这了,更多相关Java之api网关断言及过滤器内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Java使用elasticsearch基础API使用案例讲解

    1.依赖 我用的是 springboot 2.2.5.RELEASE 版本,这里只贴出主要依赖: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency> 2.配置+测试源码 这里根据elasticsearch服务端的地址进行

  • Java环境下高德地图Api的使用方式

    Java高德地图Api的使用 使用高德经纬度获取地址信息 一些准备用到的常量 /** * 高德地图请求秘钥 */ private static final String KEY = "密钥,可以去高德地图免费申请"; /** * 返回值类型 */ private static final String OUTPUT = "JSON"; /** * 根据地名获取高德经纬度Api */ private static final String GET_LNG_LAT_UR

  • elasticSearch-api的具体操作步骤讲解

    使用步骤 1.环境准备 用的是windows版,自行下载 链接: 下载地址 2.针对索引操作 这里是kibana上操作的(也可以用postman操作): #创建索引,指定文档id PUT /test1/type1/1 { "name":"张三", "age":30 } #创建索引规则(类似数据库建表) PUT /test2 { "mappings": { "properties": { "name

  • Java通过百度API实现图片车牌号识别

    本代码功能是通过调用百度API实现的,所有你需要去百度API官网申请下你的API Key 以及Secret Key才能使用它的功能哦! 拟采用百度AI实现该功能(http://ai.baidu.com/docs#/OCR-API/5116ac95) 根据百度的文档描述,初步明确需要的几个参数为: 1.应用的API Key 2.应用的Secret Key 3.access_token 4.图片数据 首先导入maven依赖 <dependency> <groupId>com.baidu

  • Java8新特性之Stream API详解

    一.前言 StreamAPI在Java8版本中使用,关注的是对数据的筛选.查找.存储等 它可以做的事情有:过滤.排序.映射.归约 二.使用流程 Stream实例化中间操作(过滤.排序.映射.规约)终止操作(匹配查找.归约.收集) 三.案例演示 public class EmployeeData { public static List<Employee> getEmployees(){ List<Employee> list = new ArrayList<>(); l

  • Java 通过API操作GraphQL

    GraphQL可以通过Java的API来实现数据的查询,通过特定的SDL查询语句,获取特定的查询数据.相当于后端作为提供数据源的"数据库",前端根据定义的SDL语句查询需要的数据,将查询数据的控制权交给前端,提高后端接口的通用性和灵活性 引入依赖 <dependency> <groupId>com.graphql-java</groupId> <artifactId>graphql-java</artifactId> <

  • Java API如何实现向Hive批量导入数据

    Java API实现向Hive批量导入数据 Java程序中产生的数据,如果导入oracle或者mysql库,可以通过jdbc连接insert批量操作完成,但是当前版本的hive并不支持批量insert操作,因为需要先将结果数据写入hdfs文件,然后插入Hive表中. package com.enn.idcard; import java.io.IOException; import java.sql.Connection; import java.sql.DriverManager; impor

  • java中并发Queue种类与各自API特点以及使用场景说明

    一 先说下队列 队列是一种数据结构.它有两个基本操作:在队列尾部加入一个元素,和从队列头部移除一个元素(注意不要弄混队列的头部和尾部) 就是说,队列以一种先进先出的方式管理数据,如果你试图向一个 已经满了的阻塞队列中添加一个元素或者是从一个空的阻塞队列中移除一个元索,将导致线程阻塞. 在多线程进行合作时,阻塞队列是很有用的工具.工作者线程可以定期地把中间结果存到阻塞队列中而其他工作者线程把中间结果取出并在将来修改它们.队列会自动平衡负载. 如果第一个线程集运行得比第二个慢,则第二个 线程集在等待

  • 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网关,就是指后台系统的统一入口,它封装了应用程序的内部结构,为客户端提供统一 路由服务,一些与业务本身功能

  • Java之Springcloud Gateway内置路由案例讲解

    Spring Cloud Gateway路由匹配是Spring WebFlux基础功能的一部分,在Spring Cloud Gateway中内置了很多路由断言工厂类.不同的断言工厂类针对HTTP请求的不同属性.多个断言工厂类可以使用逻辑"and"进行组合使用. 4.1 After Route Predicate Factory        这个Predicate工厂的实现类是AfterRoutePredicateFactory,使用一个时间参数,如果当前请求的时间在配置的赶时间之后,

  • Java之哈夫曼压缩原理案例讲解

    1. 哈夫曼压缩原理 首先要明确一点,计算机里面所有的文件都是以二进制的方式存储的. 在计算机的存储单元中,一个ASCII码值占一个字节,1个字节等于8位(1Byte = 8bit) 可以参考这个网站: ASCII码在线转换计算器 以"JavaJavaJavaJavaJavaJava"这个字符串为例,它在计算机内部是这样存储的(每一个字符的ASCII码转换为二进制存储起来): public static void main(String[] args) { String beforeS

  • Java之mybatis使用limit实现分页案例讲解

    1. Limit实现分页 1.1 为什么需要分页 减少数据的处理量 1.2 使用Limit实现分页 select * from user limit startIndex,pageSize; # 注意是从startIndex+1开始查询 pageSize 个 select * from user limit 3; # [0,3] 1.3 使用mybatis实现分页(核心:SQL) 1.3.1 接口 UserMapper.java // limit实现分页 Map后面只能是 Integer 包装类

  • Java之实现十进制与十六进制转换案例讲解

    写了两种十六进制转十进制的方式,仅供参考. 基本思路:用十六进制中每一位数乘以对应的权值,再求和就是对应的十进制 方法一: import java.util.HashMap; import java.util.Map; import java.util.Scanner; public class Test { /** * @param: [content] * @return: int * @description: 十六进制转十进制 */ public static int covert(St

  • Java之ThreadLocal使用常见和方式案例讲解

    目录 1 两大使用场景-ThreadLocal的用途 2 典型场景1:每个线程需要一个独享的对象 3 典型场景2:当前用户信息需要被线程内所有方法共享 4 ThreadLocal方法使用总结 5 ThreadLocal原理 6 ThreadLocal使用问题内存泄露 7 实际应用场景-在spring中的实例分析 [面试高频]- ThreadLocal的使用场景以及使用方式是怎么样的 1 两大使用场景-ThreadLocal的用途 典型场景1:每个线程需要一个独享的对象(通常是工具类,典型需要使用

  • Java之理解Redis回收算法LRU案例讲解

    如何通俗易懂的理解LRU算法? 1.LRU是什么? LRU全称Least Recently Used,也就是最近最少使用的意思,是一种内存管理算法,最早应用于Linux操作系统. LRU算法基于一种假设:长期不被使用的数据,在未来被用到的几率也不大.因此,当数据所占内存达到一定阈值时,我们要移除掉最近最少被使用的数据. LRU算法应用:可以在内存不够时,从哈希表移除一部分很少访问的用户. LRU是什么?按照英文的直接原义就是Least Recently Used,最近最久未使用法,它是按照一个非

  • Java数据结构 递归之迷宫回溯案例讲解

    问题介绍: 用二维数组表示一个迷宫,设置迷宫起点和终点,输出迷宫中的一条通路 实现思路: 二维数组表示迷宫: 0表示路且未走过.1表示墙.2表示通路,3表示已经走过但走不通 设置寻路方法setWay,传入地图和坐标参数 默认方向策略:下.右.上.左 假定传入的店没有走过且可以走通,将其值置为2,然后向下寻路,也就是将坐标 (i + 1, j) 传入寻路方法中 进行递归寻路,向下移动后,再次按照方向策略进行寻路,即再向下寻路,直到遇到死路,即下右左均走不通(因为将走过的路置为2,故向上也走不通,即

  • 浅谈Spring Cloud中的API网关服务Zuul

    到目前为止,我们Spring Cloud中的内容已经介绍了很多了,Ribbon.Hystrix.Feign这些知识点大家都耳熟能详了,我们在前文也提到过微服务就是把一个大的项目拆分成很多小的独立模块,然后通过服务治理让这些独立的模块配合工作等.那么大家来想这样两个问题:1.如果我的微服务中有很多个独立服务都要对外提供服务,那么对于开发人员或者运维人员来说,他要如何去管理这些接口?特别是当项目非常大非常庞杂的情况下要如何管理?2.权限管理也是一个老生常谈的问题,在微服务中,一个独立的系统被拆分成很

随机推荐