Spring 云网关未正确转发

Spring Cloud Gateway not forwarding correctly

我有一个 Spring 启动应用程序试图使用 Spring 云网关访问一些微服务。我使用的代码基于阅读的说明:

https://betterjavacode.com/programming/how-to-use-api-gateway-with-spring-cloud

基本上,我的应用程序复制了该站点上提供的代码,包括两个测试微服务 作者创建:

@RestController
@RequestMapping("/vendor")
public class VendorController
{
    @GetMapping("/total")
    public List vendors()
    {
        List list = new ArrayList<>();
        list.add("CJI Consultants");
        list.add("Signature Consultants");
        list.add("Deloitte");
        return list;
    }
}

@RestController
@RequestMapping("/customer")
public class CustomerController
{
    @GetMapping("/total")
    public List customers()
    {
        List list = new ArrayList<>();
        list.add("Microsoft");
        list.add("Amazon");
        list.add("Apple");
        return list;
    }
}

我的实际网关代码与作者的类似:

包 com.betterjavacode.apigatewaydemo.config;

import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SpringCloudConfig
{
    @Bean
    public RouteLocator gatewayRoutes(RouteLocatorBuilder routeLocatorBuilder)
    {
        return routeLocatorBuilder.routes()
                .route("customerModule", rt -> rt.path("/customer/**")
                        .uri("http://localhost:8081/"))
                .route("vendorModule", rt -> rt.path("/vendor/**")
                    .uri("http://localhost:8082/"))
                    .build();

    }
}

不幸的是,当我运行这个应用程序时,输入正确的网址:

http://localhost:8080/vendor/total

http://localhost:8080/customer/total

我收到 404 错误!

我似乎能够通过网关访问这两个微服务的唯一方法是将路径更改为“/**”。 例如,为了访问客户微服务,我必须更改:

.route("customerModule", rt -> rt.path("/customer/**") .uri("http://localhost:8081/"))

v.route("customerModule", rt -> rt.path("/**") .uri("http://localhost:8081/"))

然后我可以毫无问题地看到客户微服务输出。当然,我不能对两条路线使用相同的路径。看起来这个网关只能处理一个使用“/**”路径的路由。

我是不是漏掉了什么?有人可以说明为什么这不能正常工作吗?我怎样才能让这个网关转发到它应该去的路径?

你可以尝试使用StripPrefix参数。

return routeLocatorBuilder.routes()
                .route("customerModule", rt -> rt.path("/customer/**")
                        .filters(f -> f.stripPrefix(0))
                        .uri("http://localhost:8081/"))
                .route("vendorModule", rt -> rt.path("/vendor/**")
                    .filters(f -> f.stripPrefix(0))
                    .uri("http://localhost:8082/"))
                    .build();

或者您可以删除 @RequestMapping("/customer") 和 @RequestMapping("/vendor"),因为它会在向下游发送之前删除前缀路径。

我相信我已经解决了问题。事实证明,出于未知原因,每当网关中使用“/**”以外的路由时,URI 不得包含 HTTP 前缀。

换句话说,不是有路线:

route("customerModule", rt -> rt.path("/customer/**")
                    .uri("http://localhost:8081/"))

路由应该没有 HTTP 前缀:

.route("customerModule", rt -> rt.path("/customer/**")
                    .uri("localhost:8081/"))

我不知道为什么会这样,但确实如此。只要我格式化没有前缀的uri就可以访问微服务。

我无意中发现了这个。我很想知道为什么它会这样工作,但至少应该记录这个要求。