Max472 发表于 2024-2-15 13:59:07

spring gateway 通过RouteDefinitionWriter 动态添加路由

package org.springframework.cloud.gateway.route;

import reactor.core.publisher.Mono;

/**
* @author Spencer Gibb
*/
public interface RouteDefinitionWriter {

        Mono<Void> save(Mono<RouteDefinition> route);

        Mono<Void> delete(Mono<String> routeId);

}
上面是这个接口的代码,默认的实现类是
/*
* Copyright 2013-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springframework.cloud.gateway.route;

import java.util.LinkedHashMap;
import java.util.Map;

import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import org.springframework.cloud.gateway.support.NotFoundException;
import org.springframework.util.ObjectUtils;

import static java.util.Collections.synchronizedMap;

/**
* @author Spencer Gibb
*/
public class InMemoryRouteDefinitionRepository implements RouteDefinitionRepository {

        private final Map<String, RouteDefinition> routes = synchronizedMap(new LinkedHashMap<String, RouteDefinition>());

        @Override
        public Mono<Void> save(Mono<RouteDefinition> route) {
                return route.flatMap(r -> {
                        if (ObjectUtils.isEmpty(r.getId())) {
                                return Mono.error(new IllegalArgumentException("id may not be empty"));
                        }
                        routes.put(r.getId(), r);
                        return Mono.empty();
                });
        }

        @Override
        public Mono<Void> delete(Mono<String> routeId) {
                return routeId.flatMap(id -> {
                        if (routes.containsKey(id)) {
                                routes.remove(id);
                                return Mono.empty();
                        }
                        return Mono.defer(() -> Mono.error(new NotFoundException("RouteDefinition not found: " + routeId)));
                });
        }

        @Override
        public Flux<RouteDefinition> getRouteDefinitions() {
                Map<String, RouteDefinition> routesSafeCopy = new LinkedHashMap<>(routes);
                return Flux.fromIterable(routesSafeCopy.values());
        }

}


我看网上很多文章在调用 save方法添加路由的时候,调用了subscribe
routeDefinitionWriter.save(Mono.just(definition)).subscribe();
但是在调用delete方法删除路由的时候,没有调用subscribe
this.routeDefinitionWriter.delete(Mono.just(definition.getId()));
                        this.routeDefinitionWriter.save(Mono.just(definition)).subscribe();
这是为什么啊?响应式流不是在调用subscribe之后才可以执行吗?

FishC 发表于 2024-2-15 13:59:16

是的,响应式流需要在调用subscribe之后才能执行。但是在上面的代码中,保存(save)方法返回的是一个Mono,而删除(delete)方法返回的也是一个Mono。在这里调用subscribe的作用是订阅这个Mono,并且触发其中的逻辑执行。

对于保存方法,调用subscribe会触发保存路由的逻辑,因此需要调用subscribe来确保路由被保存。

而对于删除方法,只需要订阅这个Mono,而不需要触发其中的逻辑执行。因为删除操作是在删除路由时被执行的,而不是在订阅时执行的。所以不需要调用subscribe来执行删除操作。

总结来说,保存操作需要调用subscribe来触发保存逻辑的执行,而删除操作只需要订阅这个Mono即可,无需额外的调用subscribe。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

Max472 发表于 2024-2-15 14:03:14

FishC 发表于 2024-2-15 13:59
是的,响应式流需要在调用subscribe之后才能执行。但是在上面的代码中,保存(save)方法返回的是一个Mono ...

总结来说,保存操作需要调用subscribe来触发保存逻辑的执行,而删除操作只需要订阅这个Mono即可,无需额外的调用subscribe。
这句话什么意思?
响应式流中的订阅和执行有什么区别?
为什么保存需要执行而删除不需要执行?

FishC 发表于 2024-2-15 14:03:25

Max472 发表于 2024-02-15 14:03
总结来说,保存操作需要调用subscribe来触发保存逻辑 ...

抱歉,前一句话表述不准确。在响应式编程中,订阅(subscribe)与执行是相同的意思。当你调用.subscribe()方法时,你实际上是在订阅这个响应式流,并且触发其中的逻辑执行。

所以准确来说,保存操作和删除操作都需要进行订阅(即调用.subscribe()方法),以触发操作的执行。无论是保存(save)还是删除(delete),只有当你调用.subscribe()方法时,才会执行相关的逻辑。

因此,在调用保存操作的时候,需要调用.subscribe()方法,以确保保存逻辑被执行。而在调用删除操作的时候,也同样需要调用.subscribe()方法,以触发删除逻辑的执行。对于删除操作,无论是调用.subscribe()方法还是不调用.subscribe()方法,都不会执行删除操作。

综上所述,无论是保存操作还是删除操作,在调用时都需要使用.subscribe()方法来触发逻辑的执行。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
页: [1]
查看完整版本: spring gateway 通过RouteDefinitionWriter 动态添加路由