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

Spring+OpenFeign调用WebLogic上JEE服务报400:JSON格式不匹配

问题描述

使用OpenFeign发送携带对象列表参数的Post请求调用Web服务时,部署在WebLogic上的目标JEE服务无法识别发送的JSON格式——服务期望的JSON外层多一个tEbourse键。该问题仅在WebLogic环境出现,WildFly环境下正常。

相关代码及格式如下:

Feign客户端接口

@FeignClient(name = "clientfeign",url = "http://192.168.x.x:8080")
public interface SRestClient {

    @PostMapping(path = "/api/method-adresse")
    List<TEbourse> checkFonctionnaire(@RequestBody List<TEbourse> demandes);
}

实体类TEbourse

@Data
@AllArgsConstructor
@NoArgsConstructor
public class TEbourse {
    private int id;
    private String nom;
    private String prenom;
    private String sexe;
    private String date_naissance;
    private String lieu_naissance;
    private String matricule;
    private String statut;
}

当前发送的JSON格式

[
      {
      "ID": "12",
      "date_naissance": "08/01/84",
      "lieu_naissance": "",
      "matricule": "",
      "nom": "XXXX",
      "prenom": "XXXX XX",
      "sexe": "M",
      "statut": ""
   },
      {
      "ID": "20",
      "date_naissance": "02/10/98",
      "lieu_naissance": "",
      "matricule": "",
       "nom": "XXXX",
      "prenom": "XXXX XX",
      "sexe": "M",
      "statut": ""
   },
      {
      "ID": "152",
      "date_naissance": "27/03/94",
      "lieu_naissance": "",
      "matricule": "",
       "nom": "XXXX",
      "prenom": "XXXX XX",
      "sexe": "M",
      "statut": ""
   }
]

目标服务期望的JSON格式

{ "tEbourse":[
      {
      "date_naissance": "08/01/84",
      "ID": "12",
      "lieu_naissance": "",
      "matricule": "",
       "nom": "XXXX",
      "prenom": "XXXX XX",
      "sexe": "M",
      "statut": ""
   },
      {
      "date_naissance": "02/10/98",
      "ID": "20",
      "lieu_naissance": "",
      "matricule": "",
       "nom": "XXXX",
      "prenom": "XXXX XX",
      "sexe": "M",
      "statut": ""
   },
      {
      "date_naissance": "27/03/94",
      "ID": "152",
      "lieu_naissance": "",
      "matricule": "",
       "nom": "XXXX",
      "prenom": "XXXX XX",
      "sexe": "M",
      "statut": ""
   }
]} 

问题原因

WildFly和WebLogic对JAX-RS请求参数的解析策略存在差异:

  • WildFly默认支持直接接收JSON数组作为请求体,无需外层包装键;
  • WebLogic的JAX-RS实现(多为Oracle的Jersey版本)更严格,要求请求体必须是JSON对象,数组需要被包裹在指定键下才能与服务端参数正确绑定。

核心原因还是服务端在WebLogic上的接口定义,大概率是将列表参数封装在含tEbourse属性的对象中,而非直接接收List类型。


解决方案

提供两种可选择的实现方式:

方式一:创建包装类封装列表

这是最直接且易维护的方案:

  1. 新增包装类,属性名与服务端期望的tEbourse完全匹配:
@Data
@AllArgsConstructor
@NoArgsConstructor
public class TEbourseWrapper {
    private List<TEbourse> tEbourse;
}
  1. 修改Feign客户端接口,将请求参数替换为包装类:
@FeignClient(name = "clientfeign",url = "http://192.168.x.x:8080")
public interface SRestClient {

    @PostMapping(path = "/api/method-adresse")
    List<TEbourse> checkFonctionnaire(@RequestBody TEbourseWrapper demandesWrapper);
}
  1. 调用时将原列表封装到包装类中:
List<TEbourse> demandes = ...; // 原有列表数据
TEbourseWrapper wrapper = new TEbourseWrapper(demandes);
List<TEbourse> result = sRestClient.checkFonctionnaire(wrapper);

方式二:自定义Feign消息转换器(无需新增类场景)

如果不想新增包装类,可通过自定义序列化逻辑实现:

  1. 自定义消息转换器,序列化List时自动添加外层键:
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;

import java.io.IOException;
import java.util.List;

public class TEbourseListConverter implements HttpMessageConverter<List<TEbourse>> {

    private final ObjectMapper objectMapper;

    public TEbourseListConverter(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    @Override
    public boolean canRead(Class<?> clazz, MediaType mediaType) {
        return false; // 仅处理序列化
    }

    @Override
    public boolean canWrite(Class<?> clazz, MediaType mediaType) {
        return List.class.isAssignableFrom(clazz) && TEbourse.class.isAssignableFrom(((List<?>) clazz).getClass().getComponentType());
    }

    @Override
    public List<MediaType> getSupportedMediaTypes() {
        return List.of(MediaType.APPLICATION_JSON);
    }

    @Override
    public List<TEbourse> read(Class<? extends List<TEbourse>> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
        throw new UnsupportedOperationException("不支持反序列化");
    }

    @Override
    public void write(List<TEbourse> tEbourseList, MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
        // 将列表封装到含tEbourse键的对象中序列化
        objectMapper.writeValue(outputMessage.getBody(), new TEbourseWrapper(tEbourseList));
    }
}
  1. 配置Feign使用该转换器:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import feign.codec.Encoder;
import org.springframework.cloud.openfeign.support.SpringEncoder;

import java.util.ArrayList;
import java.util.List;

@Configuration
public class FeignConfig {

    @Bean
    public Encoder feignEncoder(ObjectMapper objectMapper) {
        List<HttpMessageConverter<?>> converters = new ArrayList<>();
        converters.add(new TEbourseListConverter(objectMapper));
        converters.add(new MappingJackson2HttpMessageConverter(objectMapper));
        return new SpringEncoder(() -> converters);
    }
}
  1. 在Feign接口上指定配置类:
@FeignClient(name = "clientfeign",url = "http://192.168.x.x:8080", configuration = FeignConfig.class)
public interface SRestClient {

    @PostMapping(path = "/api/method-adresse")
    List<TEbourse> checkFonctionnaire(@RequestBody List<TEbourse> demandes);
}

注意:自定义转换器需确保仅对List<TEbourse>生效,避免影响其他接口的序列化逻辑。


内容的提问来源于stack exchange,提问作者fady okana

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 00:44:57