本地HTML訪問REST服務的實現


本地HTML訪問REST服務的實現

 

1     前言

最近一段時間在研究如何實現跨平台應用,其中的一個關鍵技術點就是本地HTML頁面如何訪問遠程服務。經過探索,終於解決了碰到的各種問題,做出了一個Demo. 

本文就Demo所用的技術架構做了一個簡介,並分析了實現中碰到的問題及相應的解決方法。一來以此作為這段時間工作的一個技術總結,二來希望能對其他同行有所幫助。

2         技術架構

Demo 本身的功能很簡單,

1)      本地HTML 發出 “POST” 命令,發送一段數據到 Server端

2)      Server 端存儲收到的數據

3)      本地HTML  發出工“GET” 命令,取回數據  

Demo分為兩部分。Client端比較簡單,就是HTML+JQuery.  Server端則用REST服務, 是用JAVA寫的,具體方案是glasshfish+ Jersey.  兩者這間用Json格式通信。

3         主要問題的解決方法:

3.1       Same origin policy

3.1.1       問題

這是整個Demo中耗時最多的一個問題。問題的表象是 從Chrome發出HTTP命令后,Chrome console中報 “Origin null is not allowed by Access-Control-Allow-Origin”錯誤。

這是由於Browser的same origin policy 限制的緣故。簡單來說,從HTML中發出XMLHttpRequest  請求時,Browser會做檢查,如果發現Response中沒有Access-Control-Allow-Origin Header或Access-Control-Allow-Origin Header Header的值與 HTML的 orgin 不同時,Browser會拒接絕該Response,Javascript就收不到該Response。 本地HTML的Origin是 null, 而Server端沒有發出Access-Control-Allow-Origin Header Header給Browser,  所以會有了“Origin null is not allowed by Access-Control-Allow-Origin”錯誤。

3.1.2       解決方法

事實上有一個W3C標准,Cross Origin Resource Sharing (CORS) 專門用來解決這個問題的。目前的主流Browser也有支持。CORS 在HTTP Message 加入幾個Header, Browser和 Server可以利用這些Header來判斷對方是否是安全,是否可以通信。

具體來說,CORS包括兩方面。 Server端和Browser端。

3.1.2.1       Server端

以Demo中的Server端為例,解決方法就是在 Jersey Servlet中加入一個Filter, 在 Filter中修改給Browser的Response, 共有兩步

1)      配置Web.xml

在Jersey Servlet中加入init-param

<servlet>

        <servlet-name>ServletAdaptor</servlet-name>

        <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>

        <init-param>

              <param-name>com.sun.jersey.spi.container.ContainerResponseFilters</param-name>

             <param-value>jasontesting.ResponseCorsFilter</param-value>

        </init-param>

        <load-on-startup>1</load-on-startup>

       

</servlet>

 

2)      ResponseCorsFilter

/*

 * To change this template, choose Tools | Templates

 * and open the template in the editor.

 */

package jasontesting;

 

/**

 *

 * @author jianl

 */

import javax.ws.rs.core.Response;

import javax.ws.rs.core.Response.ResponseBuilder;

 

import com.sun.jersey.spi.container.ContainerRequest;

import com.sun.jersey.spi.container.ContainerResponse;

import com.sun.jersey.spi.container.ContainerResponseFilter;

 

public class ResponseCorsFilter implements ContainerResponseFilter {

 

    @Override

    public ContainerResponse filter(ContainerRequest req, ContainerResponse contResp) {

 

        ResponseBuilder resp = Response.fromResponse(contResp.getResponse());

        resp.header("Access-Control-Allow-Origin", "*")

                .header("Access-Control-Max-Age", 1728000)

        .header("Access-Control-Allow-Methods", "GET, POST, OPTIONS");

 

        String reqHead = req.getHeaderValue("Access-Control-Request-Headers");

 

        if(null != reqHead && !reqHead.equals(null)){

            resp.header("Access-Control-Allow-Headers", reqHead);

        }

 

        contResp.setResponse(resp.build());

            return contResp;

    }

 

}

3.1.2.2       Browser端

如前所述,Browser已經實現了CORS,CORS對應用開發人員是透明的。為了方便,公布Demo的Browser端源代碼如下。

<script src="jquery-latest.js"></script>

  <script src="jquery.json-2.3.js"></script>

<script type="text/javascript">

  var url= "http://localhost:8080/WebApplication3/resources/contact";

  var postobject={id:2,name:"Bob9",addresses:[{street:"Long Street 1",town:"Short Village"}],id_attribute:888};

 jQuery.ajax({

      url: url,

      type: "POST",

      data: $.toJSON(postobject),

      dataType: "json",

      contentType:"application/json",

      success: function(result) {

                     //Write your code here

                  //alert(result);

                  $.get(

                                                    url,

                                                    function(data, textStatus, jqXHR) {

                                                                alert(data);

                                                    },

                                                    "json"

                                                );

      }

});

  </script>

3.2       Accept and Content-Type Header

這個問題本身並不復雜,但由於之前對HTTP協議並不十分了解,還是花了大半天時間。問題核心是要在Request中要加入 Accept 與 Content-Type Header,指定可接愛的和發送的MIME 類型。具體的解決例子可參考Browser端的代碼。

4          總結

經過這些天的摸索,終於做出這個Demo,弄清楚了本地HTML訪問REST服務可如何實現,心中很是欣慰。要繼續努力,深化在移動開發方面的技術積累。

5         參考

 

http://www.nczonline.net/blog/2010/05/25/cross-domain-ajax-with-cross-origin-resource-sharing/

http://www.html5rocks.com/en/tutorials/cors/

http://blog.usul.org/cors-compliant-rest-api-with-jersey-and-containerresponsefilter/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM