浅挖一下微服务,网关添加请求头进行数据传递

前言

无意中留心的一串代码,就浅浅的挖了一下,发现还挺有意思。

背景

微服务的网关在配置拦截器filter用于登录校验时,一般把拿到的数据会用请求头的形式存到ServerWebExchange exchange里,然后由网关发给服务,服务再从请求头里拿。我在添加请求头的时候,发现这个方法有一种莫名的魔力,让我忍不住CTRL+⇧

开始

废话不多说,让我进去看看

具体方法:

//创建一个名为userId的请求头,把数据id存进去
exchange.mutate().request((r -> r.header("userId", id))).build();

这里exchange.mutate()返回一个ServerWebExchange.Builder内部接口

request()方法正是接口一个抽象方法

public interface ServerWebExchange {
  default Builder mutate() {
        return new DefaultServerWebExchangeBuilder(this);
    }
  public interface Builder {//内部接口
    Builder request(Consumer<ServerHttpRequest.Builder> requestBuilderConsumer);
  }
}

有趣的来了,这个Consumer<ServerHttpRequest.Builder> requestBuilderConsumer是什么,没见过,CTRL+⇧

@FunctionalInterface
public interface Consumer<T> {
​
    /**
     * Performs this operation on the given argument.
     *
     * @param t the input argument
     */
  
    /**
    *对给定的参数执行此操作。
    *
    *@param输入参数
    */
    void accept(T t);
​
    /**
     * Returns a composed {@code Consumer} that performs, in sequence, this
     * operation followed by the {@code after} operation. If performing either
     * operation throws an exception, it is relayed to the caller of the
     * composed operation.  If performing this operation throws an exception,
     * the {@code after} operation will not be performed.
     *
     * @param after the operation to perform after this operation
     * @return a composed {@code Consumer} that performs in sequence this
     * operation followed by the {@code after} operation
     * @throws NullPointerException if {@code after} is null
     */
​
    /**
     *返回一个组合的{@code Consumer},它按顺序执行以下操作
     *操作之后是{@code after}操作。如果执行以下任一操作
     *操作抛出一个异常,它被中继到调用者
     *组合操作。如果执行此操作会引发异常,
     *将不会执行{@code after}操作。
     *
     *此操作后要执行的操作后的@param
     *@返回一个按顺序执行以下操作的组合{@code Consumer}
     *操作之后是{@code after}操作
     *如果{@code after}为null,则@抛出NullPointerException
     */
    default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }
}

又是一个接口,上面还有说明

  • void accept(T t);一个抽象方法没有返回值,应该就是与(r -> r.header("userId", id))对应

  • andThen(Consumer<? super T> after)先按下不表

从第一方法我们能看到

accept(T t)方法没有返回值,那么request()方法调用Lambda表达式重写的accept(T t)是没有值。

所以:exchange.mutate() == exchange.mutate().request() ?

当然,其中肯定有变化,不然调这个凑代码量吗(感觉发现摸鱼小技巧,嘿嘿嘿嘿)

 public interface Builder {//内部接口
    Builder request(Consumer<ServerHttpRequest.Builder> requestBuilderConsumer);
  }

实现类:

public ServerWebExchange.Builder request(Consumer<ServerHttpRequest.Builder> consumer) {
        ServerHttpRequest.Builder builder = this.delegate.getRequest().mutate();
        consumer.accept(builder);
        return this.request(builder.build());
    }

这里的泛型是ServerHttpRequest.Builder,CTRL+⇧

public interface ServerHttpRequest extends HttpRequest, ReactiveHttpInputMessage {
  public interface Builder {
    Builder header(String headerName, String... headerValues);
  }
}

又是一个内部接口抽象方法

而这个方法的实现是:

class DefaultServerHttpRequestBuilder implements ServerHttpRequest.Builder {
  public ServerHttpRequest.Builder header(String headerName, String... headerValues) {
        this.headers.put(headerName, Arrays.asList(headerValues));
        return this;
    }
}

这个类和方法的设计允许开发者通过链式调用的方式构建复杂的HTTP请求,同时添加多个请求头。

那这里问题来了,绕了一个圈,还是没有发现谁在添加请求头

我们退到前面exchange.mutate() == exchange.mutate().request()

先看exchange.mutate()

default Builder mutate() {
        return new DefaultServerWebExchangeBuilder(this);
    }

CTRL+⇧ 进入 DefaultServerWebExchangeBuilder

DefaultServerWebExchangeBuilder(ServerWebExchange delegate) {
        Assert.notNull(delegate, "Delegate is required");
        this.delegate = delegate;
    }

没看懂对吧,再给你看看exchange.mutate().request()的实现类

public ServerWebExchange.Builder request(Consumer<ServerHttpRequest.Builder> consumer) {
        ServerHttpRequest.Builder builder = this.delegate.getRequest().mutate();
        consumer.accept(builder);
        return this.request(builder.build());
    }

this.delegate,没错这两个在一个类里面DefaultServerWebExchangeBuilder

一个构造方法,一个实现方法

自此,完成闭环


PS:第一次发到上面来,平常都是私下写着玩,中间明显写嗨了。而且还可以继续挖着玩,比如一次添加多个请求头

谢谢!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值