Spring Cloud Gateway Server MVC-我们可以将Spring mvc与Spring Cloud Gateway一起使用吗

qacovj5a  于 5个月前  发布在  Spring
关注(0)|答案(4)|浏览(120)

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]

pgx2nnw8

pgx2nnw81#

是的,Spring云网关MVC是Spring云网关Reactive的替代品。它们非常相似,它们之间的区别来自它们使用的方法和类-例如Spring云网关Reactive使用React式方法,因此类如MonoFluxServerWebExchangeGatewayFilterFactoryRouteLocator仅举几例,而Spring云网关MVC使用RouterFunction等类来定义路由,相当于RouteLocator
下面是一个使用spring cloud gateway MVC和Reactive定义路由 predicate 和过滤器的例子。下面的例子实现了一个路由,它只会在经过一定时间后接受请求,然后通过添加请求头X-Trace-Token来修改请求:

使用Spring Cloud网关的示例

@Bean
public RouteLocator routeConfig(RouteLocatorBuilder builder) {
    return builder.routes()
        .route(p -> p.path("/accounts").and().after(ZonedDateTime.parse("2023-12-06T19:03:47.789-05:00[America/New_York]")))
        .filters(f -> f.addRequestHeader("X-Trace-Token", "cd855f1a-0df3-4199-bc33-821dc797fc29")
        .uri("http://example.com"))
        .build();
}

字符串
`使用Spring Cloud网关MVC的示例

@Bean
public RouterFunction<ServerResponse> routeConfig() {
    return route("route_id")
        .route(after(ZonedDateTime.parse("2023-12-06T19:03:47.789-05:00[America/New_York]")), GET("/accounts"), http("http://example.com"))
        .after(addRequestHeader("X-Trace-Token", "cd855f1a-0df3-4199-bc33-821dc797fc29"))
        .build();
}


Spring Cloud Gateway MVC和Reactive的完整文档可以在上面描述的链接中找到。

已编辑

定义的网关路由配置应该可以正常工作。一些可能的修复方法包括:
1。在yaml配置中定义网关服务器端口,例如。

server:
 port: 9000


然后使用网关服务器端口向端口8081上的服务发出请求,例如:
http://localhost:9000/api/some_path
将被重定向到端口8081上的服务。
2。要定义网关路由,请使用spring.cloud.gateway.mvc.routes,因为您使用的是spring cloud gateway mvc。
3.该错误可能是由您在spring安全配置中定义的安全策略导致的,因此阻止了网关服务器重定向到服务,如果可能的话,请尝试在禁用spring安全策略的同时测试网关路由,以确定是否存在此问题。

mnowg1ta

mnowg1ta2#

请注意,Spring Cloud Gateway与Spring MVC(spring-boot-starter-web)不兼容。这在官方参考文档中的如何包含Spring Cloud Gateway中有详细说明
正如错误消息所建议的,您需要删除对spring-boot-starter-web的依赖。您可以使用以下命令列出所有直接和传递依赖:

mvn dependency:tree

字符串
这将揭示spring-cloud-starter依赖于spring-boot-starter-web。一旦从pom.xml中删除以下行,您的应用程序应该启动:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter</artifactId>
</dependency>


请注意,spring-cloud-gatewayspring-boot-starter-web不兼容
另一个可能的解决方案是更改application.properties文件:

spring.main.web-application-type=reactive


您可以查看此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下游的远程服务器:

@RestController
@SpringBootApplication
public class GatewaySampleApplication {

    @Value("${remote.home}")
    private URI home;

    @GetMapping("/test")
    public ResponseEntity<?> proxy(ProxyExchange<byte[]> proxy) throws Exception {
        return proxy.uri(home.toString() + "/image/png").get();
    }

}


下面的例子对Webflux做了同样的事情:

@RestController
@SpringBootApplication
public class GatewaySampleApplication {

    @Value("${remote.home}")
    private URI home;

    @GetMapping("/test")
    public Mono<ResponseEntity<?>> proxy(ProxyExchange<byte[]> proxy) throws Exception {
        return proxy.uri(home.toString() + "/image/png").get();
    }

}


ProxyExchange上的便利方法使处理程序方法能够发现和增强传入请求的URI路径。例如,您可能希望提取路径的尾随元素以将其传递到下游:

@GetMapping("/proxy/path/**")
public ResponseEntity<?> proxyPath(ProxyExchange<byte[]> proxy) throws Exception {
  String path = proxy.path("/proxy/path/");
  return proxy.uri(home.toString() + "/foos/" + path).get();
}


您可以扩展更多细节here

imzjd6km

imzjd6km3#

我自己的理解
最近我也一直在使用SpringCloudGateway开发我们自己的网关产品,根据我对这份官方文档的了解,具体如下:
SpringCloudGateway默认的底层依赖是Spring Webflux,我们知道Spring Webflux是异步响应式编程,编程范型是使用流范型编写的;
那么SpringCloudGateway是否支持同步网关呢?官方是支持的,官网提供了相应的解决方案,就是将默认的底层Webflux切换到SpringMVC来支持同步;
相当于SpringCloudGateway提供了网关路由的两个底层实现,一个是对应Spring Webflux的异步,另一个是对应Spring MVC的同步。

示例:

1 pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.winning.gate</groupId>
    <artifactId>mvc-gateway</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>2023.0.0</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway-mvc</artifactId>
        </dependency>
    </dependencies>

</project>

字符串

2 application.yml:

server:
  port: 9098

3 com.demo.GatewaySampleApplication:

package com.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * @author xch
 * 2023/12/15 16:56
 */
@SpringBootApplication
public class GatewaySampleApplication {

    public static void main(String[] args) {
        SpringApplication.run(GatewaySampleApplication.class, args);
    }

}

4 com.demo.SimpleGateway

package com.demo;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.function.RouterFunction;
import org.springframework.web.servlet.function.ServerResponse;

import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;

/**
 * @author xch
 * 2023/12/15 16:52
 */

@Configuration
class SimpleGateway {
    @Bean
    public RouterFunction<ServerResponse> getRoute() {
        return route().GET("/demo", http("http://localhost:8080/")).build();
    }
}


上面是所有的代码

5请求结果

GET http://localhost:9098/demo?ceshi=ceshi

HTTP/1.1 200 
date: Fri, 15 Dec 2023 09:23:37 GMT
Content-Type: application/json
Transfer-Encoding: chunked
Keep-Alive: timeout=60
Connection: keep-alive

{
  "code": 0,
  "data": "ceshi"
}
Response file saved.
> 2023-12-15T172337.200.json

Response code: 200; Time: 19ms (19 ms); Content length: 25 bytes (25 B)


路由的目的服务地址在SimpleGateway中,您可以将其更改为自己的服务

kfgdxczn

kfgdxczn4#

我运行了你提供的code,得到了同样的错误:

2023-12-16T16:07:30.395+08:00 ERROR 40097 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Handler dispatch failed: java.lang.AbstractMethodError: Receiver class org.springframework.cloud.gateway.server.mvc.handler.RestClientProxyExchange$$Lambda$942/0x000000080114bf28 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.] with root cause

字符串
根据错误消息,变量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)
变量exchangeFunctionRestClientProxyExchange中声明:

exchange方法的字节码如下:

你可以通过重新定义类型来解决这个问题,从Spring的源代码中复制RestClientProxyExchange并在你的项目中定义它:

为什么会这样?我用的是同一个源代码,只能编译正确的结果而不能编译错误的结果:

也许只有Spring知道原因。

相关问题