文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Java之api网关断言及过滤器案例讲解

2024-04-02 19:55

关注

一、什么是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网关断言及过滤器内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯