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就可以访问微服务。
我无意中发现了这个。我很想知道为什么它会这样工作,但至少应该记录这个要求。
我有一个 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就可以访问微服务。
我无意中发现了这个。我很想知道为什么它会这样工作,但至少应该记录这个要求。