You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用OpenAPI Generator生成响应式代码时ServerWebExchange无法实例化

问题排查:Spring WebFlux + OpenAPI Generator 接口调用报错

错误日志

2022-08-05 14:23:41.257 ERROR 22404 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.IllegalStateException: No primary or single unique constructor found for interface org.springframework.web.server.ServerWebExchange] with root cause

java.lang.IllegalStateException: No primary or single unique constructor found for interface org.springframework.web.server.ServerWebExchange
    at org.springframework.beans.BeanUtils.getResolvableConstructor(BeanUtils.java:267) ~[spring-beans-5.3.21.jar:5.3.21]
...

环境与配置

  • 环境:spring-boot v2.7.1、openjdk-17
  • OpenAPI Generator Maven插件配置:
<plugin>
    <groupId>org.openapitools</groupId>
    <artifactId>openapi-generator-maven-plugin</artifactId>
    <version>6.0.1</version>
    <executions>
        <execution>
            <goals>
                <goal>generate</goal>
            </goals>
            <configuration>
                <inputSpec>${project.basedir}/src/main/resources/api/petstore.yml</inputSpec>
                <generatorName>spring</generatorName>
                <output>${project.build.directory}/generated-sources/swagger</output>
                <modelNameSuffix>DTO</modelNameSuffix>
                <generateSupportingFiles>true</generateSupportingFiles>
                <supportingFilesToGenerate>
                                ApiUtil.java
                            </supportingFilesToGenerate>
                <configOptions>
                    <reactive>true</reactive>
                    <delegatePattern>false</delegatePattern>
                    <library>spring-boot</library>
                    <dateLibrary>java8</dateLibrary>
                    <interfaceOnly>true</interfaceOnly>
                    <performBeanValidation>true</performBeanValidation>
                    <useOptional>true</useOptional>
                </configOptions>
            </configuration>
        </execution>
    </executions>
</plugin>

生成的接口代码片段

@RequestMapping(
        method = RequestMethod.GET,
        value = "/pet/{petId}",
        produces = { "application/json", "application/xml" }
    )
default Mono<ResponseEntity<PetDTO>> getPetById(
    @Parameter(name = "petId", description = "ID of pet to return", required = true) @PathVariable("petId") Long petId,
    @Parameter(hidden = true) final ServerWebExchange exchange
) {
    Mono<Void> result = Mono.empty();
    exchange.getResponse().setStatusCode(HttpStatus.NOT_IMPLEMENTED);
    for (MediaType mediaType : exchange.getRequest().getHeaders().getAccept()) {
        if (mediaType.isCompatibleWith(MediaType.valueOf("application/json"))) {
            String exampleString = "{ \"photoUrls\" : [ \"photoUrls\", \"photoUrls\" ], \"name\" : \"doggie\", \"id\" : 10, \"category\" : { \"name\" : \"Dogs\", \"id\" : 1 }, \"tags\" : [ { \"name\" : \"name\", \"id\" : 0 }, { \"name\" : \"name\", \"id\" : 0 } ], \"status\" : \"available\" }";
            result = ApiUtil.getExampleResponse(exchange, mediaType, exampleString);
            break;
        }
        if (mediaType.isCompatibleWith(MediaType.valueOf("application/xml"))) {
            String exampleString = "<pet> <id>10</id> <name>doggie</name> <photoUrls> <photoUrls>aeiou</photoUrls> </photoUrls> <tags> </tags> <status>aeiou</status> </pet>";
            result = ApiUtil.getExampleResponse(exchange, mediaType, exampleString);
            break;
        }
    }
    return result.then(Mono.empty());
}

控制器实现

@RestController
public class PetController implements PetApi {

}

问题原因

  1. 参数注入规则不匹配:ServerWebExchange是Spring WebFlux核心接口,需通过@Context注解标记才能被正确注入。生成的接口直接将其作为方法参数,Spring会尝试实例化接口,而接口无可用构造器,因此抛出异常。
  2. 注解环境冲突:生成的接口使用了Spring MVC的@RequestMapping注解,而非WebFlux对应注解,导致Servlet栈的DispatcherServlet尝试处理WebFlux类型参数,加剧了解析失败。

解决方案

方案1:修改生成配置,移除ServerWebExchange参数

在OpenAPI Generator的configOptions中添加<serverWebExchange>false</serverWebExchange>,禁止生成包含该参数的方法:

<configOptions>
    <reactive>true</reactive>
    <delegatePattern>false</delegatePattern>
    <library>spring-boot</library>
    <dateLibrary>java8</dateLibrary>
    <interfaceOnly>true</interfaceOnly>
    <performBeanValidation>true</performBeanValidation>
    <useOptional>true</useOptional>
    <serverWebExchange>false</serverWebExchange> <!-- 新增配置 -->
</configOptions>

重新生成代码后,接口方法不再包含ServerWebExchange参数,即可正常调用。

方案2:手动添加@Context注解(临时方案)

若业务需保留ServerWebExchange参数,可在生成的接口方法参数上添加@Context注解:

default Mono<ResponseEntity<PetDTO>> getPetById(
    @Parameter(name = "petId", description = "ID of pet to return", required = true) @PathVariable("petId") Long petId,
    @Parameter(hidden = true) @org.springframework.web.bind.annotation.Context final ServerWebExchange exchange
) {
    // 原有代码逻辑
}

注意:此方法需每次生成代码后手动修改,仅适合临时测试场景。

方案3:升级OpenAPI Generator版本

OpenAPI Generator 6.0.1存在WebFlux适配缺陷,升级至6.6.0及以上版本后,生成的代码会自动适配WebFlux的注解与参数注入规则,避免此类问题。

内容的提问来源于stack exchange,提问作者Mate Szilard

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 10:18:35