用JQuery中的方法实现跨域请求

1 篇文章 0 订阅
0 篇文章 0 订阅

服务器端代码如下:

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class Invoke extends HttpServlet{
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		try
		{
			 String jsons="[{\"addTime\":\"2011-09-19 14:23:02\",\"iccid\":\"1111\",\"id\":0,\"imei\":\"2222\",\"imsi\":\"3333\",\"phoneType\":\"4444\",\"remark\":\"aaaa\",\"tel\":\"5555\"}," +
             "{\"addTime\":\"2011-11-11 14:23:02\",\"iccid\":\"2222\",\"id\":0,\"imei\":\"2222\",\"imsi\":\"3333\",\"phoneType\":\"4444\",\"remark\":\"aaaa\",\"tel\":\"5555\"}]";
		resp.setContentType("text/javascript");  
        boolean jsonP = false;  
        String cb = req.getParameter("pursue"); 
        
        System.out.println(cb);
        if (cb != null) {  
            jsonP = true;  
            resp.setContentType("text/javascript");  
            System.out.print("js");
        } else { 
        //如果没有这个参数表示直接返回JSON数据就可以了
        	resp.setContentType("application/x-json");  
            System.out.print("json");
        }  
        resp.setCharacterEncoding("UTF-8");  
        PrintWriter out = resp.getWriter();  
        if (jsonP) {  
        //如果是JSON的数据格式,那么对这个jsonObject进行tostring操作
        //因为这个action没有返回物理视图,直接可以通过response对象进行返回数据
        //返回类型 callbackfunction(字符串)
            out.write(cb + "("+jsons+")");  
        }  
        else{  
            out.write("出错");  
        }  
	}catch (Exception e) {  
        e.printStackTrace();  
    }  
	}
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(req,resp);
	}
}
note:jsonp的出现是为了实现跨域资源共享的,这是在CORS出现之前的常用做法。他的本质是通过动态script来完成的,因为script有能力不受限制的从其它域中加载资源。

第一种方式:(通过script标签来实现)

   window.οnlοad=function()
       {
         //回调函数  
	   var url = "http://127.0.0.1:8080/sealJs/jsonp?pursue=callbackfunction";   
	    var script = document.createElement('script');   
	    script.setAttribute('src', url);  //load javascript     
	   document.getElementsByTagName('head')[0].appendChild(script);   
	} 
	 function callbackfunction(data){  
		alert(data[0].addTime);  
	}

 note:这是通过script标签,也就是标准的jsonp来完成的,但是很显然我们必须弄清楚,我们访问了服务器端的代码,必须通过服务器端明确指定返回来的是javascript类型才可以。服务器端核心代码: 

  String cb = req.getParameter("pursue"); 
        resp.setContentType("text/javascript");  
        out.write(cb + "("+jsons+")");  
note:服务器端先获取到回调函数callbackfunction,然后把要返回的json数据作为这个函数的参数,最后通过Content-Type告诉浏览器这是javascript类型, 也就是告诉浏览器这是可以直接执行的代码!通过chorme开发者工具,我们看到服务器返回的脚本已经被添加到head中了,不过这种回调是通过服务器来完成的,而不是通过 onload等事件来检测的。缺点:从其它域加载文件,如果其它于不安全,那么会带来恶意的代码;要确定jsonp请求失败不容易,虽然HTML5提供了script的onerror,但是浏览器支持并不好。
第二种方式:(通过jQuery本身的ajax方法来完成)

$(document).ready(function()
       {
        $.ajax({
	          type:"GET",  
	         url:"http://127.0.0.1:8080/sealJs/jsonp",  
		 jsonp:"pursue",
		jsonpCallback:"backInvoke",
		cache:false,
		 dataType:"jsonp"
          });
     });  
        function backInvoke(data)
       {
         console.log(data[0].addTime);
       }
note:这是通过ajax方法来完成的,但是这种方式和方式1,也就是动态创建script有什么区别? 答案是没有区别,jquery是通过 ajaxTransport来完成script的类型的加载的,他也是通过动态创建script来完成的!
第三种方法:通过getJSON来跨域:

    $(function(){  
       /*(1)因为getJSON底层调用的是ajax方法,所以这里不能明确指明回调函数jsonpCallback,否则就会去回调他
                但是getJSON没有这种用法
         (2)虽然底层调用了ajax方法,但是无法明确指定是jsonp请求,所以服务器端不会处理,所以这种情况下要跨域
                             必须给服务器添加ACCESS-CONTROL-ALLOW-ORIGION头
       */
		jQuery.getJSON("http://127.0.0.1:8080/sealJs/jsonp?pursue=?",function(data)
		{
		 console.log(data[0].addTime);
		});   
        });  
note:这里要必须注意,虽然底层调用了ajax方法, 但是我们无法指定jsonp请求,所以这种情况下要跨域必须具有access-control-allow-origion头部。
第四种方法:通过getScript来跨域

 function xx(data)
{
   console.log(data[0].addTime);
 }
   $(function()
   {
  $.getScript("http://127.0.0.1:8080/sealJs/jsonp?pursue=xx");
        
   })

note:底层仍然调用ajax方法,不过dataType是script,因此ajaxTransport中的处理不需要在服务器端明确指定access-control-allow-origion,因为script本来就可以跨域获取数据,所以他和第一种方式是完全相同的,和ajax方法也是完全相同的!但是getJSON方式调用ajax时候指定的dataType是"json",因此他无法实现跨域,所以要借助access-control-allow-origion!

CORS默认情况下是不发送凭证的,我们有时候需要发送凭证怎么处理:

$(function()
{
  $.ajax({
   url:"http://localhost:8080/CORS/cors",//这时候也必须指定access-control-allow-origion,因为我使用了虚拟地址,用的localhostme的域名进行访问的!
      xhrFields: {
      withCredentials: true//表示发送凭证,但测试结果表示只会发送jsessionid,普通的cookie不会发送!
   }
  });
})
note:这时候不管服务器端有没有access-control-allow-credential都会发送凭证给服务器, 但是经过测试,发送的数据只是服务器的session的cookie对象,而其它的cookie不会发送。服务器能够收到JSESSIONID,但是其它的cookie不会收到。如果服务器接受带凭证的请求,必须发送access-control-allow-origion,否则浏览器不会把数据交给javascript,结果就是responseText为空字符串,status为0,调用onerrror事件处理程序!

xhrFieldsObject类型1.5.1 新增

一个具有多个"字段名称-字段值"对的对象,用于对本地XHR对象进行设置。一对「文件名-文件值」在本机设置XHR对象。例如,如果需要,你可以用它来为跨域请求设置XHR对象的withCredentials属性为true。注意:指定了这个头以后会发送凭证sessionid,但是抓包工具并没有显示他!

headersObject类型1.5 新增

默认值:{}

以对象形式指定附加的请求头信息。请求头X-Requested-With: XMLHttpRequest将始终被添加,当然你也可以在此处修改默认的XMLHttpRequest值。headers中的值可以覆盖beforeSend回调函数中设置的请求头(意即beforeSend先被调用)。headers头将会添加如Access-Control-Request-Headers,Access-Control-Request-Method等头部信息。

总结:

(1)ajax方法指定dataType为jsonp,getScript的dataType是script,手动创建script加载远端数据这三个方法都是通过script可以跨域加载数据的天性来完成的。在服务器端通过返回数据类型为"text/javascript"来实现javascript代码在浏览器端直接执行!

(2)getJSON方法调用ajax方法时候指定的dataType是json,所以无法直接实现跨域,这时候就要借助于access-control-allow-origion来完成!

(3)带凭证的请求发送的方法为options方法,而不是get/post方法!当用户通过setRequestHeader自定义头部信息,浏览器默认先发送一个请求用于判断该请求是否合法,如果不通过ajax请求就直接失败了,如果通过了浏览器再次发送一个请求,读取服务器返回的数据。也就是options方法会进行两次请求。我们可以通过设置Access-control-max-age用于指定该请求缓存的时间,把请求的结果缓存起来,为此付出的第一次代价就是第一次请求的时候多发送了一次HTTP请求。通过setRequestHeader('X-Request-With', null)可以避免浏览器发送OPTIONS请求。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值