Spring Cloud Gateway Server MVC的目的是什么?它可以用在Spring Cloud Gateway Reactive的地方吗?如果可以,有人能提供更好的例子吗?这里是我想要的文档
https://docs.spring.io/spring-cloud-gateway/reference/spring-cloud-gateway-server-mvc.html
我试图让它工作,但不明白是什么问题。这是我的配置。
import static org.springframework.security.config.Customizer.withDefaults;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests(exchanges->exchanges.requestMatchers("/oauth/**","/login/**").permitAll())
.authorizeHttpRequests(https->https.anyRequest().authenticated())
.oauth2Login(withDefaults());
return http.build();
}
}
字符串
这是我的YML文件
spring:
cloud:
gateway:
mvc:
routes:
- id: service1
uri: http://localhost:8081/
predicates:
- Path=/api/**
security:
oauth2:
client:
registration:
azure:
client-id: dummy737373737373
client-secret: dummypassword737373737373
authorization-grant-type: authorization_code
redirect-uri: '{baseUrl}/login/oauth2/code/{registrationId}'
scope: User.Read
provider:
azure:
authorization-uri: https://login.microsoftonline.com/dummypasswordtenantid/oauth2/v2.0/authorize
token-uri: https://login.microsoftonline.com/dummypasswordtenantid/oauth2/v2.0/token
user-info-uri: https://graph.microsoft.com/oidc/userinfo
jwk-set-uri: https://login.microsoftonline.com/dummypasswordtenantid/discovery/v2.0/keys
user-name-attribute: name
型
服务器:端口:9000
这是我的pom
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.0</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>swiss</groupId>
<artifactId>manoj-gateway</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>manoj-gateway</name>
<description>manoj-gateway</description>
<properties>
<java.version>17</java.version>
<spring-cloud.version>2023.0.0-RC1</spring-cloud.version>
</properties>
<dependencies>
<!--<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-gateway-server-mvc</artifactId>
</dependency>-->
<!-- <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>-->
<!--
https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-gateway-mvc -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway-mvc</artifactId>
</dependency>
<!--
https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter</artifactId>
</dependency>
<!-- <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-gateway-server</artifactId>
</dependency>
-->
<!--
https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-loadbalancer -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>
型
我有一个更多的Spring Boot 服务8081上运行.我需要重定向到该服务,但它不工作.有人能解释我需要改变什么.感谢帮助,我已经作出了改变,建议,但我得到以下错误,也删除了Spring的安全只是为了检查路线是否正常工作.
java.lang.AbstractMethodError: Receiver class org.springframework.cloud.gateway.server.mvc.handler.RestClientProxyExchange$$Lambda$906/0x000000080060f988 does not define or inherit an implementation of the resolved method 'abstract java.lang.Object exchange(org.springframework.http.HttpRequest, org.springframework.web.client.RestClient$RequestHeadersSpec$ConvertibleClientHttpResponse)' of interface org.springframework.web.client.RestClient$RequestHeadersSpec$ExchangeFunction.
at org.springframework.web.client.DefaultRestClient$DefaultRequestBodyUriSpec.exchangeInternal(DefaultRestClient.java:456) ~[spring-web-6.1.1.jar:6.1.1]
at org.springframework.web.client.DefaultRestClient$DefaultRequestBodyUriSpec.exchange(DefaultRestClient.java:429) ~[spring-web-6.1.1.jar:6.1.1]
at org.springframework.cloud.gateway.server.mvc.handler.RestClientProxyExchange.exchange(RestClientProxyExchange.java:40) ~[spring-cloud-gateway-server-mvc-4.1.0-RC1.jar:4.1.0-RC1]
at org.springframework.cloud.gateway.server.mvc.handler.ProxyExchangeHandlerFunction.handle(ProxyExchangeHandlerFunction.java:106) ~[spring-cloud-gateway-server-mvc-4.1.0-RC1.jar:4.1.0-RC1]
at org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions$LookupProxyExchangeHandlerFunction.handle(HandlerFunctions.java:94) ~[spring-cloud-gateway-server-mvc-4.1.0-RC1.jar:4.1.0-RC1]
at org.springframework.web.servlet.function.HandlerFilterFunction.lambda$ofRequestProcessor$3(HandlerFilterFunction.java:83) ~[spring-webmvc-6.1.1.jar:6.1.1]
at org.springframework.web.servlet.function.HandlerFilterFunction.lambda$andThen$0(HandlerFilterFunction.java:58) ~[spring-webmvc-6.1.1.jar:6.1.1]
at org.springframework.cloud.gateway.server.mvc.config.GatewayMvcPropertiesBeanDefinitionRegistrar.lambda$getRouterFunction$3(GatewayMvcPropertiesBeanDefinitionRegistrar.java:172) ~[spring-cloud-gateway-server-mvc-4.1.0-RC1.jar:4.1.0-RC1]
at org.springframework.web.servlet.function.HandlerFilterFunction.lambda$andThen$0(HandlerFilterFunction.java:58) ~[spring-webmvc-6.1.1.jar:6.1.1]
at org.springframework.web.servlet.function.HandlerFilterFunction.lambda$ofRequestProcessor$3(HandlerFilterFunction.java:83) ~[spring-webmvc-6.1.1.jar:6.1.1]
at org.springframework.web.servlet.function.HandlerFilterFunction.lambda$andThen$1(HandlerFilterFunction.java:59) ~[spring-webmvc-6.1.1.jar:6.1.1]
at org.springframework.web.servlet.function.HandlerFilterFunction.lambda$andThen$1(HandlerFilterFunction.java:59) ~[spring-webmvc-6.1.1.jar:6.1.1]
at org.springframework.web.servlet.function.HandlerFilterFunction.lambda$apply$2(HandlerFilterFunction.java:70) ~[spring-webmvc-6.1.1.jar:6.1.1]
at org.springframework.web.servlet.function.support.HandlerFunctionAdapter.handle(HandlerFunctionAdapter.java:107) ~[spring-webmvc-6.1.1.jar:6.1.1]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1089) ~[spring-webmvc-6.1.1.jar:6.1.1]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979) ~[spring-webmvc-6.1.1.jar:6.1.1]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014) ~[spring-webmvc-6.1.1.jar:6.1.1]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:903) ~[spring-webmvc-6.1.1.jar:6.1.1]
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:564) ~[tomcat-embed-core-10.1.16.jar:6.0]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885) ~[spring-webmvc-6.1.1.jar:6.1.1]
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658) ~[tomcat-embed-core-10.1.16.jar:6.0]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:205) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) ~[tomcat-embed-websocket-10.1.16.jar:10.1.16]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.springframework.cloud.gateway.server.mvc.filter.WeightCalculatorFilter.doFilter(WeightCalculatorFilter.java:229) ~[spring-cloud-gateway-server-mvc-4.1.0-RC1.jar:4.1.0-RC1]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.springframework.cloud.gateway.server.mvc.filter.FormFilter.doFilter(FormFilter.java:97) ~[spring-cloud-gateway-server-mvc-4.1.0-RC1.jar:4.1.0-RC1]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-6.1.1.jar:6.1.1]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.1.jar:6.1.1]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-6.1.1.jar:6.1.1]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.1.jar:6.1.1]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-6.1.1.jar:6.1.1]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.1.jar:6.1.1]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:482) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:115) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:340) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:391) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:896) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1744) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at java.base/java.lang.Thread.run(Thread.java:833) ~[na:na]
型
4条答案
按热度按时间pgx2nnw81#
是的,Spring云网关MVC是Spring云网关Reactive的替代品。它们非常相似,它们之间的区别来自它们使用的方法和类-例如Spring云网关Reactive使用React式方法,因此类如
Mono
,Flux
,ServerWebExchange
,GatewayFilterFactory
和RouteLocator
仅举几例,而Spring云网关MVC使用RouterFunction
等类来定义路由,相当于RouteLocator
。下面是一个使用spring cloud gateway MVC和Reactive定义路由 predicate 和过滤器的例子。下面的例子实现了一个路由,它只会在经过一定时间后接受请求,然后通过添加请求头
X-Trace-Token
来修改请求:使用Spring Cloud网关的示例
字符串
`使用Spring Cloud网关MVC的示例
型
Spring Cloud Gateway MVC和Reactive的完整文档可以在上面描述的链接中找到。
已编辑
定义的网关路由配置应该可以正常工作。一些可能的修复方法包括:
1
。在yaml配置中定义网关服务器端口,例如。型
然后使用网关服务器端口向端口8081上的服务发出请求,例如:
http://localhost:9000/api/some_path
将被重定向到端口8081上的服务。
2
。要定义网关路由,请使用spring.cloud.gateway.mvc.routes
,因为您使用的是spring cloud gateway mvc。3
.该错误可能是由您在spring安全配置中定义的安全策略导致的,因此阻止了网关服务器重定向到服务,如果可能的话,请尝试在禁用spring安全策略的同时测试网关路由,以确定是否存在此问题。mnowg1ta2#
请注意,Spring Cloud Gateway与Spring MVC(spring-boot-starter-web)不兼容。这在官方参考文档中的如何包含Spring Cloud Gateway中有详细说明
正如错误消息所建议的,您需要删除对spring-boot-starter-web的依赖。您可以使用以下命令列出所有直接和传递依赖:
字符串
这将揭示spring-cloud-starter依赖于spring-boot-starter-web。一旦从pom.xml中删除以下行,您的应用程序应该启动:
型
请注意,
spring-cloud-gateway
与spring-boot-starter-web
不兼容另一个可能的解决方案是更改application.properties文件:
型
您可以查看此stackoverflow帖子以获取更多信息:
Spring Cloud Gateway; Spring MVC found on classpath, which is incompatible with Spring Cloud Gateway Issue
编辑:
在错误之后,它似乎与一个名为ProxyExchange的实用程序对象有关:
Spring Cloud Gateway提供了一个名为ProxyExchange的实用程序对象。您可以在常规Spring Web处理程序中使用它作为方法参数。它通过镜像HTTP动词的方法支持基本的下游HTTP交换。使用MVC,它还支持通过forward()方法转发到本地处理程序。要使用ProxyExchange,在classpath中包含正确的模块(spring-cloud-gateway-mvc或spring-cloud-gateway-webflux)。
下面的MVC示例将请求代理到/test下游的远程服务器:
型
下面的例子对Webflux做了同样的事情:
型
ProxyExchange上的便利方法使处理程序方法能够发现和增强传入请求的URI路径。例如,您可能希望提取路径的尾随元素以将其传递到下游:
型
您可以扩展更多细节here。
imzjd6km3#
我自己的理解
最近我也一直在使用SpringCloudGateway开发我们自己的网关产品,根据我对这份官方文档的了解,具体如下:
SpringCloudGateway默认的底层依赖是Spring Webflux,我们知道Spring Webflux是异步响应式编程,编程范型是使用流范型编写的;
那么SpringCloudGateway是否支持同步网关呢?官方是支持的,官网提供了相应的解决方案,就是将默认的底层Webflux切换到SpringMVC来支持同步;
相当于SpringCloudGateway提供了网关路由的两个底层实现,一个是对应Spring Webflux的异步,另一个是对应Spring MVC的同步。
示例:
1 pom.xml:
字符串
2 application.yml:
型
3 com.demo.GatewaySampleApplication:
型
4 com.demo.SimpleGateway
型
上面是所有的代码
5请求结果
型
路由的目的服务地址在SimpleGateway中,您可以将其更改为自己的服务
kfgdxczn4#
我运行了你提供的code,得到了同样的错误:
字符串
根据错误消息,变量
exchangeFunction
不是实现方法abstract java.lang.Object exchange(org.springframework.http.HttpRequest, org.springframework.web.client.RestClient$RequestHeadersSpec$ConvertibleClientHttpResponse)
:lambda实现方法无法覆盖接口方法。通常,应该只有一个这样的方法:
public java.lang.Object org.springframework.cloud.gateway.server.mvc.handler.RestClientProxyExchange$$Lambda$942/0x000000080114bf28.exchange(org.springframework.http.HttpRequest,org.springframework.web.client.RestClient$RequestHeadersSpec$ConvertibleClientHttpResponse)
。变量
exchangeFunction
在RestClientProxyExchange
中声明:exchange
方法的字节码如下:你可以通过重新定义类型来解决这个问题,从Spring的源代码中复制
RestClientProxyExchange
并在你的项目中定义它:为什么会这样?我用的是同一个源代码,只能编译正确的结果而不能编译错误的结果:
也许只有Spring知道原因。