跨域解决方案之一---->JQuery.Ajax JSONP解决跨域访问

6 篇文章 0 订阅
5 篇文章 0 订阅

     出于安全方面的考虑,各大浏览器都使用同源策略,禁止跨域访问。所谓同源策略,简单地说,就是要求动态内容(如JavaScript)只能阅读与之同源的那些HTTP应答和cookies,而不能阅读来自不同源的内容。同源的判断,应该把握住 协议、域名和端口,只有同协议、同域名、同端口才可以算的上是同源,只要这三者中有一个不同,则两个源就属于不同的源,两者之间的访问则属于跨域访问。关于同源与非同源的判断,可以参照下表(from http://blog.sina.com.cn/s/blog_62d3ddc00101al1b.html)


特别注意两点:
第一,如果是协议和端口造成的跨域问题“前台”是无能为力的,
第二:在跨域问题上,域仅仅是通过“URL的首部”来识别而不会去尝试判断相同的ip地址对应着两个域或两个域是否在同一个ip上。

“URL的首部”指window.location.protocol +window.location.host,也可以理解为“Domains, protocols and ports must match”。

       同源策略虽然在安全性方面起到了很大的作用,但是在开发的工程中,也不可避免地会需要跨域访问资源。如目前在很多大型Web项目的开发中,为了应对大并发,常常会采取前后端分开部署,这样就涉及到跨域访问的问题。JSONP是目前应用比较广泛的一种跨域解决方案。JSONP的核心思想是利用JS标签的src属性不受跨域限制进行跨域访问的。其主要执行过程可以总结为:首先在客户端注册一个回调函数,然后把回调函数的名字传给服务器;服务器端将要返回给客户端的数据生成为json格式,同时获取到客户端传过来的回调函数的名字,将要传递的json数据以实参的方式,放到回调函数中,然后将组合成的数据返回给客户端,这样返回给客户端的数据格式则形如:回调函数名(data);客户端则会解析返回的数据,执行预先定义好的回调函数。
        JQuery.Ajax中使用JSONP很简单,只需要指定datatype为jsonp格式,至于回调函数,可以采用默认形式,JQuery会自动生成随机函数名,并以默认参数名callback=函数名附加在请求的url后,当然,也可以通过jsonp和jsonpcallback自己定义回调函数的参数名和回调函数名称,这两个参数含义如下(w3c):

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

        jsonp
        类型:String
       在一个 jsonp 请求中重写回调函数的名字。这个值用来替代在 "callback=?" 这种 GET 或 POST 请求中 URL 参数里的 "callback" 部分,比如 {jsonp:'onJsonPLoad'} 会导致将 "onJsonPLoad=?" 传给服务器。
       jsonpCallback
       类型:String
       为 jsonp 请求指定一个回调函数名。这个值将用来取代 jQuery 自动生成的随机函数名。这主要用来让 jQuery 生成度独特的函数名,这样管理请求更容易,也能方便地提供回调函数和错误处理。你也可以在想让浏览器缓存 GET 请求的时候,指定这个回调函数名。

---------------------------------------------------------
       在后端,只需要通过request.getParameter("callback")获取到回调函数名,并将数据封装成"回调函数名(data)"的形式返回即可,前端在收到返回结果后,若返回的数据格式正确,则调用success方法,对数据做相应处理,否则调用fail方法。

       下面是一个简单的示例,后端使用servlet实现,前端页面部署在http://localhost:8086/容器中,后端代码部署在http://localhost:8080/容器中,由于端口号不同,所以前端页面请求后端servlet时为跨域访问。

前端页面代码如下(部署在http://localhost:8086/):

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript"  src="js/jquery-1.11.1.min.js"></script>
<script type="text/javascript"  src="js/jquery.easyui.min.js"></script>
<script type="text/javascript">
	$(function(){
		$.ajax({
			type : "get",
			url : "http://localhost:8080/testApp/testServlet",
			dataType : "jsonp",
			success : function(data) {//客户端jquery预先定义好的callback函数,成功获取跨域服务器上的json数据后,会动态执行这个callback函数
				alert(JSON.stringify(data));
			},
			error : function() {//数据加载失败
				alert("fail");
				error.apply(this, arguments);
			}
		});
	
	})
</script>
</head>
<body>
	this is the first page.....
</body>
</html>

       上述页面发出的请求URL最后形如:

http://localhost:8080/testApp/testServlet?callback=jQuery111107367232164833695_1422853667572,回调函数设置采用JQuery的默认设置。

后端代码如下(部署在http://localhost:8080)

web.xml代码:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>testApp</display-name>
  <welcome-file-list>
    <welcome-file>/testServlet</welcome-file>
    <welcome-file>index.htm</welcome-file>
  </welcome-file-list>
  <servlet>
    <servlet-name>testServlet</servlet-name>
    <servlet-class>com.founder.servlet.TestServlet</servlet-class>
    </servlet>
  <servlet-mapping>
    <servlet-name>testServlet</servlet-name>
    <url-pattern>/testServlet</url-pattern>
  </servlet-mapping>
</web-app>

       servlet代码:

package com.founder.servlet;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.sf.json.JSONObject;
/**
 * 测试servlet
 */
public class TestServlet extends HttpServlet {

	private static final long serialVersionUID = 1L;

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		this.doPost(req, resp);
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		Map<String,String> map=new HashMap<String,String>();
		map.put("name", "sherry");
		JSONObject json=JSONObject.fromObject(map);
		String callback=req.getParameter("callback");//得到回调函数名
		String s=json.toString();
		resp.getWriter().write(callback+"("+s+")");//封装成 回调函数名(data)形式

	}

}

 

       使用jsonp方式解决跨域问题,编码简单,而且其兼容性很好,在一些古老的浏览器中都可以运行,不需要XMLHttpRequest或者ActiveX的支持,但是它只支持get请求,所以在应用上也有一定的局限性。


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值