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

Spring中MappingJackson2HttpMessageConverter未触发问题排查

排查自定义MappingJackson2HttpMessageConverter writeInternal未触发的问题

我之前维护Spring老项目时也碰到过几乎一模一样的问题,结合你的场景(Spring5、XML配置、自定义JSON转换器),咱们从几个最可能的方向逐一排查:

1. 优先检查HttpMessageConverter的注册顺序

这是最常见的原因!Spring会按照转换器的注册顺序来匹配处理请求,如果你没有禁用默认转换器,默认的MappingJackson2HttpMessageConverter会先于你的自定义转换器被注册。当请求的MediaType(比如application/json-v1)被默认转换器识别为可处理的类型(默认转换器会匹配所有application/json*类型),就会直接用默认转换器处理,你的自定义转换器的writeInternal自然不会被触发。

验证与解决:

  • 在XML配置的<mvc:message-converters>标签里添加register-defaults="false",这样Spring就不会自动注册默认转换器,你需要手动注册所有需要的转换器(包括你的自定义JSON、XML转换器,以及StringHttpMessageConverter这类基础转换器)。
  • 确保你的AppMappingJackson2HttpMessageConverter在转换器列表里排在最前面,示例配置:
    <mvc:annotation-driven>
        <mvc:message-converters register-defaults="false">
            <!-- 自定义JSON转换器放在最前面 -->
            <bean class="com.yourpackage.AppMappingJackson2HttpMessageConverter">
                <property name="supportedMediaTypes">
                    <list>
                        <value>application/json-v1</value>
                    </list>
                </property>
            </bean>
            <!-- 自定义XML转换器 -->
            <bean class="com.yourpackage.AppJaxb2RootElementHttpMessageConverter">
                <property name="supportedMediaTypes">
                    <list>
                        <value>application/xml-v1</value>
                    </list>
                </property>
            </bean>
            <!-- 手动添加基础转换器 -->
            <bean class="org.springframework.http.converter.StringHttpMessageConverter"/>
        </mvc:message-converters>
    </mvc:annotation-driven>
    
  • 可以在自定义转换器的构造方法或init方法里打印日志,确认它的注册顺序是否在默认转换器之前。

2. 检查自定义转换器的supports方法实现

虽然你的转换器初始化成功,也能返回JSON,但如果supports(Class<?> clazz)方法返回false,Spring会跳过它,不会调用writeInternal。

验证与解决:

  • 在supports方法里添加日志,输出传入的实体类类型和返回值,比如:
    @Override
    protected boolean supports(Class<?> clazz) {
        boolean result = super.supports(clazz);
        System.out.println("Supports class " + clazz.getName() + ": " + result);
        return result;
    }
    
  • 如果发现对控制器返回的实体类返回false,检查是否在重写supports时错误地修改了逻辑,确保调用super.supports(clazz)或者正确判断实体类类型。

3. 确认MediaType的匹配一致性

要确保你的自定义转换器支持的MediaType和控制器@RequestMapping的produces、请求头的Accept完全匹配:

  • 检查XML配置中supportedMediaTypes的配置,是否精确指定了application/json-v1(包括是否带字符集,比如application/json-v1;charset=UTF-8,如果请求头或produces带字符集,转换器也要对应)。
  • 确认控制器的produces属性是否准确,比如:
    @RequestMapping(value = "/api/data", produces = "application/json-v1")
    public ResponseEntity<DataVO> getData() {
        // ...
    }
    

4. 检查是否误重写了write方法而非writeInternal

MappingJackson2HttpMessageConverter的write方法是对外的入口,它会调用writeInternal。如果你不小心重写了write方法但没有调用super.write(),也没有手动调用writeInternal,那么你的自定义转换逻辑就不会执行。

验证:

  • 检查你的AppMappingJackson2HttpMessageConverter是否重写了write方法,如果有,确保里面包含:
    @Override
    public void write(Object object, Type type, MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
        // 必须调用父类方法,或者手动调用writeInternal
        super.write(object, type, contentType, outputMessage);
    }
    

5. 排查Spring与Jackson版本兼容性

你的项目从Spring3升级到Spring5,要确保Jackson版本和Spring5兼容(Spring5要求Jackson 2.9.x及以上版本)。如果版本不匹配,可能会出现隐藏的方法调用异常,导致writeInternal未执行(虽然你说能返回JSON,但部分逻辑可能被跳过)。

验证:

  • 检查项目依赖中的Jackson版本(比如jackson-databind),确保是2.9.x或更高;
  • 查看服务器日志,有没有隐藏的IllegalAccessError或NoSuchMethodError这类反射异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:30:31