rails与jsonp
涉及后台的东西,我也不敢保证对错,总之写出来如果有错望各位高人不吝赐教吧。跨域的需要大多数出于web2.0的mashup,如果我的网站想搞一个地图,但自己实现没有钱没有技术显然难度太大,这样可以利用google map,又如想加入天气预报,这样也可以调用yahoo网站提供的相关服务。这些服务常常是一些HTTP GET形式的API。那么我们就发起一个get请求就是,往往可以得到一段文本或xml,然后我们就可以搞鼓了……本文提到的jsonp,或许说动态JS标签更合适些,与上面提到的情形有些不同。上面的google,yahoo都不属性于你的东西,你只要传入URI外加几个参数,它就会返回一堆东西,然后你再用它们提供的代码加工一下。如本博客引用feedsky的服务,就是这种情况。由于这情况太简单,不在本文讨论范围内。我所说的情况是有两个网站,它们都是我们开发的。我们从一个网站发送请求,另一个网站接收请来,返回数据,交由原网站处理。发送的请求当然是get请求,就是普通动态加载JS文件,不过这JS文件是另一个网站生成的。看一下面代码:
<!doctype html> <html> <head> <meta http-equiv= "Content-Type" content= "text/html; charset=UTF-8" > <title>Demo by 司徒正美</title> <script type= "text/javascript" > //在原页设置函数体 function say(words) { alert(words); } </script> </head> <body> <!--在远程js文件上调用本地函数//--> <script src= "http://yabooo.org/remote.js" type= "text/javascript" ></script> </body> </html> |
JS文件很简单:
say( "司徒正美!" ) |
弹出司徒正美
一般认为这就是JSONP的原型,用一个以js文件作结尾的URL请求另一个域的服务器,然后让它把所需要的东西全部搞成一个JSON对象,作为本地函数的参数传入执行。下面的例子需要rails支持,有兴趣的可以看看。
设置控制器:
class FooController < ApplicationController def bar respond_to do |format| format.html format.js do render :update do |page| page << %{ say( "司徒正美!" ) } end end end end end |
设置layout:
#D:\demo\views\layouts <!doctype html> <html> <head> <meta http-equiv= "Content-Type" content= "text/html; charset=UTF-8" > <title>Demo</title> </head> <body> <h1>layout</h1> <%= yield %> </body> </html> |
设置视图:
#D:\polyline\app\views\foo\bar.html.erb <script type= "text/javascript" > //在原页设置函数体 function say(words) { alert(words); } </script> <!--在远程js文件上调用本地函数//--> <%= javascript_include_tag "/foo/bar.js" %> |
设置路由规则:
map.resources :foo , :collection => { :bar => :get } |
然后打开http://localhost:3000/foo/bar.html,就会看到alert了,证明调用成功。
下面是一个增强版,由于可怜的我没有网站与域名,姑且用另一个action冒充第二个网站吧,反正我们都知道JS文件是不受域名限制的,很完美地绕过所谓的同源策略。
class FooController < ApplicationController def bar end def laaa respond_to do |format| format.html format.js do render :update do |page| page << %{ say( " laaa" ) } end end end end end |
map.resources :foo , :collection => { :bar => :get , :laaa => :get } |
<script type= "text/javascript" > //在原页设置函数体 function say(words) { alert(words); } var url = "http://localhost:3000/foo/laaa.js" ; // URL of the external script // this shows dynamic script insertion var script = document.createElement( 'script' ); script.setAttribute( 'src' , url+ "?" +(+ new Date)); script.setAttribute( "charset" , "utf-8" ); // load the script document.getElementsByTagName( 'head' )[ 0 ].appendChild(script); </script> |
再修改一下,这次传入json做参数。rails在这方面做得很好,可以直接把从数据库取得的记录用to_json转换成JSON,不过我现在不需要这么复杂。
class FooController < ApplicationController def bar end def laaa respond_to do |format| format.html format.js do if params[ :jsonp ].present? callback = params[ :jsonp ] render :update do |page| page << %{ #{callback}({"a":"司徒正美","b":"RestlessDream"}) } end end end end end end |
<script type= "text/javascript" > //在原页设置函数体 function say(json) { alert(json.a+ " : " +json.b); } function jsonp(url,callback){ if (url.indexOf( "?" ) > - 1 ) url += "&jsonp=" +callback else url += "?jsonp=" +callback url += "&nocache=" +(+ new Date()); // prevent caching var script = document.createElement( "script" ); script.setAttribute( "src" ,url); script.setAttribute( "type" , "text/javascript" ); script.setAttribute( "charset" , "utf-8" ); document.getElementsByTagName( 'head' )[ 0 ].appendChild(script); } jsonp( "http://localhost:3000/foo/laaa.js" , "say" ) </script> |
这次会弹出司徒正美 : RestlessDream,当然现实的需要会很复杂,会对传回来的JSON进行深加工,很少会像这样对号入座。不过处理JSON总比处理XML好。有时可能加载N多JSON,那么后台就要设置更多的分支,前台动态生成的script标签也随之增加,那么我们加载完这些标签后,可以立即删除,这是没有问题的。
好了,这样就完了,更复杂更完善的东西结合Ajax再说吧。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义