平时工作中经常被JavaScript跨域问题所困扰,其实有很多种解决方式,下面给大家介绍常用的几种:
1.jsonp解决跨域问题
客户端代码:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>jsonp-跨域</title> <script type="text/javascript" src="resources/js/jquery-1.8.3.min.js"></script> <script type="text/javascript"> function callbackFn(data){ data = typeof data != 'string' ? JSON.stringify(data) : data; console.log('callback:'+data); } function jsonpFn(){ $.ajax({ type:"get", dataType:"jsonp", url:"http://localhost:9393/ccy_server/server.jsp", jsonpCallback:"callbackFn", success:function(data){ data = typeof data != 'string' ? JSON.stringify(data) : data; console.log('success.data:'+data); } }); } function ajaxFn(){ var xmlhttp = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP"); var url = "http://localhost:9393/ccy_server/server.jsp"; xmlhttp.onreadystatechange = function(){ if(xmlhttp.readyState==4){ if(xmlhttp.status==200){ callbackFn(xmlhttp.responseText); } } } xmlhttp.open('GET',url,true); xmlhttp.send(null); } ajaxFn(); //jsonpFn(); </script> </head> <body> </body> </html>
服务端代码:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <% String result = "{"name":"ccy","age":18,"info":{"address":"wuhan","interest":"playCards"}}"; out.println("callbackFn("+result+")"); %>
相信大家对此种方式并不陌生,需要引用jquery库文件,并且要与服务端进行协调处理。
我先写了个简单的ajax调用非同源的异步请求直接报错
执行jsonpFn方法
成功获取服务端信息!
2.window.name解决跨域问题
在客户端浏览器中每个页面都有一个独立的窗口对象window,默认情况下window.name为空,在窗口的生命周期中,载入的所有页面共享一个window.name并且每个页面都有对此读写的权限,window.name会一直存在当前窗口,但存储的字符串不超过2M。
http://localhost:8383/ccy_client/window_name.html代码
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>window.name-跨域</title> <script type="text/javascript"> window.name = "我是 window.name 字符串"; setTimeout(function(){ window.location = "http://localhost:9393/ccy_server/window_name.html"; },2000); </script> </head> <body> </body> </html>
http://localhost:9393/ccy_server/window_name.html代码
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>window.name-跨域</title> <script type="text/javascript"> var str = window.name; console.log('ccy_server.window_name:'+str); </script> </head> <body> </body> </html>
chrome打印信息
上面是以window.location跳转的方式获取window.name字符串信息,平时开发中经常需要异步获取,请继续往下看:
http://localhost:8383/ccy_client/window_name_iframe.html代码
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>window.name-跨域</title> </head> <body> <script type="text/javascript"> var boo = false; var iframe = document.createElement('iframe'); var loadData = function() { if (boo) { var data = iframe.contentWindow.name; //获取window.name console.log(data); //销毁数据 iframe.contentWindow.document.write(''); iframe.contentWindow.close(); document.body.removeChild(iframe); } else { boo = true; iframe.contentWindow.location = ""; // 设置的代理文件,iframe重新载入 } }; iframe.src = 'http://localhost:9393/ccy_server/window_name_iframe.html'; if (iframe.attachEvent) { iframe.attachEvent('onload', loadData); } else { iframe.onload = loadData; } document.body.appendChild(iframe); </script> </body> </html>
http://localhost:9393/ccy_server/window_name_iframe.html代码
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>window.name-跨域</title> <script type="text/javascript"> window.name = '我是 http://localhost:9393/ccy_server/window_name_iframe.html'; </script> </head> <body> </body> </html>
chrome打印信息
成功获取非同源地址的数据信息,主要是通过iframe的src属性,类似含有src属性的标签都可以成功处理跨域问题(img,script)
3.postMessage解决跨域问题
h5新特性,window.postMessage(msg,targetOrigin);
msg:传入的字符串信息
targetOrigin:目标源(协议主机端口有效)
同样借助iframe进行跨域操作
http://localhost:8383/ccy_client/postMessage.html代码
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>postMessage-跨域</title> </head> <body> <iframe id="ifr" src="http://localhost:9393/ccy_server/postMessage.html" style="display: none;"></iframe> <br> <input id="txt" type="text" style="600px;height:70px;"/> <br> <input id="btn" type="button" value="获取9393数据" onclick="getData();" style="180px;height:60px;"/> <script type="text/javascript"> var data; function handleMsg(e){ e = e || event; data = e.data; console.log('8383:'+e.data); } if(window.addEventListener){ window.addEventListener('message', handleMsg); }else{ window.attachEvent('onmessage', handleMsg); } function getData(){ document.getElementById('txt').value=data; var msg = 'http://localhost:8383/ccy_client/postMessage.html'; window.frames[0].postMessage(msg, 'http://localhost:9393'); } </script> </body> </html>
http://localhost:9393/ccy_server/postMessage.html代码
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>postMessage-跨域</title> </head> <body> <script type="text/javascript"> function handleMsg(e){ e = e || event; console.log('9393:'+e.data); } if(window.addEventListener){ window.addEventListener('message', handleMsg); }else{ window.attachEvent('onmessage', handleMsg); } window.onload = function(){ var msg = '我是 http://localhost:9393/ccy_server/postMessage.html'; window.parent.postMessage(msg, 'http://localhost:8383'); } </script> </body> </html>
chrome打印信息
点击“获取9393数据”
成功获取非同源数据,将非同源地址嵌入获取数据页面窗口。
4.Java解决跨域问题
通过客户端页面的ajax异步请求同源页面,再通过java的HttpURLConnect或者HttpClient进行转换即可,此处就不再赘述。
还有一种就是设置服务端的Header,我们果果乐园新版的api就是这么处理的。
5.参考资料
https://www.sojson.com/blog/121.html
https://www.jianshu.com/p/43ff69d076e3
JavaScript权威指南
欢迎纠错~~~