jsonp跨域请求详解——从繁至简
2017-05-09 10:37
239 查看
jsonp跨域请求详解——从繁至简
原文链接:https://zhuanlan.zhihu.com/p/24390509详细讲述跨域请求的由来与演变——由hinesboy分享
什么是jsonp?为什么要用jsonp?
JSONP(JSON with Padding)是JSON的一种“使用模式”,可用于解决主流浏览器的跨域数据访问的问题。由于同源策略,一般来说位于 server1.example.com 的网页无法与不是 server1.example.com的服务器沟通,而 HTML 的
$.get("http://169.254.200.238:8080/jsonp.do", function (data) { console.log(data); });
此时浏览器抛出异常
因为两者的端口号分别为8080、8020 并不同源,从报错中也可以看出。
但是,我们换一种方式请求:
<script type="text/javascript" src="http://169.254.200.238:8080/jsonp.do"> </script>
可以看到,此时同样的请求确成功了!由此,我们可以得出可以进行跨域请求,这是jsonp的基础,但是浏览器同样抛出了语句不合法的异常,
那是因为我们请求的数据会立马被浏览器当作javascript语句去执行(谁让我们用
callback( {"result":"success"} )
其中{“result”:”success”} 是我们想要获取的数据,浏览器会立即执行callback这个函数,此时,我们已经定义好了函数名为callback这个函数:
function callback(data){ // data为返回数据 // TODO 解析数据 }
这样是不是一切都说的通了!
所以jsonp跨域请求的关键就在于:
4000
服务端要在返回的数据外层包裹一个客户端已经定义好的函数
ajax跨域请求实例理解了上述内容,你就已经掌握了跨域请求的原理,那么下面我们将利用ajax发起跨域请求,服务端通过spring MVC处理jsonp请求。
//通过JQuery Ajax 发起jsonp请求 (注:不是必须通过jq发起请求 , 例如:Vue Resource中提供 $.http.jsonp(url, [options])) $.ajax({ // 请求方式 type: "get", // 请求地址 url: "http://169.254.200.238:8080/jsonp.do", // 标志跨域请求 dataType: "jsonp", // 跨域函数名的键值,即服务端提取函数名的钥匙(默认为callback) jsonp: "callbackparam", // 客户端与服务端约定的函数名称 jsonpCallback: "jsonpCallback", // 请求成功的回调函数,json既为我们想要获得的数据 success: function(json) { console.log(json); }, // 请求失败的回调函数 error: function(e) { alert("error"); } });
@RequestMapping({"/jsonp.do"}) public String jsonp(@RequestParam("callbackparam") String callback){ // callback === "jsonpCallback" return callback + "({\"result\":\"success\"})"; }
此时,客户端接收到的返回值为:
这就是一个完整的跨域请求,但是这样就结束了吗?
细心的同学可能会发觉,现在如果不通过跨域去请求jsonp.do这个接口,不是就报错了吗?
是的,现在这个接口仅仅只能被携带callbackparam这个参数的请求。
为了解决这个问题,我们要判断请求的来源,
return (request.from === jsonp) ? callback(data) : data ;
这才是我们想要的结果,解决这个问题需要我们对每个接口都做判断,或者通过AOP等等方式实现统一处理,这样做好像并不优雅。
在spring4.2以上的版本,支持了CORS(跨域资源共享)
CORS
CORS是一个W3C标准,全称是”跨域资源共享”(Cross-origin resource sharing)。
它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。
为什么说它优雅呢?
整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。
因此,实现CORS通信的关键是服务器。 只要服务器实现了CORS接口 ,就可以跨源通信。
所以我们客户端可以像什么都没发生一样,依旧漠不关心的发送我们的请求:
// 不用担心跨域问题 $.ajax({ // 请求方式 type: "get", // 请求地址 url: "http://169.254.200.238:8080/jsonp.do", // 此时依然请求json格式数据 而非jsonp dataType: "json", // 请求成功的回调函数 success: function(json) { console.log(json); }, // 请求失败的回调函数 error: function(e) { alert("error"); } });
而我们用spring MVC实现的服务端也出乎意料的简洁(基于xml):
// spring配置文件 spring必须为4.2以上版本 <mvc:cors> <mvc:mapping path="/**" /> </mvc:cors>
注意:通过以上两步我们已经完成了跨域请求操作。
这里,我对整个项目添加了跨域支持 , path 为支持跨域的路径 , 同样你可以在这里做详细配置:
<mvc:cors> <mvc:mapping path="/api/**" allowed-origins="http://domain1.com, http://domain2.com" allowed-methods="GET, PUT" allowed-headers="header1, header2, header3" exposed-headers="header1, header2" allow-credentials="false" max-age="123" /> <mvc:mapping path="/resources/**" allowed-origins="http://domain1.com" /> </mvc:cors>
当然,spring也支持通过java的方式进行配置:
// 此种方式等同于xml全局配置 @Configuration public class WebConfig extends WebMvcConfigurerAdapter { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**"); } } // 此种方式为详细配置 @Configuration public class WebConfig extends WebMvcConfigurerAdapter { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/api/**") .allowedOrigins("http://domain2.com") .allowedMethods("PUT", "DELETE") .allowedHeaders("header1", "header2", "header3") .exposedHeaders("header1", "header2") .allowCredentials(false).maxAge(3600); } }
pring 也允许针对某个controller类 或者 方法进行 跨域 ,通过@Configuration注解完成。
这里就不做详细解释,详情可以参考
SpringMvc解决跨域问题 - 王念博客 - 开源中国社区
相关文章推荐
- JSONP跨域请求实例详解
- JS JSONP跨域请求实例详解
- JSONP跨域请求实例详解
- 详解java 中Spring jsonp 跨域请求的实例
- AJAX 跨域请求 - JSONP获取JSON数据(详解-示例)
- 跨域请求jsonp详解
- jsonp跨域请求详解
- AJAX 跨域请求 – JSONP的使用,PHP实例详解
- AJAX 跨域请求 - JSONP获取JSON数据(详解-示例)
- 详解Java Ajax jsonp 跨域请求
- jsonp详解跨域请求
- 使用jquery的jsonp如何发起跨域请求及其原理详解
- 详解SpringBoot多跨域请求的支持(JSONP)
- JavaScript用JSONP跨域请求数据实例详解
- 跨域请求之二:jsonp详解
- js&jquery跨域详解jsonp,jquery并发大量请求丢失回调bug
- AJAX 跨域请求 – JSONP的使用,PHP实例详解
- jsonp跨域请求详解
- 跨域请求之JSONP 一
- AJAX(XMLHttpRequest)进行跨域请求方法详解(一)