Spring MVC 处理 JSONP 跨域请求的核心是服务端识别 callback 参数并返回包裹 JSON 的 JavaScript 函数调用,响应类型设为 application/javascript;它利用 script 标签绕过同源策略,仅支持 GET,前端需设 dataType: "jsonp",推荐使用 Spring 4.1+ 的 AbstractJsonpResponseBodyAdvice 统一处理,注意 XSS 防护与现代项目优先选用 CORS。

Spring MVC 中处理 JSONP 跨域请求,核心是让服务端识别 callback 参数,并将 JSON 数据包裹进 JavaScript 函数调用中返回,同时设置正确的响应类型。它不依赖 CORS 头,而是利用 <script> 标签不受同源策略限制的特性。
前端发起 JSONP 请求
必须使用 dataType: "jsonp",jQuery 会自动添加 callback=xxx 查询参数(如 ?callback=jQuery123456789),并动态插入 <script> 标签:
- 只支持 GET 方法,不能发 POST/PUT/DELETE
- 需显式设置
crossDomain: true(部分旧版 jQuery 需要) - 若需携带 Cookie,需加
xhrFields: { withCredentials: true },但注意:JSONP 实际不走 XHR,此配置对纯 JSONP 无效;真正生效的是 script 标签的crossorigin属性(极少用,且兼容性差),所以 JSONP 通常不传 Cookie
后端手动拼接 JSONP 响应
在 Controller 方法中判断是否存在 callback 参数,有则包装返回,无则正常返回 JSON:
- 用
String callback = request.getParameter("callback")或直接声明方法参数String callback - 用 Jackson 的
ObjectMapper将对象转为 JSON 字符串 - 拼接成
callback + "(" + json + ");"并设响应类型为application/javascript - 示例代码片段:
if (StringUtils.isNotBlank(callback)) {
response.getWriter().write(callback + "(" + objectMapper.writeValueAsString(data) + ");");
} else {
response.getWriter().write(objectMapper.writeValueAsString(data));
}
用 Spring 内置 JSONP 支持(推荐)
Spring 4.1+ 提供了 AbstractJsonpResponseBodyAdvice,无需修改每个 Controller,统一拦截响应:
- 新建一个
@ControllerAdvice类,继承AbstractJsonpResponseBodyAdvice - 构造器传入回调参数名,如
super("callback")(对应 URL 中的?callback=xxx) - 该 Advice 会自动检测响应体是否可 JSON 序列化,且存在 callback 参数时,自动包装为 JSONP 格式
- Controller 方法保持原样,不用判空、不用拼字符串、不用改返回类型
注意事项与限制
JSONP 是历史方案,现代项目优先选 CORS。使用 JSONP 时要注意:
- 不支持 POST 等非 GET 请求,本质是 script 标签加载
- 无法获取 HTTP 状态码或错误详情,失败只能靠超时或 script onerror
- 服务端需信任 callback 参数内容,防止 XSS,建议白名单校验函数名(如 /^[a-zA-Z_$][a-zA-Z0-9_$]*$/)
- 浏览器控制台看到的是
GET xxx?callback=xxx,不是 XHR,Network 面板显示为script类型


















