js跨域取数据问题


原文链接:http://sonyfe25cp.iteye.com/blog/609725

------------------------------------------------------------------------------------------------------------------------------------

关于ajax跨域取数据,有很多解决办法。但多数都是具体情况具体对待,没有统一的完美解决方案。

本文包括两种ajax跨域的解决方案,第一种是用servlet屏蔽掉跨域,具体获取数据由servlet完成,ajax跟平时并无不同。第二种方式由jquery提供的jsonp来完成,内部原理是利用script标签的src无跨域限制来实现的,具体解释可以参看相关同类文章,后文只是对使用过程中发现的注意事项略作记述。

两种方案,servlet解决的比较好,但是略显笨重,耦合度稍高,jsonp比较轻易,但只支持get方式请求,部分情况下可能无法满足需求,而且不支持ajax的同步处理,即async:false属性对jsonp无效。

-------------------------------------------------------------------------------------------------------------------------------------

问题描述:
1.根据已知的url,获取url中的id,然后拼接出另一个url,去获取该id对应的值。
举例:
已知url:http://video.guoshi.com/play/index/4b6a3c233b4cb.html?peixun=1&start=680000
获取id 为:4b6a3c233b4cb
拼接的url:http://video.guoshi.com/rest-video?id=4b6a3c233b4cb
2.通过浏览器可以观察到上面url的内容是:

Java代码   收藏代码
  1.  <?xml version="1.0" encoding="utf-8" ?>   
  2. lt;packet version="1.0.0">  
  3.  <status>success</status>   
  4. <data>  
  5. <item>  
  6.  <id>4b6a3c233b4cb</id>   
  7.  <count_view>43</count_view>   
  8.  <updated>2010-03-04 17:08:28</updated>   
  9.  </item>  
  10.  </data>  
  11.  </packet>  

3.目标就是取到这个xml中的<count_view>43</count_view>的41
4.采用jQuery的ajax实现.

问题:这个url跟我的系统不是同一个域.涉及到了ajax的跨域问题.由于不能通过修改用户IE的 Internet选项-安全-自定义安全-跨域浏览资源 启用 ,所以这个问题就显得棘手了。

5.思路:
1)自己做一个servlet,让ajax访问自己的servlet来获取这个xml.
2)servlet接收id参数.然后输出对应的xml
3)servlet中采用java的HttpURLConnection来获取原地址的源代码,然后输出.
4)注意设置编码utf-8,类型text/xml

6.servlet:GetClickNum
Java代码   收藏代码
  1. public void doPost(HttpServletRequest request, HttpServletResponse response)  
  2.             throws ServletException, IOException {  
  3.   
  4.           
  5.         String id=request.getParameter("id");  
  6.         String url="http://video.guoshi.com/rest-video?id="+id;  
  7.         String curLine = "";  
  8.         String content = "";  
  9.         URL server=new URL(url);  
  10.         HttpURLConnection connection = (HttpURLConnection) server.openConnection();  
  11.         connection.connect();  
  12.         InputStream is = connection.getInputStream();  
  13.         BufferedReader reader = new BufferedReader(new InputStreamReader(is));  
  14.         while ((curLine = reader.readLine()) != null) {  
  15.             content = content + curLine + "";  
  16.         }  
  17.         is.close();  
  18.         response.setContentType("text/xml");  
  19.         response.setCharacterEncoding("utf-8");  
  20.           
  21.         ServletOutputStream   out = response.getOutputStream();  
  22.         out.print(content);  
  23.     }  

这样原来的 http://video.guoshi.com/rest-video?id=4b6a3c233b4cb
就转换成 /GetClickNum?id=4b6a3c233b4cb
跨域问题解决!

7.js
Java代码   收藏代码
  1. $('#rows').find('li').each(function(){  
  2.         var url=$(this).find('a[id=videoUrl]').attr('href');  
  3.         var b=url.lastIndexOf('index');  
  4.         var e=url.lastIndexOf('.');  
  5.         var id= url.substring(b+6,e); //the id  
  6.         var $li=$(this);  
  7.         $.ajax({  
  8.             type:"POST",  
  9.             url :"GetClickNum",  
  10.             data:"id="+id,  
  11.             timeout:10000,  
  12.             success : function(xml) {  
  13.                     var val=$(xml).find("data>item>count_view").text();  
  14.                     $li.find('b[id=click]').html("点击量:"+val);  
  15.                     //alert(val);  
  16.                 }  
  17.             });  
  18.     });  


总结:
本文解决ajax跨域问题的思路就是将跨域变成不跨域.将对方服务器的servlet功能由自己的servlet来实现!

---------------------------------------------------------------------------------------------

在采用该方法的时候,遇到的一个问题是乱码。原因是BufferedReader默认采用iso-8859-1的编码方式进行读取数据,而如果发送端的编码不是该种编码(比如utf-8),那么便会产生乱码问题,解决办法是在创建这个reader的时候指定编码,方式是 BufferedReader reader = new BufferedReader(new InputStreamReader(is,"utf-8"));  还有一个问题是采用ServletOutputStream 进行输出数据时也报了一个异常,java.io.CharConversionException: Not an ISO 8859-1 character:也是默认编码的问题,正好是servlet,改成PrintWriter out = response.getWriter(); out.print(content);进行输出即可,当然别忘了关掉这个out流。

还有值得注意的是,这么输出的实际是一个文本类型也就是字符串,具体怎么处理就看js怎么写了。

ps:这么解决的好处是屏蔽了跨域,也无需考虑浏览器的差异。


/

以上内容为某位前辈所作,的确很好的解决了跨域问题。但该方法需在请求发起端写一servlet,获取数据由servlet来完成,显得有些麻烦。相对来说,jsonp不失为这一遗憾的一种补充。

jsonp是由jquery支持的一种“数据格式”,其实并不是数据格式,具体原理网上都有介绍,是在页面上利用script标签的src属性进行的,需要注意的是后台的数据返回处理跟同步问题,下面贴代码:

js部分:

 $.ajax({
			type:"GET",
			url: "http://"+adServer+":"+port+"/ad/AD2.xhtml?action=show_ad",
			data: "name="+panel_name+"&"+new Date(),
			dataType: "jsonp",
			cache:false,
			success: function(ad_){
		 		operate(ad_);//由于jsonp不支持ajax同步获取数据,故后续操作在此处理
			},
			error:function(data){
				alert("error happened");
			}
		});
后台java部分:
public void show_ad(HttpServletRequest request,
			HttpServletResponse response){
		 String callback = request.getParameter("callback");  
		 PrintWriter out = null;
		try {
			out = response.getWriter();
			out.print(callback+"("+JsonUtil.list2json(this.getAdService().show_ad((HashMap)this.getParams(request)))+");");
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			out.flush();
			out.close();
		}

		
	}
项目中的部分代码,可以运行,相关其它部分作省略处理。
**当时无意中发现该功能需要做跨域处理,由于之前用过servlet的那种处理方案,所以很想用那个,但有同事提出说jsonp可以跨域,于是按照资料进行模仿,结果每次都不成功,返回error,经查明为后台返回数据时不正确,跟正常情况略有不同,需加callback。
**另:由于当时js代码的结构设计,想先ajax在success获取到需要的数据data,然后将data赋值给某个局部变量,再return给外边的变量,但始终未成功。经排查为同步问题,查阅资料发现jsonp不支持同步设置,jquery源码这样解释:


async
Default: true

By default, all requests are sent asynchronously (i.e. this is set to true by default). If you need synchronous requests, set this option to false.Cross-domain requests anddataType: "jsonp" requests do not support synchronous operation. Note that synchronous requests may temporarily lock the browser, disabling any actions while the request is active.

结束

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值