AJAX跨域访问
来源:互联网 发布:pl2303hx数据手册 编辑:程序博客网 时间:2024/05/22 10:45
谈到js跨域访问,首先要了解的一个概念,就是同源策略。所谓同源是指域名、协议、端口相同。不同源的客户端脚本(javascript、ActionScritp)在没明确授权的情况下,不能读写对方的资源。简单的来说,就是浏览器仅允许包含在A页面的脚本访问与他同域名下的页面或者服务器资源(如service,action,servlet,js脚本等),不同域名下的脚本不能互相访问,即便是子域也不行。它是由Netscapte提出的一个著名的安全策略,现在所有的支持JavaScript的浏览器都会使用这个策略。
如果我们需要不同域名下的脚本互相访问的话,由于同源策略的限制,直接访问肯定不行。这样,就涉及到了跨域访问的问题。如何解决跨域访问问题呢?这里提供三个方案。
- 采用JSONP跨域GET请求是一个常用的解决方案。
- 用服务端的XmlHttpRequest代理实现跨域访问
- 基于iframe(一般用于父域子域之间的跨域)
JSONP方式实现跨域请求
JSONP工作原理:由于同源策略的限制,XmlHttpRequest只允许请求当前源(域名、协议、端口)的资源。若要跨域请求出于安全性的考虑是不行的。但是我们发现,Web页面上调用js文件时则不受是否跨域的影响,而且拥有“src”这个属性的标签都具有跨域的能力,比如<script>、<img>、<iframe>。如果通过使用html的script标记来进行跨域请求,并在响应中返回要执行的script代码,其中可以直接使用JSON传递javascript对象。即在跨域的服务端生成JSON数据,然后包装成script脚本回传,就突破了同源策略的限制,解决了跨域访问的问题。
JSONP的缺点:JSONP不提供错误处理。如果动态插入的代码正常运行,你可以得到返回,但是如果失败了,那么什么都不会发生。demo1
客户端代码
<!DOCTYPE html><html> <head> <meta charset="utf-8" /> <title>客户端</title> <script type="text/javascript" src="js/jquery-1.11.1.min.js"></script> <script type="text/javascript"> function SendData(){ $.ajax({ type:"get", url:"http://127.0.0.1:8080/WebTest/doTestServer", dataType:"jsonp", jsonp:"callback", //传递给请求处理程序或页面的,用以获得jsonp回调函数名 //的参数名(一般默认为callback)不需要改动 jsonpCallback:"clientreceive",//自定义的jsonp回调函数名称, //默认为jQuery自动生成的随机函数名,也可以写“?”,jQuery会自动为你处理数据 //执行成功后执行的方法,此方法在clientreceive方法之后执行 success:function(data){ alert(data.name); }, error:function(data){ alert("出错了!"); } }); } //将服务端返回的数据封装成相应的js文件 functionclientreceive(data){ alert(data.age); } </script> </head> <body> <input type="button" value="提交" onclick="SendData();"/> </body></html>
服务端代码:(此demo服务端用servlet实现)
public class testService extends HttpServlet{ @Override protectedvoiddoGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException { resp.setContentType("application/json;charset=utf-8"); Stringcallback = req.getParameter("callback"); Stringjson = " ({'name':'张三','age':'20'})"; resp.getWriter().write(callback+ json);//注意此处输出的数据格式 }}
用服务端的XmlHttpRequest代理实现跨域访问
我们不能在浏览器端直接使用AJAx来跨域访问资源,但是在服务端是没有这种跨域安全限制的。所以,我们只需要让服务器端帮我们完成“跨域访问”的工作,然后在浏览器端用AJAX获取服务端“跨域访问”的结果就可以了。
客户端js代码
<span style="font-size:14px;">function SendData(){ $.ajax({ type:"get", url:"doServiceProxy", success:function(res){ varsubval=res.substring(res.indexOf("(")); //返回的参数名 varcallfunc=res.substring(0,res.indexOf("(")); //返回的数值 var json = (new Function("return "+ subval))(); //转换为json格式 if($.trim(callfunc)=='clientreceive'){ clientreceive(json);//调用回调方法,将返回的数值封装成相应的文件 } alert(json.name); alert(json.age); }, error:function(res){ alert("失败"); } }); } //将服务端返回的数据封装成相应的js文件 functionclientreceive(data){ alert("处理服务端数据"); }</span>
本地服务端代码(跨域代理)
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader; import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse; import org.apache.http.HttpEntity;import org.apache.http.HttpResponse;import org.apache.http.client.HttpClient;import org.apache.http.client.methods.HttpGet;import org.apache.http.impl.client.DefaultHttpClient;@SuppressWarnings("deprecation")publicclassserviceproxy extends HttpServlet{ privatestaticfinallongserialVersionUID= -2007067084377015151L; @Override protectedvoiddoGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException { HttpClientclient=newDefaultHttpClient(); HttpGethttpgets=newHttpGet("http://127.0.0.1:8080/WebTest/doTestServer?callback=clientreceive"); HttpResponseresponse=client.execute(httpgets); HttpEntityentity=response.getEntity(); if(entity!=null){ InputStreaminstreams=entity.getContent(); Stringstr=convertStreamToString(instreams); resp.getWriter().write(str); } } //将流转换为字符串 publicstatic StringconvertStreamToString(InputStream is){ BufferedReaderreader=newBufferedReader(newInputStreamReader(is)); StringBuildersb=newStringBuilder(); Stringline=null; try{ while((line=reader.readLine())!=null){ sb.append(line+"\n"); } }catch(Exception e){ e.printStackTrace(); }finally{ try{ is.close(); }catch(Exception e){ e.printStackTrace(); } } return sb.toString(); } @Override protectedvoiddoPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException { doGet(req,resp); }}
远程服务端(最终要访问的跨域服务端)与demo1服务端代码一致。
基于iframe实现跨域访问demo(一般用于父域子域之间的跨域)
基于iframe实现的跨域要求两个域具有aa.xx.com,bb.xx.com这种特点,也就是两个页面必须属于一个基础域(例如都是xxx.com或是xxx.com.cn),使用同一协议(例如都是http)和同一端口,这样在两个页面中同时添加document.domain,就可以实现父页面调用子页面的函数。
页面一:
<html> <head> <script> document.domain = "xx.com"; function aa(){ alert("p"); } </script> </head> <body> <iframe src="http://localhost:8080/CmsUI/2.html"id="i"> </iframe> <script> document.getElementById('i').onload = function(){ var d = document.getElementById('i').contentWindow; d.a(); }; </script> </body> </html>
页面2
<html> <head> <script> document.domain = "xx.com"; function a(){ alert("c"); } </script> </head> <body> </body> </html>
参考资料:http://blog.csdn.net/wangxiaohu__/article/details/7294842
- Ajax跨域访问
- ajax跨域访问?
- Ajax跨域访问
- ajax跨域访问
- ajax跨域访问
- ajax跨域访问
- AJAX跨域访问
- AJAX跨域访问
- Ajax跨域访问
- ajax跨域访问
- Ajax跨域访问
- ajax跨域访问
- Ajax 跨域访问
- ajax跨域访问
- ajax跨域访问
- AJAX-跨域访问
- ajax 跨域访问
- ajax 跨域访问
- 配置IntelliJ IDEA 13的SBT和Scala开发环境
- Unix时间戳(Unix timestamp)转换
- 文件上传时判断是否为图片
- Android 性能优化
- C++面试笔试题目(选2)(字符串,原码反码补码)
- AJAX跨域访问
- 第十一周项目1层次遍历算法的验证
- lua table访问的元方法
- POJ 2288 Islands and Bridges 状态压缩DP
- category添加成员变量
- Java将Unix时间戳转换成指定格式日期
- Java基础面试题笔记(2)
- 每天00:00:01循环执行定时任务
- iOS多线程GCD