如何让Spring Boot REST API生成可被JS处理的JSONP响应?
问题分析与解决方案
你的核心问题是返回的响应不符合JSONP格式规范:
- JSONP的本质是返回一段可执行的JavaScript代码,格式为
回调函数名(纯JSON数据),比如scriptWrapper({"status":true, "data":"some data"}) - 你当前返回的是纯JSON字符串
{"status":true, "status":"some data"},浏览器无法将其识别为可执行脚本,因此触发了OpaqueResponseBlocking拦截
另外注意:你的JSON存在重复的status键,这是无效的JSON结构,需要先修正StatusDto(比如把第二个status字段重命名为data)。
具体修改方案
方案1:手动拼接JSONP格式(简单直接)
修改Spring Boot接口,接收前端传递的callback参数,并将JSON数据包裹在回调函数调用中:
@GetMapping(value = "/open/status", produces = "application/javascript") public String handlerMethod(@RequestParam(name = "callback", required = false) String callback) { StatusDto statusDto = statusBuilder(); // 修正StatusDto,避免重复的status字段 ObjectMapper objectMapper = new ObjectMapper(); try { String jsonStr = objectMapper.writeValueAsString(statusDto); // 存在callback参数时返回JSONP格式,否则返回纯JSON if (callback != null && !callback.isBlank()) { return String.format("%s(%s);", callback, jsonStr); } return jsonStr; } catch (JsonProcessingException e) { throw new RuntimeException("序列化数据失败", e); } }
方案2:使用Spring官方的JSONP支持(更优雅)
利用Spring提供的MappingJacksonValue自动处理JSONP包装,无需手动拼接字符串:
@GetMapping(value = "/open/status") public MappingJacksonValue handlerMethod(@RequestParam(name = "callback", required = false) String callback) { StatusDto statusDto = statusBuilder(); // 修正StatusDto,避免重复的status字段 MappingJacksonValue jsonWrapper = new MappingJacksonValue(statusDto); // 设置回调函数名,自动生成JSONP格式响应 if (callback != null && !callback.isBlank()) { jsonWrapper.setJsonpFunction(callback); } return jsonWrapper; }
关键注意点
- Content-Type调整:标准JSONP响应的Content-Type应为
application/javascript,而非application/jsonp(部分浏览器对后者兼容性较差) - @Async的使用:如果接口不需要异步处理可以直接去掉;若保留,建议将返回类型改为
CompletableFuture<String>(方案1)或CompletableFuture<MappingJacksonValue>(方案2),避免不必要的嵌套 - 无效JSON修正:必须修正StatusDto中重复的
status字段,否则序列化后的JSON本身就是无效的,即使包装成JSONP也无法正常解析
内容的提问来源于stack exchange,提问作者haoz
相关产品推荐
相关产品推荐

