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
相关产品推荐
相关产品推荐

