平时工作中经常被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。
<!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>
<!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打印信息
" data-src="https://user-gold-cdn.xitu.io/2018/12/2/1676f2f4ec55c056?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="758" data-height="42" />
上面是以window.location
跳转的方式获取window.name
字符串信息,平时开发中经常需要异步获取,请继续往下看:
<!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>
<!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
进行跨域操作
<!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="width:600px;height:70px;"/>
<br>
<input id="btn" type="button" value="获取9393数据" onclick="getData();" style="width: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>
<!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打印信息
成功获取非同源数据,将非同源地址嵌入获取数据页面窗口。
4.Java解决跨域问题
通过客户端页面的ajax
异步请求同源页面,再通过Java
的HttpURLConnect
或者HttpClient
进行转换即可,此处就不再赘述。
还有一种就是设置服务端的Header
,公司产品ggly
的api
就是这么处理的。
5.参考资料
《JavaScript权威指南》
作者:蟹丸
来源:掘金
文章评论