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

Spring4.3升级至5.6后RestController响应Content-Type异常问题

解决Spring5.6升级后GWT JSONP响应Content-Type异常及回调丢失问题

问题分析

你的接口在Spring4.3下会返回带GWT JSONP回调的application/javascript响应,但升级到5.6后,Spring的消息转换逻辑发生变化:

  • 设置produces为text/javascript时,响应Content-Type被覆盖为text/html
  • 移除produces属性,默认返回application/xml;charset=UTF-8
  • 手动用ResponseEntity设置Content-Type时,携带数据会触发500错误(原因是消息转换器不支持对应MediaType的序列化)
  • 手动转JSON后丢失GWT回调包装,本质是Spring不再自动处理GWT的JSONP格式包装

可行解决方案

方案1:手动构建GWT JSONP响应字符串

直接将Java对象转为JSON后,手动包装到GWT指定的回调函数中,返回字符串类型并指定正确的Content-Type:

@RequestMapping(value = "/getValuesAsJson", method = RequestMethod.GET, produces = "application/javascript")
@ResponseBody
public String getValuesAsJson(@RequestParam final String ownerId, 
                              @RequestParam final String searchString, 
                              @RequestParam final Long valueTypeId,
                              @RequestParam(required = false) final boolean extendedSearch, 
                              @RequestParam(required = false) final String meta3Filter,
                              @RequestParam(required = false) final String meta4Filter, 
                              @RequestParam(required = false) final String valueFilter,
                              @RequestParam(required = false) final String searchFields, 
                              @RequestParam(required = false) final Boolean distinct,
                              // 若GWT请求会传递回调参数,可通过此参数接收,否则用默认值
                              @RequestParam(required = false, defaultValue = "gwt_jsonp.P0.onSuccess") String callback) throws JsonProcessingException {
    // 原有业务逻辑
    final ValuesJsonObject valuesObject = new ValuesJsonObject();
    valuesObject.setValues(values);
    
    // 将对象转为JSON字符串
    ObjectMapper objectMapper = new ObjectMapper();
    String jsonContent = objectMapper.writeValueAsString(valuesObject);
    
    // 包装成GWT要求的JSONP格式(前面的/**/用于防止XSS攻击)
    return "/**/" + callback + "(" + jsonContent + ");";
}

这种方式直接绕过Spring的自动消息转换,完全控制响应内容和格式,确保Content-Type为application/javascript且保留GWT回调结构。

方案2:配置Spring消息转换器支持JSONP

通过配置MappingJackson2HttpMessageConverter,让Spring自动处理JSON到JSONP的包装,并支持application/javascript类型的序列化:

1. 添加WebMvc配置类

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        MappingJackson2HttpMessageConverter jsonpConverter = new MappingJackson2HttpMessageConverter();
        
        // 配置支持的媒体类型,包含application/javascript
        jsonpConverter.setSupportedMediaTypes(Arrays.asList(
                MediaType.APPLICATION_JSON,
                MediaType.APPLICATION_JAVASCRIPT,
                MediaType.TEXT_JAVASCRIPT
        ));
        
        // 设置JSONP回调函数解析逻辑,适配GWT的回调格式
        jsonpConverter.setJsonpFunctionNameResolver(request -> {
            // 优先从请求参数获取回调名,没有则用GWT默认的回调格式
            String callbackParam = request.getParameter("callback");
            return callbackParam != null ? callbackParam : "gwt_jsonp.P0.onSuccess";
        });
        
        converters.add(jsonpConverter);
    }
}

2. 修改接口方法

保持原有返回对象类型,指定produces为application/javascript:

@RequestMapping(value = "/getValuesAsJson", method = RequestMethod.GET, produces = MediaType.APPLICATION_JAVASCRIPT_VALUE)
@ResponseBody
public ValuesJsonObject getValuesAsJson(@RequestParam final String ownerId, 
                                        @RequestParam final String searchString, 
                                        @RequestParam final Long valueTypeId,
                                        @RequestParam(required = false) final boolean extendedSearch, 
                                        @RequestParam(required = false) final String meta3Filter,
                                        @RequestParam(required = false) final String meta4Filter, 
                                        @RequestParam(required = false) final String valueFilter,
                                        @RequestParam(required = false) final String searchFields, 
                                        @RequestParam(required = false) final Boolean distinct) {
    // 原有业务逻辑
    final ValuesJsonObject valuesObject = new ValuesJsonObject();
    valuesObject.setValues(values);
        
    return valuesObject;
}

此方案利用Spring原生的JSONP支持,修复消息转换器对application/javascript的序列化支持,同时自动完成GWT回调包装,解决500错误和Content-Type异常问题。

关键注意点

  • 若你的GWT客户端传递的回调参数不是默认的callback,需在jsonpFunctionNameResolver中调整参数名
  • 确保ValuesJsonObject类的序列化配置正确(比如有无@JsonProperty注解、是否包含无参构造函数),避免序列化失败导致500错误

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 15:05:14