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

Spring Boot跨服务调用GetDataset接口失败排查求助

问题:Spring Boot服务间WebClient调用嵌套HashMap接口失败

问题背景

我是Spring Boot新手,正在实现两个服务间的通信。两个服务单独运行正常,但服务间调用GetDataset接口时出错,Check接口则能正常工作。Server2的GetDataset接口通过Postman调用可正常返回嵌套HashMap,但通过Server1调用时出现反序列化错误。


相关代码

Server1代码

IndexController

@RestController
@AllArgsConstructor
@RequestMapping(path = "/webpage")
public class IndexController {

    @Autowired
    private CheckService checkService;

    @Autowired
    private SearchService searchService;

    @Autowired
    private GetDatasetService getDatasetService;

    @GetMapping(path = {"check"})
    public String CheckDataset(@RequestParam List<String> checking) {
        return checkService.checkDataset(checking);
    }

    @GetMapping(path = {"GetDataset"})
    public HashMap<String, HashMap<String, List<String>>> GetDataset(@RequestParam List<String> userinfo) {
        return getDatasetService.getDataset(userinfo);
    }
}

异常的GetDatasetService

public class GetDatasetService {

    @Value("${first.year.project.url}")
    private String url;

    public HashMap<String, HashMap<String, List<String>>> getDataset(List<String> userinfo){
        String urlForGetDataset = url + "/api/GetDataset";
        URI uri = UriComponentsBuilder
                .fromHttpUrl(urlForGetDataset)
                .queryParam("userinfo",userinfo)
                .build(Collections.emptyMap());

        return WebClient.create()
                .get()
                .uri(uri)
                .retrieve()
                .bodyToMono(GetDatasetModel.class)
                .block();
    }
}

正常工作的CheckService

@Component
public class CheckService {

    @Value("${first.year.project.url}")
    private String url;

    public String checkDataset(List<String> list){
        String urlForrCheck = url + "/api/Check";
        URI uri = UriComponentsBuilder
                .fromHttpUrl(urlForrCheck)
                .queryParam("checking",list)
                .build(Collections.emptyMap());

        String check = WebClient.create()
                .get()
                .uri(uri)
                .retrieve()
                .bodyToMono(String.class)
                .block();
        return check;
    }
}

Server2代码

RequestsController

@AllArgsConstructor
@RestController
@RequestMapping(path = {"/api"})
public class RequestsController {

    private final HashMap<String, HashMap<String,String>> DatasetMaps = ProcessingApplication.DatasetMaps;

    @GetMapping(path = {"Check"})
    public String Check(@RequestParam List<String> checking){
        GetCheck getCheck = new GetCheck(this.DatasetMaps);
        CheckModel checkModel = new CheckModel();
        checkModel.setList(checking);
        return getCheck.GetCheckDatasetMethod(checkModel.checking);
    }

    @GetMapping(path = {"GetDataset"})
    public HashMap<String, HashMap<String, List<String>>> GetDataset(@RequestParam List<String> userinfo) throws IOException {
        GetDatasetModel getDatasetModel = new GetDatasetModel();
        getDatasetModel.setList(userinfo);
        GetDataset getDataset = new GetDataset();
        return getDataset.GetDatasetMethod(getDatasetModel.userinfo.get(0),getDatasetModel.userinfo.get(1));
    }
}

CheckModel类

@Getter
@Setter
public class CheckModel {
    protected List<String> checking;
    public CheckModel(){}
    public void setList(List<String> list){
        this.checking = list;
    }
}

GetDatasetModel类

@Setter
@Getter
public class GetDatasetModel {
    protected List<String> userinfo;

    public GetDatasetModel(){}

    public void setList(List<String> userinfo){
        this.userinfo=userinfo;
    }
}

错误栈信息

org.springframework.core.codec.CodecException: Type definition error: [map type; class com.Portal.Indexes.HTMLModel.GetDatasetModel, [simple type, class java.lang.String] -> [map type; class java.util.HashMap, [simple type, class java.lang.String] -> [collection type; class java.util.List, contains [simple type, class java.lang.String]]]]
	at org.springframework.http.codec.json.AbstractJackson2Decoder.processException(AbstractJackson2Decoder.java:269)
	Suppressed: The stacktrace has been enhanced by Reactor, refer to additional information below: 
Error has been observed at the following site(s):
	*__checkpoint ⇢ Body from GET http://127.0.0.1:1200/api/GetDataset?userinfo=Alex&userinfo=check [DefaultClientResponse]
Original Stack Trace:
		at org.springframework.http.codec.json.AbstractJackson2Decoder.processException(AbstractJackson2Decoder.java:269)
		at org.springframework.http.codec.json.AbstractJackson2Decoder.decode(AbstractJackson2Decoder.java:209)
		at org.springframework.http.codec.json.AbstractJackson2Decoder.lambda$decodeToMono$2(AbstractJackson2Decoder.java:189)
		at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:132)
		at reactor.core.publisher.FluxContextWrite$ContextWriteSubscriber.onNext(FluxContextWrite.java:107)
		at reactor.core.publisher.FluxMapFuseable$MapFuseableConditionalSubscriber.onNext(FluxMapFuseable.java:299)
		at reactor.core.publisher.FluxFilterFuseable$FilterFuseableConditionalSubscriber.onNext(FluxFilterFuseable.java:337)
		at reactor.core.publisher.Operators$BaseFluxToMonoOperator.completePossiblyEmpty(Operators.java:2071)
		at reactor.core.publisher.MonoCollect$CollectSubscriber.onComplete(MonoCollect.java:145)
		at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:144)
		at reactor.core.publisher.FluxPeek$PeekSubscriber.onComplete(FluxPeek.java:260)
		at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:144)
		at reactor.netty.channel.FluxReceive.onInboundComplete(FluxReceive.java:415)
		at reactor.netty.channel.ChannelOperations.onInboundComplete(ChannelOperations.java:431)
		at reactor.netty.channel.ChannelOperations.terminate(ChannelOperations.java:485)
		at reactor.netty.http.client.HttpClientOperations.onInboundNext(HttpClientOperations.java:712)
		at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.

解决方案

问题根源

GetDatasetService中用bodyToMono(GetDatasetModel.class)尝试把Server2返回的嵌套HashMap转换成GetDatasetModel对象,但Server2实际返回的是HashMap<String, HashMap<String, List<String>>>类型,和GetDatasetModel的结构完全不匹配,导致Jackson反序列化失败。另外,GetDatasetService缺少Spring管理注解,会导致注入失败。

修复步骤

  1. 修正WebClient的反序列化类型
    直接让WebClient接收Server2返回的嵌套HashMap类型,使用ParameterizedTypeReference指定泛型结构:

    @Service
    public class GetDatasetService {
    
        @Value("${first.year.project.url}")
        private String url;
    
        public HashMap<String, HashMap<String, List<String>>> getDataset(List<String> userinfo){
            String urlForGetDataset = url + "/api/GetDataset";
            URI uri = UriComponentsBuilder
                    .fromHttpUrl(urlForGetDataset)
                    .queryParam("userinfo",userinfo)
                    .build(Collections.emptyMap());
    
            return WebClient.create()
                    .get()
                    .uri(uri)
                    .retrieve()
                    .bodyToMono(new ParameterizedTypeReference<HashMap<String, HashMap<String, List<String>>>>() {})
                    .block();
        }
    }
    
  2. 添加Spring管理注解
    给GetDatasetService添加@Service或@Component注解,确保Spring能自动注入该类。

  3. 可选:统一返回载体(推荐)
    如果想使用GetDatasetModel作为返回载体,需要修改Server2的接口,让它返回包含HashMap的GetDatasetModel对象:

    • 修改Server2的RequestsController:
      @GetMapping(path = {"GetDataset"})
      public GetDatasetModel GetDataset(@RequestParam List<String> userinfo) throws IOException {
          GetDatasetModel getDatasetModel = new GetDatasetModel();
          getDatasetModel.setList(userinfo);
          GetDataset getDataset = new GetDataset();
          HashMap<String, HashMap<String, List<String>>> result = getDataset.GetDatasetMethod(getDatasetModel.userinfo.get(0),getDatasetModel.userinfo.get(1));
          getDatasetModel.setDataset(result);
          return getDatasetModel;
      }
      
    • 修改GetDatasetModel类,添加存储结果的字段:
      @Setter
      @Getter
      public class GetDatasetModel {
          protected List<String> userinfo;
          private HashMap<String, HashMap<String, List<String>>> dataset;
      
          public GetDatasetModel(){}
      
          public void setList(List<String> userinfo){
              this.userinfo=userinfo;
          }
      }
      

    此时Server1的bodyToMono(GetDatasetModel.class)就能正常反序列化,后续从model中取出dataset即可。


内容的提问来源于stack exchange,提问作者ilie alexandru

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 02:59:52