跨域问题的解决方案
认识JSONP
<script src="ajax.js"> </script>
<script>
$.get('http://bbs.com/1.php',function(){});
</script>
ajax 请求的URL地址,不在当前域名下,就会出现一下错误:
同源策略,也叫跨域禁止策略;
阻止从一个域上加载的脚本,获取或操作另一个域上的资源;
内部系统的数据交互可能因此无法进行:
而Web页面上调用js文件时则不受是否跨域的影响
(不仅如此,我们还发现凡是拥有”src”这个属性的标签都拥有跨域的能力,比如script、img、iframe);
src 的能力就是把远程的数据资源加载到本地(图片、JS代码等);
前台代码:
<script src="ajax.js"> </script>
<script>
//提前写好函数,调用函数需要传参
function cb(msg){
console.log(msg);
}
</script>
<!--src加载进来的代码就是一个JS的函数调用,cb函数调用 -->
<script src="http://bbs.com/1.php"></script>
后台PHP代码:
$arr = ['a'=>1,'b'=>'san','c'=>'wu','d'=>4];
$str = json_encode($arr);
//返回字符串,JS代码的函数调用
//要返回的数据作为函数传参传递
echo "cb(".$str.")";
修改前后台代码,增加灵活性;
前台代码:
<script src="ajax.js"> </script>
<script>
//提前写好函数,调用函数需要传参
function callback(msg){
console.log(msg);
}
</script>
<!--src加载进来的代码就是一个JS的函数调用,cb函数调用 -->
<!--地址get传参,告知后台函数调用名称 -->
<script src="http://bbs.com/1.php?cb=callback"></script>
PHP后端代码:
$arr = ['a'=>1,'b'=>'san','c'=>'wu','d'=>4];
$str = json_encode($arr);
//返回字符串,JS代码的函数调用
//要返回的数据作为函数传参传递
//接受参数拼接,作为函数调用名称
echo $_GET['cb']."($str)";
JAVA后端代码
import net.sf.json.JSONObject;
public void exchangeJson(HttpServletRequest request,HttpServletResponse response) {
try {
response.setContentType("text/plain");
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
Map<String,String> map = new HashMap<String,String>();
map.put("result", "content");
PrintWriter out = response.getWriter();
JSONObject resultJSON = JSONObject.fromObject(map); //根据需要拼装json
String jsonpCallback = request.getParameter("cb");//客户端请求参数
out.println(jsonpCallback+"("+resultJSON.toString(1,1)+")");//返回jsonp格式数据
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
如何使用JSONP
<body>
<input type="button" value="获取" id="btn">
</body>
<script>
document.getElementById('btn').onclick = function () {
var sc = document.createElement('script');
sc.src = "./0.3.php?callback=b&url=http://bbs.com/19.php";
sc.id='hh';
var head = document.getElementsByTagName('head')[0];
head.appendChild(sc);
var script = document.getElementById('hh');
head.removeChild(script);
}
function b(data){
var d = JSON.parse(data);
console.log(d);
}
</script>
就是在远程服务器上设法动态的把数据装进js格式的文本代码段中,供客户端调用和进一步处理;
在前台通过动态添加script标签及src属性,表面看上去与ajax极为相似,但是,这和ajax并没有任何关系;
为了便于使用及交流,逐渐形成了一种 非正式传输协议,人们把它称作 JSONP ;
该协议的一个要点就是允许用户传递一个callback参数给服务端,
然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,
这样客户端就可以随意定制自己的函数来自动处理返回数据了。
跨域资源共享(CORS)机制
在后端代码中添加一下header头声明(HTML5响应头,老式浏览器可能会不兼容):
Access-Control-Allow-Origin:* //域名,* 允许所有
PHP服务端代码
header('Access-Control-Allow-Origin:http://localhost');
JAVA服务端代码
public void HttpServlet(ServletRequest request, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) resp;
response.setHeader("Access-Control-Allow-Origin", "*"); //解决跨域访问报错
response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600"); //设置过期时间
response.setHeader("Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept, client_id, uuid, Authorization");
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // 支持HTTP 1.1.
response.setHeader("Pragma", "no-cache"); // 支持HTTP 1.0.
response.setHeader("Expires", "0");
}