Jsonp解决ajax的跨域问题
这次给大家带来Jsonp解决ajax的跨域问题,Jsonp解决ajax跨域问题的注意事项有哪些,下面就是实战案例,一起来看一下。
一、介绍
最近跨域问题比较多,而且自己刚好也看到这一块,就总结了一下,关于JSONP的东西百度的话东西确实很多,很多人都是复制别人的,如此下去,其实找的资料就那么几份,关键是我还看不懂,可能是能力问题吧,自己经过很多尝试,所以总结了一下,终究还是弄懂了皮毛。注意一点是,这里是用Jsonp解决ajax的跨域问题,具体的实现其实不是ajax。
1、同源策略
浏览器有一个很重要的概念——同源策略(Same-Origin Policy)。所谓同源是指,域名,协议,端口相同。不同源的客户端脚本(JavaScript、ActionScript)在没明确授权的情况下,不能读写对方的资源。
2、JSONP
JSONP(JSON with Padding)是JSON的一种”使用模式”,可用于解决主流浏览器的跨域数据访问的问题。由于同源策略,一般来说位于 server1.example.com 的网页无法与不是 server1.example.com的服务器沟通,而 HTML 的script 元素是一个例外。利用 <script> 元素的这个开放策略,网页可以得到从其他来源动态产生的 JSON 资料,而这种使用模式就是所谓的 JSONP。用 JSONP 抓到的资料并不是 JSON,而是任意的JavaScript,用 JavaScript 直译器执行而不是用 JSON 解析器解析。</p> <p style="text-align: left;"><span style="color: #ff0000"><strong>二、实践</strong></span></p> <p style="text-align: left;"><strong>1、模拟跨域请求</strong></p> <p style="text-align: left;">在本机弄两个tomcat,端口分别为8080,8888,也就满足了非同源的条件,那么要是从一个端口发送ajax去获取另外一个端口的数据,那么肯定会报跨域请求问题。</p> <p style="text-align: left;"><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/061/021/6aa998e4d2edca235a11c4aef7eb7a24-0.png" class="lazy" title="" alt="这里写图片描述"></p> <p style="text-align: left;">这里有两个项目,分别是jsonp(8080),other(8888),在jsonp项目中index.jsp如下:</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false"><%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <title>Insert title here</title> <script type="text/javascript" src="js/jquery.min.js"></script> <script type="text/javascript"> function jsonp_fun(){ $.ajax({ url:'http://localhost:8888/other/index.jsp', type:'post', dataType:'text', success:function(data){ console.log(data); } }); } </script> </head> <body> <input type="button" value="jsonp" onclick="jsonp_fun()"/> </body> </html></pre><div class="contentsignin">登录后复制</div></div> <p style="text-align: left;">other(8888)项目中index.jsp如下:// 因为jsp实际就是servlet,这里就用jsp代替servlet演示。</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false"><%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <title>Insert title here</title> <script type="text/javascript" src="js/jquery.min.js"></script> </head> <body> other domain </body> </html></pre><div class="contentsignin">登录后复制</div></div> <p style="text-align: left;">其实中上面看无非就是jsonp页面中点击按钮ajax去获取other页面中的数据。</p> <p style="text-align: left;">结果如下:chrome控制台</p> <p style="text-align: left;"><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/061/021/6aa998e4d2edca235a11c4aef7eb7a24-1.png" class="lazy" title="" alt="这里写图片描述"></p> <p style="text-align: left;">XMLHttpRequest cannot load http://localhost:8888/other/index.jsp. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access.</p> <p style="text-align: left;">以上提示就是指跨域问题,不能从8080这个域去访问8888域的资源。</p> <p style="text-align: left;"><strong>2、利用script标签去访问other域的js文件</strong></p> <p style="text-align: left;">由于<script>标签的src是支持跨域请求的。最常见的就是CDN服务的应用啦,比如我项目中,如果想用jQuery,但是就没有这个js文件,去下载要找很久,而且版本还不知道下的对不对,那么可以百度搜jquery cdn,我随便找一个,比如bootstrap的cdn:http://www.bootcdn.cn/jquery/,有很多版本供你选择,只要在项目中加上就行了,最大缺点的话就是你没网的话,就引入不到啦。</p> <p style="text-align: left;"><strong>2.1 在other根路径创建js/other.js文件,</strong>内容如下:</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">alert("this is other(8888) js");</pre><div class="contentsignin">登录后复制</div></div> <p style="text-align: left;"><strong>2.2 在jsonp/index.jsp中,加入script标签,引入other的js</strong></p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false"><script type="text/javascript" src="http://localhost:8888/other/js/other.js"></script></pre><div class="contentsignin">登录后复制</div></div> <p style="text-align: left;">进入http://localhost:8080/jsonp/index.jsp,会立马弹出alert,表示引入的js文件自动执行了,跨域请求js成功。</p> <p style="text-align: left;"><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/061/021/6aa998e4d2edca235a11c4aef7eb7a24-2.png" class="lazy" title="" alt="这里写图片描述"></p> <p style="text-align: left;"><strong>2.3 同样的,直接引用,会立马执行立马的alert</strong>,那么在other.js中写函数,同样jsonp/index.jsp中也能调用到,这点就不演示了,项目开发中大多都是这样做的,页面与js/css分离。</p> <p style="text-align: left;"><strong>2.4 另外说明一点,</strong>如果在other.js中有函数通过ajax调用8080中的东西,然后引入之后,调用这个函数,也是可以的,但是如果other.js中函数ajax调用8888的东西,引入之后,调用这个函数,同样是跨域的。</p> <p style="text-align: left;"><strong>3、script实现跨域请求</strong></p> <p style="text-align: left;"><strong>3.1 简单模拟服务器返回数据</strong></p> <p style="text-align: left;">将jsonp/index.jsp改成如下:这里注意引入的other.js的位置,是在函数getResult之后的,如果在它之前的话,会提示函数不存在。js加载顺序是从上开始,在之前调用没创建的,不能成功。注意这里是指引入的js文件,如果是同一个js文件或者当前页面的js中,先执行调用,然后再写函数也是没有问题的,但是如果先执行调用引入js文件中的函数,然后再引入js文件,就会提示函数不存在。</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false"><script type="text/javascript" src="js/jquery.min.js"></script> <script type="text/javascript" src="http://localhost:8888/other/js/other.js"></script>
然后other.js
getResult({"result":"this is other domain's data"});
也就是在jsonp/index.jsp页面写好函数,然后引入其他域的js传入参数去调用这个函数,这里的参数你可以先看做是其他域服务器的接口返回的数据。
刷新页面,效果当然是
弹出alert框,this is other domain's data
3.2 模拟接口访问
看到这里,你会不会还是想不懂,上面js弄啥的,传个死的数据,有什么实际意义吗?,其实script的src不仅可以接js的地址,还可以接servlet的地址,也就是http接口地址,所以接下来,懒得写servlet,这里还是写jsp当做接口,在other项目中新建other.jsp页面,内容如下:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <% String params = request.getParameter("params"); out.println("ajax cross success,the server receive params :"+params); %>
内容很简单,也就是接受一个params的参数,然后返回数据给调用者。
我们在jsonp/index.jsp中加上
<script type="text/javascript" src="http://localhost:8888/other/other.jsp?params=fromjsonp"></script>
看到这个地址,你是不是很熟悉,不熟悉的证明你用servlet用蠢了,jsp也是servlet,流程就是页面一加载的时候,script标签就会去发送请求,然后返回数据。那么我们刷新页面,看看效果。
Uncaught SyntaxError: Unexpected identifier
报错了,如上,然后代码有问题?No,点击错误,你会看到请求的东西也打印出来了,就是提示错误,表示这个东西浏览器不认识,其实是script不认识啦。
还不明白,那么你去页面加上如下内容,你看报不报错!!肯定报错
<script type="text/javascript"> ajax cross success,the server receive params : jsonp_param </script>
那么js不能解析,我们换一种思路,要是我们输出的是JSON字符串或者调用当前页面函数的字符串了,类似于3.1中返回的getResult({“result”:”this is other domain's data”});
所以改造一下,把other.jsp中的内容改成
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <% String params = request.getParameter("params"); //out.println("ajax cross success,the server receive params :"+params); out.println("getResult({'result':'"+params+"'})"); %>
别忘了,之前jsonp/index.jsp中我们定义了,那么加入引用之后,依然记得getResult函数与引入函数的先后顺序问题。
<script type="text/javascript" src="http://localhost:8888/other/other.jsp?params=fromjsonp"></script>
刷新页面,发现大工告成。
至此,大部分原理已经讲完了,还有一个问题,这里服务器返回的是getResult(xxx),其中这里的xxx可以当做是经过接口的很多处理,然后塞进去的值,但是这个getResult这个函数名,调用方与其他域服务器这一方怎么约定这个名字是一致的了,况且很多公司自己做服务的,别的公司的开发人员去调用,难道每个人都去那么公司去约定调用函数的名字?怎么可能,所以有人就想出来了一种解决方案,当然不是我~~,其实也很简单啦,也就是把回调的函数名字也一起传过去不就行了,所以代码如下:
<script type="text/javascript" src="http://localhost:8888/other/other.jsp?params=fromjsonp&callback=getResult"></script>
other.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <% String params = request.getParameter("params"); String callback = request.getParameter("callback"); // 经过该接口一系列操作,然后得到data,将data返回给调用者 String data = "{'result':'"+params+"'}"; out.println(callback + "("+data+")"); %>
代码很简单,也就是传递一个回调函数的参数名,然后经过该接口一系列操作,将返回数据,塞到回调函数里面,调用端的函数就得到了该接口的数据,也就是类似于ajax中succsss:function(data),然后处理data一样,这里的success回调函数,相当于上面的getResult函数。当然你也可以写的优雅一点,比如:
function CreateScript(src) { $("<script><//script>").attr("src", src).appendTo("body") } function jsonp_fun(){ CreateScript("http://localhost:8888/other/other.jsp?params=fromjsonp&callback=getResult") }
4、Jquery的JSONP
至此跨域请求的原理已经讲清楚了,但是仍然还有一个问题,总觉得这样用有点怪是不是,如果用jquery的话,调用就很简单了,其实jquery底层实现也是拼了一个script,然后指定src这种方式,跟上面讲的一样,只是jquery封装了一下,显得更加优雅,跟ajax调用方式差不多,所以容易记,代码如下:
<script type="text/javascript"> function getResult(data){ alert("through jsonp,receive data from other domain : "+data.result); } function jsonp_fun(){ $.ajax({ url:'http://localhost:8888/other/other.jsp', type:'post', data:{'params':'fromjsonp'}, dataType: "jsonp", jsonp: "callback",//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(一般默认为:callback) jsonpCallback:"getResult",//自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名,也可以不写这个参数,jQuery会自动为你处理数据 success: function(data){ }, error: function(){ alert('fail'); } }); } </script> <body> <input type="button" value="jsonp" onclick="jsonp_fun()"/> </body>
这里的jsonCallback,回调函数设置为getResult,那么返回后会先调用getResult函数中的代码,再调用success函数中的代码,一般情况下,不用定义getResult函数,同样jsonCallback不需要设置,那么就只执行success中的代码,也就跟平时的ajax一样用啦。
所以实际工作用法如下:
function jsonp_fun(){ $.ajax({ url:'http://localhost:8888/other/other.jsp', type:'post', data:{'params':'fromjsonp'}, dataType: "jsonp", jsonp: "callback",//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(一般默认为:callback) success: function(data){ alert("through jsonp,receive data from other domain : "+data.result); }, error: function(){ alert('fail'); } }); } <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <% String params = request.getParameter("params"); String callback = request.getParameter("callback"); // 经过该接口一系列操作,然后得到data,将data返回给调用者 String data = "{\"result\":\""+params+"\"}"; out.println(callback + "("+data+")"); %>
这里没有指定jsonpCallback,实际上jquery底层拼装了一个函数名,当然生成函数规则就没研究了。
补充:
1、ajax和jsonp这两种技术在调用方式上“看起来”很像,目的也一样,都是请求一个url,然后把服务器返回的数据进行处理,因此jquery和ext等框架都把jsonp作为ajax的一种形式进行了封装;
2、但ajax和jsonp其实本质上是不同的东西。ajax的核心是通过XmlHttpRequest获取非本页内容,而jsonp的核心则是动态添加

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

热门话题

标题:解决jQueryAJAX请求出现403错误的方法及代码示例403错误是指服务器禁止访问资源的请求,通常会导致出现这个错误的原因是请求缺少权限或者被服务器拒绝。在进行jQueryAJAX请求时,有时候会遇到这种情况,本文将介绍如何解决这个问题,并提供代码示例。解决方法:检查权限:首先要确保请求的URL地址是正确的,同时验证是否有足够的权限来访问该资

jQuery是一个流行的JavaScript库,用于简化客户端端的开发。而AJAX则是在不重新加载整个网页的情况下,通过发送异步请求和与服务器交互的技术。然而在使用jQuery进行AJAX请求时,有时会遇到403错误。403错误通常是服务器禁止访问的错误,可能是由于安全策略或权限问题导致的。在本文中,我们将讨论如何解决jQueryAJAX请求遭遇403错误

使用Ajax从PHP方法中获取变量是Web开发中常见的场景,通过Ajax可以实现页面无需刷新即可动态获取数据。在本文中,将介绍如何使用Ajax从PHP方法中获取变量,并提供具体的代码示例。首先,我们需要编写一个PHP文件来处理Ajax请求,并返回所需的变量。下面是一个简单的PHP文件getData.php的示例代码:

如何解决jQueryAJAX报错403的问题?在开发网页应用程序时,经常会使用jQuery来发送异步请求。然而,有时候在使用jQueryAJAX时可能会遇到错误代码403,表示服务器禁止访问。这种情况通常是由服务器端的安全设置所导致的,但可以通过一些方法来解决这个问题。本文将介绍如何解决jQueryAJAX报错403的问题,并提供具体的代码示例。一、使

使用PHP和Ajax构建自动完成建议引擎:服务器端脚本:处理Ajax请求并返回建议(autocomplete.php)。客户端脚本:发送Ajax请求并显示建议(autocomplete.js)。实战案例:在HTML页面中包含脚本并指定search-input元素标识符。

Ajax(异步JavaScript和XML)允许在不重新加载页面情况下添加动态内容。使用PHP和Ajax,您可以动态加载产品列表:HTML创建一个带有容器元素的页面,Ajax请求加载数据后将数据添加到该元素中。JavaScript使用Ajax通过XMLHttpRequest向服务器发送请求,从服务器获取JSON格式的产品数据。PHP使用MySQL从数据库查询产品数据,并将其编码为JSON格式。JavaScript解析JSON数据,并将其显示在页面容器中。点击按钮触发Ajax请求,加载产品列表。

为了提升Ajax安全性,有几种方法:CSRF保护:生成令牌并将其发送到客户端,在请求中添加到服务器端进行验证。XSS保护:使用htmlspecialchars()过滤输入,防止恶意脚本注入。Content-Security-Policy头:限制恶意资源加载,指定允许加载脚本和样式表的来源。验证服务器端输入:验证从Ajax请求接收的输入,防止攻击者利用输入漏洞。使用安全Ajax库:利用jQuery等库提供的自动CSRF保护模块。

如何利用Ajax函数实现异步数据交互随着互联网和Web技术的发展,前端与后端之间的数据交互变得十分重要。传统的数据交互方式,如页面刷新和表单提交,已经不能满足用户的需求。而Ajax(AsynchronousJavaScriptandXML)则成为了实现异步数据交互的重要工具。Ajax通过使用JavaScript和XMLHttpRequest对象,使得网
