【springboot】【若依 (ruoyi)】@RestController 接口支持 JSONP
前言
- 若依 (ruoyi): v4.3
- springboot 2.1.1.RELEASE
- spring 5.1.3.RELEASE
- 360 极速浏览器 12.0.1476.0 (正式版本) (32 位)
- jquery 3.5.0
简单来说,@RestController 接口支持 JSONP 需要对返回结果用 callback 包裹。
需求为:
jsonpCallback固定为callback。- JSONP 开关参数为
jsonp。比如:http://localhost:8085/api/sample/form/get1?jsonp=1输出callback({"code":0,"msg":"OK"});,http://localhost:8085/api/sample/form/get1输出{"code":0,"msg":"OK"}
操作步骤
- 编写
MappingJackson2HttpMessageConverterSupportJsonp类,且继承MappingJackson2HttpMessageConverter类。 - 在
MappingJackson2HttpMessageConverterSupportJsonp类中覆盖writePrefix(在输出时,添加前缀) 和writeSuffix(在输出时,添加后缀)。 - 使用
MappingJackson2HttpMessageConverterSupportJsonpBean 替换MappingJackson2HttpMessageConverterBean。
代码如下:
@Configuration
public class JsonpSupportConfig {
@Bean
public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter(
ObjectMapper objectMapper) {
return new MappingJackson2HttpMessageConverterSupportJsonp(objectMapper);
}
private static class MappingJackson2HttpMessageConverterSupportJsonp extends MappingJackson2HttpMessageConverter {
private final String PARAM_JSONP = "jsonp";
public MappingJackson2HttpMessageConverterSupportJsonp(ObjectMapper objectMapper) {
super(objectMapper);
}
@Override
protected void writePrefix(JsonGenerator generator, Object object) throws IOException {
if (this.isJsonp(object)) {
generator.writeRaw("callback(");
}
}
@Override
protected void writeSuffix(JsonGenerator generator, Object object) throws IOException {
if (this.isJsonp(object)) {
generator.writeRaw(")");
}
}
private boolean isJsonp(Object object) {
RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes servletAttributes = (ServletRequestAttributes) attributes;
HttpServletRequest request = servletAttributes.getRequest();
String jsonpStr = request.getParameter(PARAM_JSONP);
if ("0".equals(jsonpStr)) { return false; }
if ("1".equals(jsonpStr)) { return true; }
return Boolean.valueOf(jsonpStr);
}
}
}
效果图:

spring boot 对 jsonp 的支持问题
spring 5.1 之前可以使用 AbstractJsonpResponseBodyAdvice 支持 JSONP,spring 5.1 之后将其移除了。
AbstractJsonpResponseBodyAdvice was deprecated starting from Spring 5.0.7 and 4.3.18 and in version 5.1 it is completely removed.
因为随着时间的推移,浏览器都支持了 CROS 。CROS 要比 JSONP 好。工作中,逐渐的转投 CROS。
参考
https://blog.csdn.net/sayyy/article/details/108399070
https://stackoverflow.com/questions/52845927/how-to-handle-jsonp-spring-framework-5-1
前言
- springboot 2.1.1.RELEASE
- 360 极速浏览器 12.0.1476.0 (正式版本) (32 位)
- jquery 3.5.0
- 接口跨域请求有两者方式:
- jsonp
- CORS
JSONP
JSONP (JSON with Padding) 是利用浏览器对 script 的资源引用没有同源限制,通过动态插入一个 script 标签,当资源加载到页面后会立即执行的原理实现跨域的。
JSONP 是一种非正式传输协议,具体做法是:用户传递一个 callback 参数给服务端。服务端返回数据时用 callback 参数包裹住 JSON 数据,形如 callback({name:'zhangsan',age:18})。
JSONP 只支持 GET 请求 (不支持 POST 等其它类型的 HTTP 请求),它只支持跨域 HTTP 请求这种情况,不能解决不同域的两个页面之间如何进行 JavaScript 调用的问题。
JSONP 的优势在于支持老式浏览器,弊端也比较明显:需要客户端和服务端定制进行开发。
CORS
Cross-Origin Resource Sharing (CORS) 是 W3c 工作草案,它定义了在跨域访问资源时浏览器和服务器之间如何通信。CORS 背后的基本思想是使用自定义的 HTTP 头部允许浏览器和服务器相互了解对方,从而决定请求或响应成功与否。
CORS 的具体做法为:浏览器发现请求不符合同源策略时,给请求加一个请求头 Origin。服务端如果接受请求则在返回结果中加入一个响应头 Access-Control-Allow-Origin。
CORS 与 JSONP 的使用目的相同,但是比 JSONP 更强大。CORS 支持所有的浏览器请求类型,承载的请求数据量更大(因为 URL 是有长度限制的,参考这里。以目前的技术看,URL 没有长度限制,那是不可想象的)。
CORS 也不是万能的,老旧的浏览器就不支持。
CORS 请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。下面的方法只在简单请求下做了测试。
springboot 启用 @CrossOrigin
springboot 很贴心的提供了不同粒度的控制。这里介绍全局设置。
-
添加注解
@CrossOrigin@CrossOrigin(origins = {"*"}) @SpringBootApplication public class Application { ... }说明:origins 不建议使用
*(为了方便这里用*。实际应用时,老老实实的一个一个的添加)。 -
或者
addCorsMappings@Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/api/**"); } } -
测试
测试略。模拟跨域请求,可以在浏览器里发送 ajax 请求,参考这里(使用 jquery 调试 ajax 接口 - 2)。
Http 请求如下(http://localhost:8085/api/sample/form/get1):
GET /api/sample/form/get1 HTTP/1.1
Host: localhost:8085
Connection: keep-alive
Accept: */*
Origin: null
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36
Sec-Fetch-Site: cross-site
Sec-Fetch-Mode: cors
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Http 响应如下:
HTTP/1.1 200
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Access-Control-Allow-Origin: *
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Fri, 04 Sep 2020 06:09:46 GMT
springboot 2.2.13.RELEASE 补充
-
addCorsMappings方式依然有效。@Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/api/**"); } }想了解更多,参考这里。
参考
https://www.cnblogs.com/banning/p/6250677.html
https://zhuanlan.zhihu.com/p/38972475
https://www.cnblogs.com/zhaosq/p/10529803.html
【springboot】【若依 (ruoyi)】@RestController 接口跨域请求_若依跨域 - CSDN 博客
Web on Servlet Stack (spring.io)

浙公网安备 33010602011771号