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

Spring OpenAPI生成GET请求客户端时DTO参数序列化问题求助

解决Spring Boot OpenAPI生成WebClient时GET请求DTO参数拆分问题

方案一:调整springdoc + openapi-generator核心配置

直接在项目里做两处配置修改,就能让生成的客户端自动支持DTO转拆分后的查询参数:

  • 后端application.yml里开启springdoc的对象参数聚合:
    springdoc:
      default-flat-param-object: false
    
  • 调整openapi-generator-maven-plugin的配置,启用DTO作为查询参数并自动展开:
    <plugin>
      <groupId>org.openapitools</groupId>
      <artifactId>openapi-generator-maven-plugin</artifactId>
      <version>请替换为最新稳定版</version>
      <executions>
        <execution>
          <goals>
            <goal>generate</goal>
          </goals>
          <configuration>
            <inputSpec>${project.basedir}/target/openapi.json</inputSpec>
            <generatorName>spring</generatorName>
            <configOptions>
              <library>webclient</library>
              <useSpringBoot3>true</useSpringBoot3>
              <!-- 关键:指定查询参数风格为form,自动展开DTO属性 -->
              <queryParamStyle>form</queryParamStyle>
              <explodeFormParameters>true</explodeFormParameters>
            </configOptions>
            <additionalProperties>
              <!-- 强制用DTO作为查询参数,不拆成单个属性 -->
              <additionalProperty>useDtoForQueryParams=true</additionalProperty>
            </additionalProperties>
          </configuration>
        </execution>
      </executions>
    </plugin>
    
    后端接口保持用@ParameterObject标注DTO,生成的客户端方法会直接接受DTO参数,自动把非空属性拆成URI查询参数,后端也能正常解析。

方案二:给DTO加Schema注解明确参数风格

如果不想改全局配置,直接在DTO类上标注参数风格:

@Data
// 明确告诉OpenAPI用form风格展开参数
@Schema(style = "form", explode = true)
public class TicketSearchFilterDTO {
    private String ticketNo;
    private LocalDate startDate;
    // 其他30+属性...
}

后端接口依然用@ParameterObject:

@GetMapping("/tickets")
public ResponseEntity<List<TicketVO>> searchTickets(@ParameterObject TicketSearchFilterDTO filter) {
    // 业务逻辑
}

同时在openapi-generator的configOptions里加上:

<configOptions>
  <library>webclient</library>
  <queryParamStyle>form</queryParamStyle>
</configOptions>

生成的客户端会自动处理DTO到查询参数的拆分,只传非空属性。

方案三:WebClient过滤器手动处理(后备方案)

如果前两个方案不生效,直接给生成的WebClient加个过滤器,手动把DTO转成查询参数:

@Bean
public ExchangeFilterFunction dtoToQueryParamsFilter() {
    return (request, next) -> {
        ClientRequest.Builder requestBuilder = ClientRequest.from(request);
        // 从请求属性里拿到DTO参数(根据实际参数名调整)
        Optional<TicketSearchFilterDTO> filterOpt = request.attributes()
                .getOrDefault("filter", null) instanceof TicketSearchFilterDTO dto
                ? Optional.of(dto) : Optional.empty();

        if (filterOpt.isPresent()) {
            TicketSearchFilterDTO dto = filterOpt.get();
            // 把DTO转成Map,过滤空值
            ObjectMapper mapper = new ObjectMapper();
            Map<String, Object> paramMap = mapper.convertValue(dto, new TypeReference<>() {});
            paramMap.entrySet().removeIf(entry -> entry.getValue() == null);

            // 替换URI里的查询参数
            requestBuilder.uri(uri -> UriComponentsBuilder.fromUri(uri)
                    .replaceQueryParams(MultiValueMap.fromMap(paramMap))
                    .build());
        }
        return next.exchange(requestBuilder.build());
    };
}

然后在生成的WebClient配置类里注入这个过滤器,客户端传DTO时就会自动拆分非空属性为查询参数。

内容的提问来源于stack exchange,提问作者Roman Vottner

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 15:50:34