找回密码
 注册
搜索
查看: 2016|回复: 1

[讨论] Android平台上基于Rexsee实现的Ajax跨域访问,附原生源码

[复制链接]
发表于 2011-12-15 15:44:30 | 显示全部楼层 |阅读模式
在移动平台的WebApp开发中,跨域问题一直是一个比较重要的环节。尽管Ajax的跨域在某些层面带来了不少安全隐患,但同时也彻底放开了传统Ajax的限制。。目前大量的移动Web开发框架都已从不同角度提出了自己的解决方法,效果不一。。

本篇重点介绍Rexsee内置的Ajax对象,通过RexseeAjax对本地的页面进行动态注值,是不是很爽啊~

这就是我们使用Rexsee时可以使用的独特程序架构——B/C/S,即页面和资源文件本地化,通过ajax从服务器获取数据。
此种架构有3种好处:其一,页面读取和加载速度的优化。其二,流量的优化。其三,用户体验的优化。

先来了解一下rexseeajax对象。此对象包含3个方法和3个事件:前2个方法是异步取值,最后一个方法则是同步取值。事件的对应在手册中有相应的说明,这里就不再叙述了。

使用rexseeajax的时候需要注意:

在rexsee 提供的3个ajax对象函数中,submit和submitWithCallback函数在回调函数(事件)中返回的字串(response)是需要用unescape解码的,即直接alert(response)会看到乱码,需要alert(unescape(response))才可以看到正常的字串。但在syncSubmit函数中,返回字串则不需要unescape。

对于submit和syncSubmit,这两个函数是在读取数据的时候默认调用的旋转进度框,如果想在请求数据时不使用旋转进度框,那么我们需要使用submitWithCallback,当然我想使用其他进度框也可以在其的触发事件onAjaxProgressChanged中编写。

为什么要额外提到这里,因为在数据较多的情况下,使用带默认进度框的ajax方法会使得用户体验变得很不好,而使用没有进度框ajax方法,则可以自己定义用户等待的界面,比如一个GIF动画等等。同时,可以避免在页面切换时带来的延迟等待(因为我们一般都把页面本地化,页面的读取都是从本地读取,而数据获取则是从网络)。

大家现在来看个小例子:
图片:http://www.rexsee.com/imagecache/bbs/11-10-09/1318131354.png
图片:http://www.rexsee.com/imagecache/bbs/11-10-09/1318131430.png
图片:http://www.rexsee.com/imagecache/bbs/11-10-09/1318131487.png

无进度框代码
function checkLogin(){
       var name=document.getElementById('username').value;
       var password=document.getElementById('password').value;
   rexseeAjax.submitWithCallback('http://www.fuwu800.com/yezhenqing/ajaxTest/check.php','name='+name+'&password='+password,'gb2312');
       }
           function onAjaxReturned(ajaxUrl,response)
   {
               var temp=eval("("+unescape(response)+")");
               temp=temp.result;
       if(temp==1){
       rexseeBrowser.go('test.html');
       }else if(temp==0){
       rexseeDialog.alert('消息框','登录失败!');
       }
   }

有进度框代码
function checkLogin(){
       var name=document.getElementById('username').value;
       var password=document.getElementById('password').value;
    var temp=eval("("+    rexseeAjax.syncSubmit('http://www.fuwu800.com/yezhenqing/ajaxTest/check.php','name='+name+'&password='+password,'gb2312')+")");
               temp=temp.result;
       if(temp==1){
       rexseeBrowser.go('test.html');
       }else if(temp==0){
       rexseeDialog.alert('消息框','登录失败!');
      }
      }

通过ajax来检查我们的用户名和密码是否合法,合法的话进入数据页面,否则提示失败。数据页面获取代码:

无进度框代码
        rexseeAjax.submitWithCallback('http://www.fuwu800.com/yezhenqing/ajaxTest/a.html','','gb2312');
   function onAjaxReturned(ajaxUrl,response)
   {
       document.getElementById("contents").innerHTML="";
       var temp=unescape(response);
       var test=eval("("+temp+")");
       for(var i=0;i<test.length;i++){
       document.getElementById("contents").innerHTML+="<li>"+test.firstName+"."+test.lastName+"</li>";
       }
   }
   
   function  onAjaxProgressChanged(ajaxUrl,totalSize,downloadedSize){
    document.getElementById("contents").innerHTML="<li>Loading...</li>";
   }

有进度框代码
window.onRexseeReady=function(){

       document.getElementById("contents").innerHTML="";
       var test=eval("("+rexseeAjax.syncSubmit('http://www.fuwu800.com/yezhenqing/ajaxTest/a.html','','gb2312')+")");
       for(var i=0;i<test.length;i++){
       document.getElementById("contents").innerHTML+="<li>"+test.firstName+"."+test.lastName+"</li>";
       }
   
}

大家可以将数据页面的内容加大,看看在2中不用的请求形式下,等待程序的长短。那么以后自己的程序该如何去设计,都应该了然于胸了。
数据格式都是标准的json数据和数组,使用eval('('+json+')')方法转换为对象即可方便使用。

最后把RexseeAjax的源码贴出,供参考。。有点多~~
/*
* Copyright (C) 2011 The Rexsee Open Source Project
*
* Licensed under the Rexsee License, Version 1.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.rexsee.com/CN/legal/license.html
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package rexsee.core.transportation;  

import java.io.DataOutputStream;  
import java.io.InputStream;  
import java.net.HttpURLConnection;  
import java.net.SocketTimeoutException;  
import java.net.URL;  
  
public class RexseeAjax implements JavascriptInterface {  

       public static final String INTERFACE_NAME = "Ajax";  
       @Override  
       public String getInterfaceName() {  
               return mBrowser.application.resources.prefix + INTERFACE_NAME;  
       }  
       @Override  
       public JavascriptInterface getInheritInterface(RexseeBrowser childBrowser) {  
               return new RexseeAjax(childBrowser);  

       public static final String EVENT_ONAJAXPROGRESSCHANGED = "onAjaxProgressChanged";  
       public static final String EVENT_ONAJAXRETURNED = "onAjaxReturned";  
       public static final String EVENT_ONAJAXTIMEOUT = "onAjaxTimeout";  

       public static final int AJAX_PROGRESS_DONE = 1;  
       public static abstract class AjaxProgressListener {  
               public abstract void run(String ajaxUrl, int status, int totalSize, int downloadedSize, String ajaxResponse, Runnable stopTheAjax);  
       }  

       private final RexseeBrowser mBrowser;  
       private String syncAjaxRtn = null;  

       public RexseeAjax(RexseeBrowser browser) {  

               mBrowser = browser;  

       public void submit(String url, final String postData, final AjaxProgressListener progressListener, final String encode, final boolean callbackJs) {  
               final String ajaxUrl = mBrowser.urlListeners.getAbsoluteUrl(url);  
               Uri uri = Uri.parse(ajaxUrl);  
               if (uri == null) {  
                       if (progressListener != null) progressListener.run(ajaxUrl,                if (scheme == null || (!scheme.equals("http") && !scheme.equals("https"))) {  
                       if (progressListener != null) progressListener.run(ajaxUrl, AJAX_PROGRESS_EXCEPTION, 0, 0, "Invalid url.", null);  
                       mBrowser.exception(getInterfaceName(), url + ":Invalid url.");  
                       return;  
               }  
               if (!mBrowser.domainWhiteList.isValidUrl(ajaxUrl)) {  
                       if (progressListener != null) progressListener.run(ajaxUrl, AJAX_PROGRESS_EXCEPTION, 0, 0, "Url not allowed.", null);  
                       mBrowser.exception(getInterfaceName(), url + ":Url not allowed.");  
                       return;  
                                       stop = true;  
                                       if (progressListener != null) progressListener.run(ajaxUrl, AJAX_PROGRESS_EXCEPTION, 0, 0, "User canceled.", null);  
                               }  
                       };  
                       @Override  
                       public void run() {  
                               int timeout = mBrowser.application.getTimeout() * 1000;  
                               try {  
                                       byte[] postBytes = new String(postData.getBytes(), encode).getBytes(encode);  
                                       if (progressListener != null) progressListener.run(ajaxUrl, AJAX_PROGRESS_CONNECTING, 0, 0, null, stopRunnable);  
                                       URL url = new URL(ajaxUrl);  
                                       CookieManager cookieManager = CookieManager.getInstance();  
                                       String cookie = cookieManager.getCookie(ajaxUrl);  
                                       if (cookie != null) {  
                                               urlConnection.setRequestProperty("Cookie", cookie);  
                                               //After urlConnection.connect(); could retrieve sessionId with urlConnection.getHeaderField("Set-Cookie");  
                                       }  
                                       urlConnection.setRequestProperty("User-Agent", mBrowser.getSettings().getUserAgentString());  
                                       urlConnection.setRequestProperty("Content-Length", "" + postBytes.length);  
                                       urlConnection.connect();  
                                       DataOutputStream dos = new DataOutputStream(urlConnection.getOutputStream());  
                                       dos.write(postBytes);  
                                       dos.flush();  
                                       dos.close();  
                                       if (cookieManager.acceptCookie()) {  
                                               ////Set session cookie  
+ ";";  
                                                       } else {  
                                                       }  
                                               }  
                                               if (sessionCookie != "") cookieManager.setCookie(ajaxUrl, cookieVal);  
                                       }  
                                       InputStream inputStream = urlConnection.getInputStream();  
                                       int totalSize = urlConnection.getContentLength();  
                                       int downloadedSize = 0;  
                                       byte[] buffer = new byte[1024];  
                                       int bufferLength = 0;  
                                       String rtn = "";  
                                       while ((bufferLength = inputStream.read(buffer)) > 0 && !stop) {  
                                               rtn += new String(buffer, 0, bufferLength, encode);  
                                               downloadedSize += bufferLength;  
                                               if (progressListener != null) progressListener.run(ajaxUrl, AJAX_PROGRESS_ONGOING, totalSize, downloadedSize, rtn, stopRunnable);  
                                       }  
                                       if (!stop) {  
                                               if (progressListener != null)                                                if (progressListener != null) progressListener.run(ajaxUrl, AJAX_PROGRESS_TIMEOUT, 0, 0, String.valueOf(timeout), null);  
                                               if (callbackJs) mBrowser.eventList.run(EVENT_ONAJAXTIMEOUT, new String[]{ajaxUrl, String.valueOf(timeout)});  
                                       }  
                               } catch (Exception e) {  
                                       if (!stop) {  
                                               if (progressListener != null) progressListener.run(ajaxUrl, AJAX_PROGRESS_EXCEPTION, 0, 0, e.getLocalizedMessage(), null);  
                                               mBrowser.exception(getInterfaceName(), ajaxUrl + ":" + e.getLocalizedMessage());  
                                       }  
                               }  
                       }  
               }.start();  
       }  

       //JavaScript Interface  
       public void sendMessage(final String ajaxUrl, final String postData) {  
               submit(ajaxUrl, postData, null, "UTF-8", false);  
       }  
       public void submit(String ajaxUrl, String postData, final String encode) {  
                                       if (cancelable) {  
                                               mBrowser.progressDialog.showWithRunnable(RexseeLanguage.PROGRESS_CONNECT, stopTheAjax);  
                                       } else {  
                                               mBrowser.progressDialog.show(RexseeLanguage.PROGRESS_CONNECT);  
                                       }  
                               } else if (status == AJAX_PROGRESS_TIMEOUT) {  
                                       mBrowser.progressDialog.hide();  
                               } else if (status == AJAX_PROGRESS_EXCEPTION) {  
                                       mBrowser.progressDialog.hide();  
                               } else if (status == AJAX_PROGRESS_ONGOING) {  
                                       String progress = (totalSize < 0) ? "" : (downloadedSize * 100 / totalSize) + "%";  
                                       if (cancelable) {  
                                               mBrowser.progressDialog.showWithRunnable(RexseeLanguage.PROGRESS_ONGOING + "......" + progress + " ", stopTheAjax);  
                                       } else {  
                                               mBrowser.progressDialog.show(RexseeLanguage.PROGRESS_ONGOING + "......" + progress + " ");  
                                       }  
                               } else if (status == AJAX_PROGRESS_DONE) {  
                                       mBrowser.progressDialog.hide();  
                               }  
                       }  
               }, encode, true);  
       }  
       public void submitWithCallback(String ajaxUrl, String postData, final String encode) {  
               submit(ajaxUrl, postData, new AjaxProgressListener() {  
                       @Override  
                       public void run(String ajaxUrl, int status, int totalSize, int downloadedSize, String ajaxResponse, Runnable stopTheAjax) {  
                               mBrowser.eventList.run(EVENT_ONAJAXPROGRESSCHANGED, new String[]{ajaxUrl, String.valueOf(totalSize), String.valueOf(downloadedSize)});  
                       }  
               }, encode, true);  
       }  
       public String syncSubmit(String url, final String postData, final String encode) {  
               return syncSubmit(url, postData, encode, true, true);  
       }  
       public String syncSubmit(String url, final String postData, final String encode, final boolean showProgress, final boolean cancelable) {  
               syncAjaxRtn = null;  
               submit(url, postData, new AjaxProgressListener() {  
                       @Override  
                       public void run(String ajaxUrl, int status, int totalSize, int downloadedSize, String ajaxResponse, final Runnable stopTheAjax) {  
                               if (status == RexseeAjax.AJAX_PROGRESS_CONNECTING) {  
                                       if (cancelable) {  
                                               if (showProgress) mBrowser.progressDialog.showWithRunnable(RexseeLanguage.PROGRESS_CONNECT, stopTheAjax);  
                                       } else {  
                                               if (showProgress) mBrowser.progressDialog.show(RexseeLanguage.PROGRESS_CONNECT);  
                                       }  
                               } else if (status == RexseeAjax.AJAX_PROGRESS_TIMEOUT) {  
                                       syncAjaxRtn = RexseeApplication.EXCEPTION_PREFIX + ajaxResponse;  
                               } else if (status == RexseeAjax.AJAX_PROGRESS_EXCEPTION) {  
                                       syncAjaxRtn = RexseeApplication.EXCEPTION_PREFIX + ajaxResponse;  
                               } else if (status == RexseeAjax.AJAX_PROGRESS_ONGOING) {  
                                       String progress = (totalSize < 0) ? "" : (downloadedSize * 100 / totalSize) + "%";  
                                       if (cancelable) {  
                                               if (showProgress) mBrowser.progressDialog.showWithRunnable(RexseeLanguage.PROGRESS_ONGOING + "......" + progress + " ", stopTheAjax);  
                                       } else {  
                                               if (showProgress) mBrowser.progressDialog.show(RexseeLanguage.PROGRESS_ONGOING + "......" + progress + " ");  
                                       }  
                               } else if (status == RexseeAjax.AJAX_PROGRESS_DONE) {  
                                       syncAjaxRtn = ajaxResponse;  
                               }  
                       }  
               }, encode, false);  
               while (syncAjaxRtn == null) {  
                       try {  
                               Thread.sleep(100);  
                       } catch (InterruptedException e) {  
                       }  
               }  
               if (showProgress) mBrowser.progressDialog.hide();  
               return syncAjaxRtn;  
       }  

}
发表于 2011-12-15 18:25:57 | 显示全部楼层
好多Web框架啊,都是采用JS注入接口的,没啥差别
点评回复

使用道具 举报

高级模式
B Color Image Link Quote Code Smilies

本版积分规则

Archiver|手机版|小黑屋|52RD我爱研发网 ( 沪ICP备2022007804号-2 )

GMT+8, 2024-11-23 11:21 , Processed in 0.045970 second(s), 17 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表