El filtro de puerta de enlace Spring Cloud Gateway es realmente divertido

1. Agregue el filtro de puerta de enlace de encabezado de solicitud AddRequestHeader

La ruta coincidente agregará el encabezado de solicitud especificado y el formato de valor como nombre de encabezado de solicitud, valor de encabezado de solicitud

server:
  port: 81
spring:
  cloud:
    gateway:
      routes:   # 配置路由,是一个集合
        - id: apptest1 # 路由的ID, 没有固定规则但要求唯一,建议配合服务名
          uri: http://localhost:80  # 匹配后提供服务的路由地址
          predicates:
            - Path=/say/**
          filters:
            - AddRequestHeader=gateway,8848
复制代码

Cambiar el código del controlador

package gateway.controller;

import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.RequestContextHolder;
import reactor.netty.http.server.HttpServerRequest;

import java.util.Iterator;
import java.util.Map;

/**
 * @author sz
 * @DATE 2022/3/20  20:15
 */

@Data
@RestController
public class HelloController {

    @Value("${server.port}")
    public String serverPort;

    @GetMapping("/say")
    public String say(
        @RequestHeader(name = "gateway",required = false)String value
    )
    {



        return "HelloWord   "+serverPort +"   "+value;
    }

    @GetMapping("/say/one")
    public String sayOne()
    {
        return "HelloWord one";
    }

}

复制代码

resultado devuelto

image-20220321205828575

No llevamos el encabezado de solicitud al enviar la solicitud, porque el encabezado de solicitud especificado se agregó a la solicitud después de hacer coincidir la ruta apptest1

2. Filtrado de puerta de enlace AddRequestParameter para agregar parámetros de solicitud

La ruta coincidente agregará el parámetro de solicitud especificado y el formato de valor como nombre de parámetro de solicitud, valor de parámetro de solicitud

server:
  port: 81
spring:
  cloud:
    gateway:
      routes:   # 配置路由,是一个集合
        - id: apptest1 # 路由的ID, 没有固定规则但要求唯一,建议配合服务名
          uri: http://localhost:8081  # 匹配后提供服务的路由地址
          predicates:
            - Path=/say/**
          filters:
            - AddRequestParameter=gateway,8848
复制代码
package gateway.controller;

import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestContextHolder;
import reactor.netty.http.server.HttpServerRequest;

import java.util.Iterator;
import java.util.Map;

/**
 * @author sz
 * @DATE 2022/3/20  20:15
 */

@Data
@RestController
public class HelloController {

    @Value("${server.port}")
    public String serverPort;

    @GetMapping("/say")
    public String say(
        @RequestParam(name = "gateway",required = false)String value
    )
    {
        return "HelloWord   "+serverPort +"   "+value;
    }

    @GetMapping("/say/one")
    public String sayOne()
    {
        return "HelloWord one";
    }

}

复制代码

image-20220321210415276

3. Agregue el filtro de puerta de enlace del encabezado de respuesta AddResponseHeader

La ruta coincidente agregará el parámetro de encabezado de respuesta especificado y el formato de valor como nombre de encabezado de respuesta, valor de encabezado de respuesta

server:
  port: 81
spring:
  cloud:
    gateway:
      routes:   # 配置路由,是一个集合
        - id: apptest1 # 路由的ID, 没有固定规则但要求唯一,建议配合服务名
          uri: http://localhost:8081  # 匹配后提供服务的路由地址
          predicates:
            - Path=/say/**
          filters:
            - AddResponseHeader=gateway, 8848
复制代码

image-20220321220449374

No llevamos ningún encabezado de solicitud cuando enviamos la solicitud, pero cuando la respuesta respondió, pudimos ver que se agregó el encabezado de solicitud que especificamos

4. Filtrado de puerta de enlace de mapeo de encabezado de solicitud MapRequestHeader

MapRequestHeader= encabezado de solicitud uno, encabezado de solicitud dos

Si el encabezado de la solicitud no existe en el objeto de la solicitud, no se realizará ningún cambio en el encabezado de la solicitud del objeto de la solicitud.

Si el encabezado de solicitud 1 existe en el objeto de solicitud y el encabezado de solicitud 2 no existe, el encabezado de solicitud 2 se agregará al encabezado de solicitud del objeto de solicitud y el valor del encabezado de solicitud 1 se asignará al encabezado de solicitud. 2

Si el encabezado de solicitud 2 ya existe en el objeto de solicitud, no realizará ningún cambio en el objeto de solicitud.

server:
  port: 81
spring:
  cloud:
    gateway:
      routes:   # 配置路由,是一个集合
        - id: apptest1 # 路由的ID, 没有固定规则但要求唯一,建议配合服务名
          uri: http://localhost:8081  # 匹配后提供服务的路由地址
          predicates:
            - Path=/say/**
          filters:
            - MapRequestHeader=fuck, hello
复制代码

¿Qué significa esto?

Si el encabezado de solicitud del objeto de solicitud lleva el encabezado de solicitud de mierda y no hay encabezado de solicitud de saludo

Se agregará el encabezado de solicitud de saludo, y el valor del encabezado de solicitud de mierda se asignará al encabezado de solicitud de saludo

Si el encabezado de solicitud del objeto de solicitud ya incluye el encabezado de solicitud de saludo, o no hay un encabezado de solicitud de mierda, el encabezado de solicitud de saludo no realizará ningún cambio.

ver la demostración

@Data
@RestController
public class HelloController {

    @Value("${server.port}")
    public String serverPort;

    @GetMapping("/say")
    public String say(
    )
    {
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = servletRequestAttributes.getRequest();
        HttpServletResponse response = servletRequestAttributes.getResponse();

        String fuck = request.getHeader("fuck");
        System.out.println("fuck = " + fuck);
        String hello = request.getHeader("hello");
        System.out.println("hello = " + hello);

        return "HelloWord   ";
    }

    @GetMapping("/say/one")
    public String sayOne()
    {
        return "HelloWord one";
    }

}

复制代码

Postman_BabRHpaYyi

5. Agregar filtro de puerta de enlace de prefijo de ruta PrefixPath

Si coincide con la ruta actual, agregue el prefijo especificado antes de la ruta

server:
  port: 81
spring:
  cloud:
    gateway:
      routes:   # 配置路由,是一个集合
        - id: apptest1 # 路由的ID, 没有固定规则但要求唯一,建议配合服务名
          uri: http://localhost:8081  # 匹配后提供服务的路由地址
          predicates:
            - Path=/say/**
          filters:
            - PrefixPath=/prefix
复制代码

Configurar como arriba

En este momento, la asignación de solicitud no se puede encontrar al acceder a /say, porque la dirección de asignación del objeto de solicitud se ha agregado con el prefijo dirección /prefijo

image-20220321222743896

La ruta a la que se accede en este momento es localhost:81/prefix/say

6. Redirigir filtro de puerta de enlace RedirectTo

server:
  port: 81
spring:
  cloud:
    gateway:
      routes:   # 配置路由,是一个集合
        - id: apptest1 # 路由的ID, 没有固定规则但要求唯一,建议配合服务名
          uri: http://localhost:8081  # 匹配后提供服务的路由地址
          predicates:
            - Path=/say/**
          filters:
            - RedirectTo=302,http://localhost:8081/say/one
复制代码

Si la solicitud actual coincide con esta ruta, se redirigirá a la dirección especificada

image-20220321223154148

image-20220321223200384

7. Eliminar el filtro de puerta de enlace del encabezado de la solicitud RemoveRequestHeader

server:
  port: 81
spring:
  cloud:
    gateway:
      routes:   # 配置路由,是一个集合
        - id: apptest1 # 路由的ID, 没有固定规则但要求唯一,建议配合服务名
          uri: http://localhost:8081  # 匹配后提供服务的路由地址
          predicates:
            - Path=/say/**
          filters:
            - RemoveRequestHeader=fuck
复制代码

如果当前请求匹配此路由将删除请求头中指定的请求头参数

image-20220321223520891

请求对象中有请求头fuck,且值为you

但controller层接收的时候,已经没有了

image-20220321223628794

8.删除响应头网关过滤器 RemoveResponseHeader

如果当前请求匹配此路由,将删除响应头中指定的头信息

server:
  port: 81
spring:
  cloud:
    gateway:
      routes:   # 配置路由,是一个集合
        - id: apptest1 # 路由的ID, 没有固定规则但要求唯一,建议配合服务名
          uri: http://localhost:8081  # 匹配后提供服务的路由地址
          predicates:
            - Path=/say/**
          filters:
            - RemoveResponseHeader=fuck
复制代码

先不加此网关过滤器,访问 /say

 @GetMapping("/say")
    public String say(
    )
    {
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = servletRequestAttributes.getRequest();
        HttpServletResponse response = servletRequestAttributes.getResponse();


        response.setHeader("fuck","you");

        return "HelloWord   ";
    }

复制代码

image-20220321223952223

响应头中有fuck,且有值

如果我们加上此过滤器,重启网关模块再次访问

server:
  port: 81
spring:
  cloud:
    gateway:
      routes:   # 配置路由,是一个集合
        - id: apptest1 # 路由的ID, 没有固定规则但要求唯一,建议配合服务名
          uri: http://localhost:8081  # 匹配后提供服务的路由地址
          predicates:
            - Path=/say/**
          filters:
            - RemoveResponseHeader=fuck
复制代码

image-20220321224059097

响应头中的fuck已经被删除了

9.删除请求参数网关过滤器 PrefixPath

server:
  port: 81
spring:
  cloud:
    gateway:
      routes:   # 配置路由,是一个集合
        - id: apptest1 # 路由的ID, 没有固定规则但要求唯一,建议配合服务名
          uri: http://localhost:8081  # 匹配后提供服务的路由地址
          predicates:
            - Path=/say/**
          filters:
            - RemoveRequestParameter=fuck
复制代码

如果当前请求匹配此路由,请求参数中的fuck就被删除,如果有的情况下

10.路径重写网关过滤器 RewritePath

server:
  port: 81
spring:
  cloud:
    gateway:
      routes:   # 配置路由,是一个集合
        - id: apptest1 # 路由的ID, 没有固定规则但要求唯一,建议配合服务名
          uri: http://localhost:8081  # 匹配后提供服务的路由地址
          predicates:
            - Path=/say/**
          filters:
            - RewritePath=/say(?<segment>/?.*), $\{segment}
复制代码

如果当前请求匹配此路由,将按照指定规则重写路径

如上的配置 我们访问 /say/fuck 将会被重写为 访问 /fuck

 @GetMapping("/say")
    public String say(
    )
    {
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = servletRequestAttributes.getRequest();
        HttpServletResponse response = servletRequestAttributes.getResponse();


        response.setHeader("fuck","you");

        return "HelloWord   ";
    }


    @GetMapping("/fuck")
    public String fuck(){
        return "RewritePath fuck";
    }
复制代码

image-20220321225128973

11.模板重设路径网关过滤器 SetPath

如果请求匹配当前路由,将使用模板重新设置路径

什么意思呢 看下面这个配置

spring:
  cloud:
    gateway:
      routes:   # 配置路由,是一个集合
        - id: apptest1 # 路由的ID, 没有固定规则但要求唯一,建议配合服务名
          uri: http://localhost:80  # 匹配后提供服务的路由地址
          predicates:
            - Path=/fuck/{segment}
          filters:
            - SetPath=/{segment}
复制代码

如果我们访问 /fuck/say 路径将被重新设置为 /say

image-20220326225714495

例如,我们访问的是 localhost:81/fuck/say 但实际上我们访问的 localhost:81/say

image-20220326225752792

12.设置响应状态码网关过滤器 SetStatus

将响应的状态码修改为指定的值,注意,仅仅只是修改响应状态码状态码

spring:
  cloud:
    gateway:
      routes:   # 配置路由,是一个集合
        - id: apptest1 # 路由的ID, 没有固定规则但要求唯一,建议配合服务名
          uri: http://localhost:80  # 匹配后提供服务的路由地址
          predicates:
            - Path=/say
          filters:
            - SetStatus=404
复制代码

image-20220326230514360

13.重试网关过滤器 Retry

  • retries:应尝试的重试次数。
  • statuses:应重试的 HTTP 状态代码,使用 表示。org.springframework.http.HttpStatus
  • methods:应重试的 HTTP 方法,通过使用 表示。org.springframework.http.HttpMethod
  • series:要重试的一系列状态代码,使用 表示。org.springframework.http.HttpStatus.Series
  • exceptions:应重试的引发的异常的列表。
  • backoff:为重试配置的指数退避。重试是在回退间隔为 之后执行的,其中迭代是。如果配置了 ,则应用的最大回退限制为 。如果为 true,则使用 计算回退。firstBackoff * (factor ^ n)``n``maxBackoff``maxBackoff``basedOnPreviousValue``prevBackoff * factor
spring:
  cloud:
    gateway:
      routes:   # 配置路由,是一个集合
        - id: apptest1 # 路由的ID, 没有固定规则但要求唯一,建议配合服务名
          uri: http://localhost:80  # 匹配后提供服务的路由地址
          predicates:
            - Path=/say/**
          filters:
            - name: Retry
              args:
                retries: 30
                statuses: NOT_FOUND
                methods: GET,POST
                backoff:
                  firstBackoff: 1000ms
                  maxBackoff: 5000ms
                  factor: 2
                  basedOnPreviousValue: false
复制代码

如上面的配置 则效果为

请求的路径如果匹配当前路由( id: apptest1 ) 且返回的响应状态码为 NOT_FOUND (404) 则会重试30次

第一次重试间隔为 1秒 之后每次最大间隔为 5秒

为了看到测试效果 这里添加了全局过滤器

@Component
public class GlobalFilterConf implements GlobalFilter {

    Long start = System.currentTimeMillis();
    long end = 0L;

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

        System.out.println("收到请求 : "+exchange.getRequest().getPath().toString());

        Long temp =  end = System.currentTimeMillis();


        System.out.println("间隔: "+ (end - start)/1000);

        start = temp;

        return chain.filter(exchange);
    }
}
复制代码

访问一个不存在的映射地址

image-20220326232849940

idea64_PDn6FXTaei

Supongo que te gusta

Origin juejin.im/post/7079432098267791397
Recomendado
Clasificación