springcloud网关和过滤器

网关

不直接访问微服务

通过网关进行访问微服务

添加jar

<!-- getway-->

<dependency>

<groupId>org.springframework.cloud</groupId>

<artifactId>spring-cloud-starter-gateway</artifactId>

</dependency>

<!-- nacos-->

<dependency>

<groupId>com.alibaba.cloud</groupId>

<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>

</dependency>

和spring-boot-starter-web 有冲突

设置路由的规则

新建模块写好启动类

写下application.properties

server.port=8088
# nacos ????????
spring.cloud.nacos.discovery.server-addr=localhost:8849
# ??????
spring.application.name=gateway

写下application.yml

spring:                #注意层级
  cloud:
    gateway:
      routes:
        - id: order
          order:0   #值越小优先级越高
          uri: http://localhost:8081/   #注意空格
#断言      predicates:#简单理解为判断条件 ,满足就找uri,不满足不走此路径
            - Path=/order/**  #order为开始的路径uri里面,路径加order
          filters:
            - StripPrefix=1  #将路径截断几层 1为截断的位数 可写可不写
        - id: pro
          order: 1  
          uri: http://localhost:8082/
          predicates:
            - Path=/pro/**  #order为开始的路径uri里面
          filters:
            - StripPrefix=1  #将路径截断几层 1为截断的位数
        - id: pro1
          order:  2
          uri: http://localhost:8083/
          predicates:
            - Path=/pro1/**  #order为开始的路径uri里面
          filters:
            - StripPrefix=1  #将路径截断几层 1为截断的位数

运行路径加order可运行

l id,路由标识符,区别于其他 Route。唯一 不写 默认的唯一的值

l uri,路由指向的目的地 uri,即客户端请求最终被转发到的微服务。

l order,用于多个 Route 之间的排序,数值越小排序越靠前,匹配优先级越高。

l predicate,断言的作用是进行条件判断,只有断言都返回真,才会真正的执行路由。

l fifilter,过滤器用于修改请求和响应信息。

流程:

http-》routes-》断言-成功-uri

http-》routes-》断言-不成功-找其他的路由-x

断言

不符条件的不可运行

内置的断言工厂再框架中是存在的我们可以直接使用

Predicate(断言, 谓词) 用于进行条件判断,只有断言都返回真,才会真正的执行路由。

断言就是说: 在 什么条件下 才能进行路由转发

内置路由断言工厂

SpringCloud Gateway包括许多内置的断言工厂,所有这些断言都与HTTP请求的不同属性匹配体如下:

l 基于Datetime类型的断言工厂

此类型的断言根据时间做判断,主要有三个:

AfterRoutePredicateFactory: 接收一个日期参数,判断请求日期是否晚于指定日期

BeforeRoutePredicateFactory: 接收一个日期参数,判断请求日期是否早于指定日期

BetweenRoutePredicateFactory: 接收两个日期参数,判断请求日期是否在指定时间段内

-After=2019-12-31T23:59:59.789+08:00[Asia/Shanghai]

l 基于远程地址的断言工厂 RemoteAddrRoutePredicateFactory:

接收一个IP地址段,判断请求主机地址是否在地址段中

-RemoteAddr=192.168.1.24

l 基于Cookie的断言工厂

CookieRoutePredicateFactory:接收两个参数,cookie 名字和一个正则表达式。 判断请求

cookie是否具有给定名称且值与正则表达式匹配。

-Cookie=chocolate, ch.

l 基于Header的断言工厂

HeaderRoutePredicateFactory:接收两个参数,标题名称和正则表达式。 判断请求Header是否

具有给定名称且值与正则表达式匹配。

-Header=X-Request-Id, \d+

l 基于Host的断言工厂

HostRoutePredicateFactory:接收一个参数,主机名模式。判断请求的Host是否满足匹配规则。

-Host=**.testhost.org

l 基于Method请求方法的断言工厂

MethodRoutePredicateFactory:接收一个参数,判断请求类型是否跟指定的类型匹配。

-Method=GET

l 基于Path请求路径的断言工厂

PathRoutePredicateFactory:接收一个参数,判断请求的URI部分是否满足路径规则。

-Path=/foo/{segment}基于Query请求参数的断言工厂

QueryRoutePredicateFactory :接收两个参数,请求param和正则表达式, 判断请求参数是否具

有给定名称且值与正则表达式匹配。

-Query=baz, ba.

l 基于路由权重的断言工厂

WeightRoutePredicateFactory:接收一个[组名,权重], 然后对于同一个组内的路由按照权重转发

routes: 
    -id: weight_route1
     uri: host1
     predicates: 
        -Path=/product/** 
        -Weight=group3, 1 
 
 
    -id: weight_route2
     uri: host2
     predicates: 
        -Path=/product/** 
        -Weight= group3, 9 

l 内置路由断言工厂的使用

接下来我们验证几个内置断言的使用:

server:
  port: 7000
spring:
  application:
    name: api-gateway
  # 配置api
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
    gateway:
#      discovery:
#        locator:
#          enabled: true
      routes:
        - id: product_route   # 路由的唯一标识,只要不重复都可以,如果不写默认会通过UUID产生,一般写成被路由的服务名称
          uri: lb://shop-product  # 被路由的地址
          order: 1                     #表示优先级  数字越小优先级越高
          predicates:                  #断言: 执行路由的判断条件
            - Path=/product_serv/**
            - Before=2023-11-28T00:00:00.000+08:00 # 表示在2023前访问
          filters:                     # 过滤器: 可以在请求前或请求后作一些手脚
            - StripPrefix=1

自定义的断言

需要自己编写

Age

类名: age 首字母大写AgeRoutePredicateFactory

package com.example.config;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import javax.validation.constraints.NotNull;
import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.cloud.gateway.handler.predicate.GatewayPredicate;
import org.springframework.http.HttpRequest;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.server.ServerWebExchange;
@Component
public class AgeRoutePredicateFactory extends AbstractRoutePredicateFactory<AgeRoutePredicateFactory.Config> {
    public static final String MIN_AGE = "minAge";
    public static final String MAX_AGE = "maxAge";
    public AgeRoutePredicateFactory() {
        super(Config.class);
    }
    public List<String> shortcutFieldOrder() {
        return Arrays.asList("minAge", "maxAge");
    }
    public Predicate<ServerWebExchange> apply(final Config config) {
        // Assert.isTrue(config.getDatetime1().isBefore(config.getDatetime2()), config.getDatetime1() + " must be before " + config.getDatetime2());
        return new GatewayPredicate() {
            public boolean test(ServerWebExchange serverWebExchange) {
                // 年龄是不是在最小值和最大值之间
                // age 作为一个参数传过来
                ServerHttpRequest request = serverWebExchange.getRequest();
                List<String> age = request.getQueryParams().get("age");
                System.out.println("________________________"+age);
                String s = age.get(0);
                int i = Integer.parseInt(s);
                // 》=minAge&&<=maxAge
                return i>=config.getMinAge()&&i<= config.getMaxAge(); // true   false
            }
//            public String toString() {
//                return String.format("Between: %s and %s", config.getDatetime1(), config.getDatetime2());
//            }
        };
    }
    @Validated
    public static class Config {
        private @NotNull Integer minAge;
        private @NotNull Integer maxAge;
        public Config() {
        }
        public Integer getMinAge() {
            return minAge;
        }
        public void setMinAge(Integer minAge) {
            this.minAge = minAge;
        }
        public Integer getMaxAge() {
            return maxAge;
        }
        public void setMaxAge(Integer maxAge) {
            this.maxAge = maxAge;
        }
    }
}

过滤器:

过滤器就是在请求的传递过程中,对请求和响应做一些操作

局部过滤器

局部过滤器只对某一个路由有用

局部过滤器需要手动的配置

StripPrefix

用于截断原始请求的路径

使用数字表示要截断的路径的数量

过滤器工厂

作用

参数

AddRequestHeader

为原始请求添加Header

Header的名称及值

AddRequestParameter

为原始请求添加请求参数

参数名称及值

AddResponseHeader

为原始响应添加Header

Header的名称及值

DedupeResponseHeader

剔除响应头中重复的值

需要去重的Header名称及去重策略

Hystrix

为路由引入Hystrix的断路器保护

HystrixCommand的名称

FallbackHeaders

为fallbackUri的请求头中添加具体的异常信息

Header的名称

PrefixPath

为原始请求路径添加前缀

前缀路径

PreserveHostHeader

为请求添加一个preserveHostHeader=true的属性,路由过滤器会检查该属性以决定是否要发送原始的Host

RequestRateLimiter

用于对请求限流,限流算法为令牌桶

keyResolver、rateLimiter、statusCode、denyEmptyKey、emptyKeyStatus

RedirectTo

将原始请求重定向到指定的URL

http状态码及重定向的url

RemoveHopByHopHeadersFilter

为原始请求删除IETF组织规定的一系列Header

默认就会启用,可以通过配置指定仅删除哪些Header

RemoveRequestHeader

为原始请求删除某个Header

Header名称

RemoveResponseHeader

为原始响应删除某个Header

Header名称

RewritePath

重写原始的请求路径

原始路径正则表达式以及重写后路径的正则表达式

RewriteResponseHeader

重写原始响应中的某个Header

Header名称,值的正则表达式,重写后的值

SaveSession

在转发请求之前,强制执行WebSession::save操作

secureHeaders

为原始响应添加一系列起安全作用的响应头

无,支持修改这些安全响应头的值

SetPath

修改原始的请求路径

修改后的路径

SetResponseHeader

修改原始响应中某个Header的值

Header名称,修改后的值

SetStatus

修改原始响应的状态码

HTTP 状态码,可以是数字,也可以是字符串

StripPrefix

用于截断原始请求的路径

使用数字表示要截断的路径的数量

Retry

针对不同的响应进行重试

retries、statuses、methods、series

RequestSize

设置允许接收最大请求包的大小。如果请求包大小超过设置的值,则返回 413 Payload Too Large

请求包大小,单位为字节,默认值为5M

ModifyRequestBody

在转发请求之前修改原始请求体内容

修改后的请求体内容

ModifyResponseBody

修改原始响应体的内容

修改后的响应体内容

Default

为所有路由添加过滤器

过滤器工厂名称及值

自定义过滤器:

Ctrl+c->ctrl+v

和断言类似

全局过滤器:

不需要配置直接生效

全局的过滤器:头部有token的值放行没有就直接响应一个json数据

代码实现:

package com.example.filter;

import cn.hutool.json.JSONUtil;

import com.alibaba.cloud.commons.lang.StringUtils;

import com.sun.xml.internal.ws.api.ha.HaInfo;

import org.apache.http.HttpResponse;

import org.springframework.cloud.gateway.filter.GatewayFilterChain;

import org.springframework.cloud.gateway.filter.GlobalFilter;

import org.springframework.core.Ordered;

import org.springframework.core.io.buffer.DataBuffer;

import org.springframework.http.server.reactive.ServerHttpResponse;

import org.springframework.stereotype.Component;

import org.springframework.web.server.ServerWebExchange;

import reactor.core.publisher.Mono;

import java.io.UnsupportedEncodingException;

import java.util.HashMap;

import java.util.Map;

@Component

public class MyGlobalFilter implements GlobalFilter, Ordered {

@Override

public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

/**

* token

* 有放行

* 没有json数据 code 500 msg ”“ ,data:null

*/

String token = exchange.getRequest().getHeaders().getFirst("token");

// token不为空

if(StringUtils.isNotBlank(token)){

// 放行

return chain.filter(exchange);// 走下面的过滤器

}else{

// 返回json数据

Map map =new HashMap<>();

map.put("code",500);

map.put("msg","错误!!!");

map.put("data","sdfjdvhgs");

// 转化为json数据

String s = JSONUtil.toJsonStr(map);

// 返回json数据

ServerHttpResponse response = exchange.getResponse();

//

// Mono<Void> voidMono = response.setComplete();

DataBuffer dataBuffer;

try {

byte[] bytes = s.getBytes("utf8");

dataBuffer = response.bufferFactory().wrap(bytes);

} catch (UnsupportedEncodingException e) {

throw new RuntimeException(e);

}

return response.writeWith(Mono.just(dataBuffer));

}

//return null;

}

/**

* @return

*/

@Override

public int getOrder() {

return 0;

}

}

要求:会写全局的过滤器

局部的过滤器能看懂即可

简写网关:

根据微服务名字去找微服务的时候

2021.1 版本 ribbon剔除 使用策略的时候

1. 加jar

<dependency>

<groupId>org.springframework.cloud</groupId>

<artifactId>spring-cloud-starter-loadbalancer</artifactId>

</dependency>

</dependencies>

配置文件中

写访问微服务的时候是根据微服务的名字来进行访问的

spring:

cloud:

gateway:

discovery:

locator:

enabled: true # 根据微服务的名字进行转发的 8808/order

lower-case-service-id: true # 微服务的名字小写

总结:

网关:

作用:统一入口

编写:

原始版:

Routes:

-id

Uri:

过滤器:

局部过滤器配置

全部不需要配置直接生效 注入到容器里面

一个uri下两个,简单版默认就是轮询

思考:

页面访问的时候通过网关跨域:

作业:

写一个页面通过网关访问微服务

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值