<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 495,  comments - 11,  trackbacks - 0
     

    Java代碼實現

    /**
    * 查找兩個串的最大公共子串
    *
    * @param s1
    * @param s2
    * @return
    */
    public static String commonMaxSubString(String s1, String s2) {
    ?? String maxstr = "";
    ?? String substring = "";
    ?? if (s1.length() > s2.length()) { // s1為兩個串中的短串;s2為長串
    ??? String temp = s1;
    ??? s1 = s2;
    ??? s2 = temp;
    ?? }
    ?? int len = s1.length();
    ?? ok: for (int i = len; i > 0; i--) {
    ??? for (int j = 0; j < len - i + 1; j++) {
    ???? substring = s1.substring(j, j + i);
    ???? if (s2.indexOf(substring) != -1) {
    ????? maxstr = substring;
    ????? break ok; // 只要一找到最大子串,就退出這個for循環
    ???? }
    ??? }
    ?? }
    ?? return maxstr;
    }

    posted @ 2009-08-20 23:42 jadmin 閱讀(82) | 評論 (0)編輯 收藏

    通常交換兩個整型變量,經常會如下做:

    public void swap(int a, int b) {
    ??? int t = a;// 使用第三個變量t

    ??? a = b;

    ??? b = t;
    }

    下面介紹兩種不借助變量,讓兩個整型變量交換的方法

    方法一:借助代數運算

    public void swap(int a, int b) {
    ???? a = a + b;

    ???? b = a - b; // 這個時候a=a+b,b=a

    ???? a = a - b; // a = b
    }

    方法二:借助^異或運算

    public void swap(int a, int b) {
    ???? a = a^b;

    ???? b = a^b;

    ???? a = a^b;
    }

    posted @ 2009-08-20 23:36 jadmin 閱讀(92) | 評論 (0)編輯 收藏

    OGNL中的#%$符號

    #%$符號在OGNL表達式中經常出現,而這三種符號也是開發者不容易掌握和理解的部分。在這里筆者簡單介紹它們的相應用途。


    1
    #符號

    #符號的用途一般有三種。
    >>>
    訪問非根對象屬性,例如示例中的#session.msg表達式,由于Struts 2中值棧被視為根對象,所以訪問其他非根對象時,需要加#前綴。實際上,#相當于ActionContext. getContext()#session.msg表達式相當于ActionContext.getContext().getSession(). getAttribute("msg")
    >>>

    用于過濾和投影(projecting)集合,如示例中的persons.{?#this.age>20}
    >>>

    用來構造Map,例如示例中的#{'foo1':'bar1', 'foo2':'bar2'}

    2%符號

    %符號的用途是在標志的屬性為字符串類型時,計算OGNL表達式的值。如下面的代碼所示:

    構造Map

    The value of key "foo1" is 
    不使用%:
    使用%:

    運行界面如圖8.4所示。

    8.4 “%”OGNL表達式用法

    3$符號

    $符號主要有兩個方面的用途。
    >>>
    在國際化資源文件中,引用OGNL表達式,例如國際化資源文件中的代碼:reg.agerange=國際化資源信息:年齡必須在${min}${max}之間。
    >>>
    Struts 2框架的配置文件中引用OGNL表達式,例如下面的代碼片斷所示:

     
    10
    100
    BAction-test
    校驗:數字必須為${min}${max}之間!


    posted @ 2009-08-15 17:34 jadmin 閱讀(101) | 評論 (0)編輯 收藏

    <?xml:namespace prefix = st1 />1.1.1 業務控制器

    為本示例建立一個業務控制器,該控制器用到了代碼8.1中定義的Person人員信息類。該業務控制器如代碼8.4所示。

    代碼8.4 Struts 2OGNL示例業務控制器

    package ch8;
    import java.util.Date;
    import java.util.LinkedList;
    import java.util.List;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    import org.apache.struts2.ServletActionContext;
    import com.opensymphony.xwork2.ActionContext;
    import com.opensymphony.xwork2.ActionSupport;
    public class OgnlAction extends ActionSupport {
    //List
    類型屬性
    private List persons;
    //execute
    方法
    public String execute() throws Exception {
    //
    獲得ActionContext實例,以便訪問Servlet API
    ActionContext ctx = ActionContext.getContext();
    //
    存入application
    ctx.getApplication().put("msg", "application
    信息");
    //
    保存session
    ctx.getSession().put("msg", "seesion
    信息");
    //
    保存request信息
    HttpServletRequest request = ServletActionContext.getRequest();
    request.setAttribute("msg", "request
    信息");
    //
    persons賦值
    persons = new LinkedList();
    Person person1=new Person();
    person1.setName("pla1");
    person1.setAge(26);
    person1.setBirthday(new Date());
    persons.add(person1);

    Person person2=new Person();
    person2.setName("pla2");
    person2.setAge(36);
    person2.setBirthday(new Date());
    persons.add(person2);
    Person person3=new Person();
    person3.setName("pla3");
    person3.setAge(16);
    person3.setBirthday(new Date());
    persons.add(person3);
    return SUCCESS;
    }
    public List getPersons() {
    return persons;
    }
    public void setPersons(List persons) {
    this.persons = persons;
    }
    }

    該業務控制器分別在applicationsessionrequest中存入名為“msg”的字符串信息,另外定義了一個List類型屬性,同時添加了兩個Person類型元素。在配置文件中增加了相應的配置,代碼如下:


    /ch8/showognl.jsp

    1.1.2 JSP視圖

    showognl.jsp是使用了OGNL表達式的JSP視圖,視圖用來顯示Action中處理的各種信息,讀者可以看到,使用OGNL表達式,代碼更加簡潔和直觀,如代碼8.5所示。

    代碼8.5使用OGNL表達式的JSP視圖


    http://www.w3.org/TR/ xhtml1/DTD/xhtml1-transitional.dtd">
    http://www.w3.org/1999/xhtml">

    訪問OGNL上下文和Action上下文

    parameters: 
    request.msg: 
    session.msg: 
    application.msg: 
    attr.msg: 
    
    
    用于過濾和投影(projecting)集合
    年齡大于20
    1.???????????????????????   - 年齡:
    姓名為pla1的年齡: 
    
    
    構造Map
    The value of key "foo1" is 

    1.1.3 運行示例

    在瀏覽器中輸入http://localhost:8080/bookcode/ch8/OgnlAction.action?msg=hello,運行結果如圖8.3所示。

    8.3 Struts 2中使用OGNL表達式

    說明

    本示例演示了如何使用OGNL表達式來訪問OGNL上下文和值棧,同時演示了如何使用OGNL表達式進行集合操作。對讀者深入理解Struts 2OGNL表達式的使用有所幫助。

    posted @ 2009-08-15 17:29 jadmin 閱讀(90) | 評論 (0)編輯 收藏

    OGNL的集合操作

    如果需要一個集合元素的時候(例如List對象或者Map對象),可以使用OGNL中同集合相關的表達式。

    可以使用如下代碼直接生成一個List對象:

    {e1,e2,e3…}

    OGNL表達式中,直接生成了一個List對象,該List對象中包含3個元素:e1e2e3。如果需要更多的元素,可以按照這樣的格式定義多個元素,多個元素之間使用逗號隔開。

    如下代碼可以直接生成一個Map對象:

    #{key1:value1,key2:value2,…}


    Map
    類型的集合對象,使用key-value格式定義,每個key-value元素使用冒號標識,多個元素之間使用逗號隔開。

    對于集合類型,OGNL表達式可以使用innot in兩個元素符號。其中,in表達式用來判斷某個元素是否在指定的集合對象中;not in判斷某個元素是否不在指定的集合對象中,如代碼8.3所示。

    代碼8.3使用OGNL集合操作符


    muhahaha


    boo


    muhahaha


    boo

    除了innot in之外,OGNL還允許使用某個規則獲得集合對象的子集,常用的有以下3個相關操作符。
    >>>
    ?
    :獲得所有符合邏輯的元素。
    >>>
    ^
    :獲得符合邏輯的第一個元素。
    >>>
    $
    :獲得符合邏輯的最后一個元素。

    例如代碼:

    person.relatives.{? #this.gender == 'male'}

    該代碼可以獲得person的所有性別為malerelatievs集合。

    posted @ 2009-08-15 17:25 jadmin 閱讀(161) | 評論 (0)編輯 收藏

    注意

    使用索引,并不是直接獲得指定的元素,而是從指定的索引位置搜索。

    Struts 2中的OGNL ContextActionContext,如圖8.2所示。

    ??

    8.2 Struts 2OGNL Context結構示意圖

    說明

    8.2只是說明Struts 2OGNL Context結構,實際上Context還包含其他對象。

    由于值棧是Struts 2OGNL的根對象,如果用戶需要訪問值棧中的對象,則可以直接通過下面的代碼訪問值棧中的屬性:

    //獲得值棧中的foo屬性
    ${foo}

    如果訪問其他Context中的對象,由于不是根對象,在訪問時,需要加#前綴。
    >>
    application
    對象:用于訪問ServletContext,例如#application.userName或者#application['userName'],相當于調用ServletgetAttribute("username")
    >>

    session
    對象:用來訪問HttpSession,例如#session.userName或者#session['userName'],相當于調用session.getAttribute("userName")
    >>

    request
    對象:用來訪問HttpServletRequest屬性(attribute)的Map,例如#request.userName或者#request['userName'],相當于調用request.getAttribute ("userName")
    >>

    parameters
    對象:用于訪問HTTP的請求參數,例如#parameters.userName或者#parameters['userName'],相當于調用request.getParameter("username")
    >>

    attr
    對象:用于按page-request-session-application順序訪問其屬性。

    posted @ 2009-08-15 17:18 jadmin 閱讀(100) | 評論 (0)編輯 收藏

    OGNLStruts 2框架的默認表達式語言,增強了Struts 2的數據訪問能力,同時簡化了代碼。

    Struts 2OGNL表達式

    標準的OGNL會設定一個根對象(root對象)。假設使用標準OGNL表達式來求值(不使用Struts 2OGNL表達式),如果OGNL上下文(OgnlContext Map類型)有兩個對象:foo對象,在OgnlContext中名稱為foobar對象,在OgnlContext中名稱為bar。同時foo對象被設置為根對象(root)。則利用下面的OGNL表達式求值:

    // 返回foo.getBlah()
    #foo.blah
    //
    返回bar.getBlah()
    #bar.blah
    //
    返回foo.getBlah() ,因為foo為根對象
    blah

    說明

    使用OGNL是非常簡單的,如果要訪問的對象不是根對象,如示例中的bar對象,則需要使用命名空間,用“#”來標識,如“#bar”;如果訪問一個根對象,則不用指定命名空間,可以直接訪問根對象的屬性。

    Struts 2框架中,值棧(Value Stack)就是OGNL的根對象,假設值棧中存在兩個對對象實例:ManAnimal,這兩個對象實例都有一個name屬性,Animal有一個species屬性,Man有一個salary屬性,假設Animal在值棧的頂部,ManAnimal后面,下面的代碼片斷會幫助讀者更好地理解OGNL表達式:

    // 調用animal.getSpecies()
    species
    //
    調用man.getSalary()
    salary
    //
    調用animal.getName(),因為Animal位于值棧的頂部
    name


    最后一行示例代碼,返回的是animal.getName()返回值,即返回了Animalname屬性,因為Animal是值棧的頂部元素,OGNL將從頂部元素搜索,所以會返回Animalname屬性值。如果要獲得Manname值,則需要如下代碼:

    man.name

    Struts 2允許在值棧中使用索引,示例代碼如下所示:

    [0].name?? // 調用animal.getName()
    [1].name?? //
    調用man.getName()

    posted @ 2009-08-15 17:18 jadmin 閱讀(91) | 評論 (0)編輯 收藏

    ??? XFire、Axis

    ??? XFire、Axis是Webservice的實現框架,WebService可算是一個完整的SOA架構實現標準了,因此采用XFire、Axis這些也就意味著是采用webservice方式了。

      1、是基于什么協議實現的?

      基于SOAP協議。

      2、怎么發起請求?

      獲取到遠端service的proxy后直接調用。

      3、怎么將請求轉化為符合協議的格式的?

      將請求信息轉化為遵循SOAP協議的XML格式,由框架轉化為流進行傳輸。

      4、使用什么傳輸協議傳輸?

      Http協議。

      5、響應端基于什么機制來接收請求?

      監聽Http請求。

      6、怎么將流還原為傳輸格式的?

      根據SOAP協議進行還原。

      7、處理完畢后怎么回應?

      返回結果寫入XML中,由框架返回至調用端。

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

      ActiveMQ

      ActiveMQ是JMS的實現,基于JMS這類消息機制實現遠程通訊是一種不錯的選擇,畢竟消息機制本身的功能使得基于它可以很容易的去實現同步/異步/單向調用等,而且消息機制從容錯角度上來說也是個不錯的選擇,這是Erlang能夠做到容錯的重要基礎

      1、是基于什么協議實現的?

      基于JMS協議。

      2、怎么發起請求?

      遵循JMS API發起請求。

      3、怎么將請求轉化為符合協議的格式的?

      不太清楚,猜想應該是二進制流。

      4、使用什么傳輸協議傳輸?

      支持多種傳輸協議,例如tcp/ip、udp、http等等。

      5、響應端基于什么機制來接收請求?

      監聽符合協議的端口。

      6、怎么將流還原為傳輸格式的?

      同問題3。

      7、處理完畢后怎么回應?

      遵循JMS API生成消息,并寫入JMS Queue中。

      基于JMS此類機制實現遠程通訊的例子有Spring-Intergration、Mule、Lingo等等。

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

    ??? Mina

    ??? Mina是Apache提供的通訊框架,在之前一直沒有提到網絡IO這塊,之前提及的框架或library基本都是基于BIO的,而Mina是采用NIO的,NIO在并發量增長時對比BIO而言會有明顯的性能提升,而java性能的提升,與其NIO這塊與OS的緊密結合是有不小的關系的。

    ??? 1、是基于什么協議實現的?

    ??? 可選的傳輸協議+NIO.

    ??? 2、怎么發起請求?

    ??? 通過Mina提供的Client API.

    ??? 3、怎么將請求轉化為符合協議的格式的?

    ??? Mina遵循java串行化機制對請求對象進行序列化。

    ??? 4、使用什么傳輸協議傳輸?

    ??? 支持多種傳輸協議,例如tcp/ip、http等等。

    ??? 5、響應端基于什么機制來接收請求?

    ??? 以NIO的方式監聽協議端口。

    ??? 6、怎么將流還原為傳輸格式的?

    ??? 遵循java串行化機制對請求對象進行反序列化。

    ??? 7、處理完畢后怎么回應?

    ??? 遵循Mina API進行返回。

    ??? MINA是NIO方式的,因此支持異步調用是毫無懸念的。

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

    ??? EJB

    ??? EJB最突出的在于其分布式,EJB采用的是ORMI協議,和RMI協議是差不多的,但EJB在分布式通訊的安全控制、transport pool、smart proxy等方面的突出使得其在分布式領域是不可忽視的力量。

    ??? 1、是基于什么協議實現的?

    ??? 基于ORMI協議。

    ??? 2、怎么發起請求?

    ??? EJB調用。

    ??? 3、怎么將請求轉化為符合協議的格式的?

    ??? 遵循java串行化機制對請求對象進行序列化。

    ??? 4、使用什么傳輸協議傳輸?

    ??? tcp/ip.

    ??? 5、響應端基于什么機制來接收請求?

    ??? 監聽協議端口。

    ??? 6、怎么將流還原為傳輸格式的?

    ??? 遵循java串行化機制對請求對象進行反序列化。

    ??? 7、處理完畢后怎么回應?

    ??? 直接返回處理對象即可。

    ??? 在之前的分布式服務框架系列的文章中對于jndi有誤導的嫌疑,在這篇blog中也順帶的提下jndi的機制,由于JNDI取決于具體的實現,在這里只能是講解下jboss的jndi的實現了。

    ??? 在將對象實例綁定到jboss jnp server后,當遠程端采用context.lookup()方式獲取遠程對象實例并開始調用時,jboss jndi的實現方法是從jnp server上獲取對象實例,將其序列化回本地,然后在本地進行反序列化,之后在本地進行類調用。

    ??? 通過這個機制,就可以知道了,本地其實是必須有綁定到jboss上的對象實例的class的,否則反序列化的時候肯定就失敗了,而遠程通訊需要做到的是在遠程執行某動作,并獲取到相應的結果,可見純粹基于JNDI是無法實現遠程通訊的。

    ??? 但JNDI也是實現分布式服務框架一個很關鍵的技術點,因為可以通過它來實現透明化的遠端和本地調用,就像ejb,另外它也是個很好的隱藏實際部署機制(就像datasource)等的方案。

    ??? 總結

    ??? 由上一系列的分析可知,在遠程通訊領域中,涉及的知識點還是相當的多的,例如有:通信協議或遠程調用協議(tcp/http/udp/rmi/xml-rpc etc.)、消息機制、網絡IO(BIO/NIO/AIO)、MultiThread、本地調用與遠程調用的透明化方案(涉及java classloader、Dynamic Proxy、Unit Test etc.)、異步與同步調用、網絡通信處理機制(自動重連、廣播、異常、池處理等等)、Java Serialization (各種協議的私有序列化機制等)、各種框架的實現原理(傳輸格式、如何將傳輸格式轉化為流的、如何將請求信息轉化為傳輸格式的、如何接收流的、如何將流還原為傳輸格式的等等),要精通其中的哪些東西,得根據實際需求來決定了,只有在了解了原理的情況下才能很容易的做出選擇,甚至可以根據需求做私有的遠程通訊協議,對于從事分布式服務平臺或開發較大型的分布式應用的人而言,我覺得至少上面提及的知識點是需要比較了解的。

    posted @ 2009-08-15 15:10 jadmin 閱讀(242) | 評論 (0)編輯 收藏

    ??? 可選實現技術

    ??? 當然,在上面的原理中并沒有介紹到所有的java領域可選的遠程通信協議了,例如還有EJB采用的ORMI、Spring自己定義的一個簡單的Http Invoker等等。

    ??? 看完原理后我們再來看看目前java領域可用于實現遠程通訊的框架或library,知名的有:JBoss-Remoting、Spring-Remoting、Hessian、Burlap、XFire(Axis)、ActiveMQ、Mina、Mule、EJB3等等,來對每種做個簡單的介紹和評價,其實呢,要做分布式服務框架,這些東西都是要有非常深刻的了解的,因為分布式服務框架其實是包含了解決分布式領域以及應用層面領域兩方面問題的。

    ??? 當然,你也可以自己根據遠程網絡通信原理(transport protocol+Net IO)去實現自己的通訊框架或library.

    ??? 那么在了解這些遠程通訊的框架或library時,會帶著什么問題去學習呢?

    ??? 1、是基于什么協議實現的?

    ??? 2、怎么發起請求?

    ??? 3、怎么將請求轉化為符合協議的格式的?

    ??? 4、使用什么傳輸協議傳輸?

    ??? 5、響應端基于什么機制來接收請求?

    ??? 6、怎么將流還原為傳輸格式的?

    ??? 7、處理完畢后怎么回應?

    ??? JBoss-Remoting

    ??? Jboss-remoting是由jboss編寫的一個java領域的遠程通訊框架,基于此框架,可以很簡單的實現基于多種傳輸協議的java對象的RPC.

    ??? 直接來回答問題:

    ??? 1、是基于什么協議實現的?

    ??? JBoss-Remoting是個通訊框架,因此它支持多種協議方式的通信,例如tcp/ip+io方式、rmi方式、http+io方式等。

    ??? 2、怎么發起請求?

    ??? 在JBoss-Remoting中,只需將需要發起的請求參數對象傳入jboss-remoting的InvocationRequest對象即可,也可根據協議基于InvocationRequest封裝符合需求的InvocationRequest對象。

    ??? 3、怎么將請求轉化為符合協議的格式的?

    ??? JBoss-Remoting基于Java串行化機制或JBoss自己的串行化實現來將請求轉化為對象字節流。

    ??? 4、使用什么傳輸協議傳輸?

    ??? 支持多種傳輸協議,例如tcp/ip、http等。

    ??? 5、響應端基于什么機制來接收請求?

    ??? 響應端只需將自己的處理對象注冊到JBoss-Remoting提供的server端的Connector對象中即可。

    ??? 6、怎么將流還原為傳輸格式的?

    ??? JBoss-Remoting基于java串行化機制或jboss自己的串行化實現來將請求信息還原為java對象。

    ??? 7、處理完畢后怎么回應?

    ??? 處理完畢后將結果對象直接返回即可,jboss-remoting會將此對象按照協議進行序列化,返回至調用端。

    ??? 另外,jboss-remoting支持多種通信方式,例如同步/異步/單向通信等。

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

    ??? Spring-Remoting

    ??? Spring-remoting是Spring提供java領域的遠程通訊框架,基于此框架,同樣也可以很簡單的將普通的spring bean以某種遠程協議的方式來發布,同樣也可以配置spring bean為遠程調用的bean.

      1、是基于什么協議實現的?

      和JBoss-Remoting一樣,作為一個遠程通訊的框架,Spring通過集成多種遠程通訊的library,從而實現了對多種協議的支持,例如rmi、http+io、xml-rpc、binary-rpc等。

      2、怎么發起請求?

      在Spring中,由于其對于遠程調用的bean采用的是proxy實現,發起請求完全是通過服務接口調用的方式。

      3、怎么將請求轉化為符合協議的格式的?

      Spring按照協議方式將請求的對象信息轉化為流,例如Spring Http Invoker是基于Spring自己定義的一個協議來實現的,傳輸協議上采用的為http,請求信息是基于java串行化機制轉化為流進行傳輸。

      4、使用什么傳輸協議傳輸?

      支持多種傳輸協議,例如rmi、http等等。

      5、響應端基于什么機制來接收請求?

      響應端遵循協議方式來接收請求,對于使用者而言,則只需通過spring的配置方式將普通的spring bean配置為響應端或者說提供服務端。

      6、怎么將流還原為傳輸格式的?

      按照協議方式來進行還原。

      7、處理完畢后怎么回應?

      處理完畢后直接返回即可,spring-remoting將根據協議方式來做相應的序列化。

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

      Hessian

      Hessian是由caucho提供的一個基于binary-RPC實現的遠程通訊library。

      1、是基于什么協議實現的?

      基于Binary-RPC協議實現。

      2、怎么發起請求?

      需通過Hessian本身提供的API來發起請求。

      3、怎么將請求轉化為符合協議的格式的?

      Hessian通過其自定義的串行化機制將請求信息進行序列化,產生二進制流。

    ??? Hessian基于Http協議進行傳輸。

    ??? 5、響應端基于什么機制來接收請求?

    ??? 響應端根據Hessian提供的API來接收請求。

    ??? 6、怎么將流還原為傳輸格式的?

    ??? Hessian根據其私有的串行化機制來將請求信息進行反序列化,傳遞給使用者時已是相應的請求信息對象了。

    ??? 7、處理完畢后怎么回應?

    ??? 處理完畢后直接返回,hessian將結果對象進行序列化,傳輸至調用端。

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

    ??? Burlap

    ??? Burlap也是有caucho提供,它和hessian的不同在于,它是基于XML-RPC協議的。

    ??? 1、是基于什么協議實現的?

    ??? 基于XML-RPC協議實現。

    ??? 2、怎么發起請求?

    ??? 根據Burlap提供的API.

    ??? 3、怎么將請求轉化為符合協議的格式的?

    ??? 將請求信息轉化為符合協議的XML格式,轉化為流進行傳輸。

    ??? 4、使用什么傳輸協議傳輸?

    ??? Http協議。

    ??? 5、響應端基于什么機制來接收請求?

    ??? 監聽Http請求。

    ??? 6、怎么將流還原為傳輸格式的?

    ??? 根據XML-RPC協議進行還原。

    ??? 7、處理完畢后怎么回應?

    ??? 返回結果寫入XML中,由Burlap返回至調用端。

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

    posted @ 2009-08-15 15:08 jadmin 閱讀(92) | 評論 (0)編輯 收藏

      在分布式服務框架中,一個最基礎的問題就是遠程服務是怎么通訊的,在Java領域中有很多可實現遠程通訊的技術,例如:RMI、MINA、ESB、Burlap、Hessian、SOAP、EJB和JMS 等,這些名詞之間到底是些什么關系呢,它們背后到底是基于什么原理實現的呢,了解這些是實現分布式服務框架的基礎知識,而如果在性能上有高的要求的話,那深入了解這些技術背后的機制就是必須的了,在這篇blog中我們將來一探究竟,拋磚引玉,歡迎大家提供更多的實現遠程通訊的技術和原理的介紹。

      基本原理

      要實現網絡機器間的通訊,首先得來看看計算機系統網絡通信的基本原理,在底層層面去看,網絡通信需要做的就是將流從一臺計算機傳輸到另外一臺計算機,基于傳輸協議和網絡IO來實現,其中傳輸協議比較出名的有 http、tcp、udp等等,http、tcp、udp都是在基于Socket概念上為某類應用場景而擴展出的傳輸協議,網絡IO,主要有bio、 nio、aio三種方式,所有的分布式應用通訊都基于這個原理而實現,只是為了應用的易用,各種語言通常都會提供一些更為貼近應用易用的應用層協議。

      應用級協議

      遠程服務通訊,需要達到的目標是在一臺計算機發起請求,另外一臺機器在接收到請求后進行相應的處理并將結果返回給請求端,這其中又會有諸如one way request、同步請求、異步請求等等請求方式,按照網絡通信原理,需要實現這個需要做的就是將請求轉換成流,通過傳輸協議傳輸至遠端,遠端計算機在接收到請求的流后進行處理,處理完畢后將結果轉化為流,并通過傳輸協議返回給調用端。

      原理是這樣的,但為了應用的方便,業界推出了很多基于此原理之上的應用級的協議,使得大家可以不用去直接操作這么底層的東西,通常應用級的遠程通信協議會提供:

      1. 為了避免直接做流操作這么麻煩,提供一種更加易用或貼合語言的標準傳輸格式;

      2. 網絡通信機制的實現,就是替你完成了將傳輸格式轉化為流,通過某種傳輸協議傳輸至遠端計算機,遠端計算機在接收到流后轉化為傳輸格式,并進行存儲或以某種方式通知遠端計算機。

      所以在學習應用級的遠程通信協議時,我們可以帶著這幾個問題進行學習:

      1. 傳輸的標準格式是什么?

      2. 怎么樣將請求轉化為傳輸的流?

      3. 怎么接收和處理流?

      4. 傳輸協議是?

      不過應用級的遠程通信協議并不會在傳輸協議上做什么多大的改進,主要是在流操作方面,讓應用層生成流和處理流的這個過程更加的貼合所使用的語言或標準,至于傳輸協議則通常都是可選的,在java領域中知名的有:RMI、XML-RPC、Binary-RPC、SOAP、CORBA、JMS,來具體的看看這些遠程通信的應用級協議:

      RMI

      RMI是個典型的為java定制的遠程通信協議,我們都知道,在single vm中,我們可以通過直接調用java object instance來實現通信,那么在遠程通信時,如果也能按照這種方式當然是最好了,這種遠程通信的機制成為RPC(Remote Procedure Call),RMI正是朝著這個目標而誕生的。

      來看下基于RMI的一次完整的遠程通信過程的原理:

      1. 客戶端發起請求,請求轉交至RMI客戶端的stub類;

      2. stub類將請求的接口、方法、參數等信息進行序列化;

      3. 基于socket將序列化后的流傳輸至服務器端;

      4. 服務器端接收到流后轉發至相應的skelton類;

      5. skelton類將請求的信息反序列化后調用實際的處理類;

      6. 處理類處理完畢后將結果返回給skelton類;

      7. Skelton類將結果序列化,通過socket將流傳送給客戶端的stub;

      8. stub在接收到流后反序列化,將反序列化后的Java Object返回給調用者。

      來看jboss-remoting對于此過程的一個更好的圖示:

    Java遠程通訊可選技術及原理

      根據原理來回答下之前學習應用級協議帶著的幾個問題:

      1. 傳輸的標準格式是什么?

      是Java ObjectStream。

      2. 怎么樣將請求轉化為傳輸的流?

      基于Java串行化機制將請求的java object信息轉化為流。

      3. 怎么接收和處理流?

      根據采用的協議啟動相應的監聽端口,當有流進入后基于Java串行化機制將流進行反序列化,并根據RMI協議獲取到相應的處理對象信息,進行調用并處理,處理完畢后的結果同樣基于java串行化機制進行返回。

      4. 傳輸協議是?

      Socket。

      XML-RPC

      XML-RPC也是一種和RMI類似的遠程調用的協議,它和RMI的不同之處在于它以標準的xml格式來定義請求的信息(請求的對象、方法、參數等),這樣的好處是什么呢,就是在跨語言通訊的時候也可以使用。

      來看下XML-RPC協議的一次遠程通信過程:

      1. 客戶端發起請求,按照XML-RPC協議將請求信息進行填充;

      2. 填充完畢后將xml轉化為流,通過傳輸協議進行傳輸;

      3. 接收到在接收到流后轉換為xml,按照XML-RPC協議獲取請求的信息并進行處理;

      4. 處理完畢后將結果按照XML-RPC協議寫入xml中并返回。

      圖示以上過程:

    Java遠程通訊可選技術及原理

      同樣來回答問題:

      1. 傳輸的標準格式是?

      標準格式的XML。

      2. 怎么樣將請求轉化為傳輸的流?

      將XML轉化為流。

      3. 怎么接收和處理流?

      通過監聽的端口獲取到請求的流,轉化為XML,并根據協議獲取請求的信息,進行處理并將結果寫入XML中返回。

      4. 傳輸協議是?

      Http。

      Binary-RPC

      Binary-RPC看名字就知道和XML-RPC是差不多的了,不同之處僅在于傳輸的標準格式由XML轉為了二進制的格式。

      同樣來回答問題:

      1. 傳輸的標準格式是?

      標準格式的二進制文件。

      2. 怎么樣將請求轉化為傳輸的流?

      將二進制格式文件轉化為流。

      3. 怎么接收和處理流?

      通過監聽的端口獲取到請求的流,轉化為二進制文件,根據協議獲取請求的信息,進行處理并將結果寫入XML中返回。

      4. 傳輸協議是?

      Http。

      SOAP

      SOAP原意為Simple Object Access Protocol,是一個用于分布式環境的、輕量級的、基于XML進行信息交換的通信協議,可以認為SOAP是XML RPC的高級版,兩者的原理完全相同,都是http+XML,不同的僅在于兩者定義的XML規范不同,SOAP也是Webservice采用的服務調用協議標準,因此在此就不多加闡述了。

      CORBA

      Common Object Request Broker Architecture(公用對象請求代理[調度]程序體系結構),是一組用來定義“分布式對象系統”的標準,由OMG(Object Menagement Group)作為發起和標準制定單位。CORBA的目的是定義一套協議,符合這個協議的對象可以互相交互,不論它們是用什么樣的語言寫的,不論它們運行于什么樣的機器和操作系統。

      CORBA在我看來是個類似于SOA的體系架構,涵蓋可選的遠程通信協議,但其本身不能列入通信協議這里來講,而且CORBA基本淘汰,再加上對CORBA也不怎么懂,在此就不進行闡述了。

      JMS

      JMS呢,是實現java領域遠程通信的一種手段和方法,基于JMS實現遠程通信時和RPC是不同的,雖然可以做到RPC的效果,但因為不是從協議級別定義的,因此我們不認為JMS是個RPC協議,但它確實是個遠程通信協議,在其他的語言體系中也存在著類似JMS的東西,可以統一的將這類機制稱為消息機制,而消息機制呢,通常是高并發、分布式領域推薦的一種通信機制,這里的主要一個問題是容錯(詳細見ErLang論文)。

      來看JMS中的一次遠程通信的過程:

      1. 客戶端將請求轉化為符合JMS規定的Message;

      2. 通過JMS API將Message放入JMS Queue或Topic中;

      3. 如為JMS Queue,則發送中相應的目標Queue中,如為Topic,則發送給訂閱了此Topic的JMS Queue。

      4. 處理端則通過輪訓JMS Queue,來獲取消息,接收到消息后根據JMS協議來解析Message并處理。

      回答問題:

      1. 傳輸的標準格式是?

      JMS規定的Message。

      2. 怎么樣將請求轉化為傳輸的流?

      將參數信息放入Message中即可。

      3. 怎么接收和處理流?

      輪訓JMS Queue來接收Message,接收到后進行處理,處理完畢后仍然是以Message的方式放入Queue中發送或Multicast。

      4. 傳輸協議是?

      不限。

      基于JMS也是常用的實現遠程異步調用的方法之一。

    posted @ 2009-08-15 14:59 jadmin 閱讀(101) | 評論 (0)編輯 收藏
    僅列出標題
    共50頁: First 上一頁 7 8 9 10 11 12 13 14 15 下一頁 Last 
    主站蜘蛛池模板: fc2成年免费共享视频网站| 国产精品黄页在线播放免费| 美女视频黄a视频全免费网站色| 91精品手机国产免费| 亚洲第一福利网站| 99精品视频在线观看免费| 青青草原亚洲视频| 九九热久久免费视频| 亚洲综合无码AV一区二区| 国产精品hd免费观看| 亚洲男女内射在线播放| 人妻巨大乳hd免费看| 国产亚洲精品资在线| 中文字幕一区二区三区免费视频| 久久亚洲国产成人影院网站| 亚洲免费人成在线视频观看| 亚洲AV成人一区二区三区AV| 国产91色综合久久免费分享| 国产亚洲福利在线视频| 午夜dj免费在线观看| 免费精品视频在线| 亚洲精品国产精品乱码不99| 67194成手机免费观看| 亚洲另类春色国产精品| 日韩免费在线观看| 麻豆69堂免费视频| 亚洲熟妇无码乱子AV电影| 无码A级毛片免费视频内谢| 亚洲成a人片在线观看中文app| 成年女人18级毛片毛片免费观看| 国产精品亚洲一区二区在线观看| 久久亚洲国产成人精品无码区| 99精品一区二区免费视频| 亚洲国产91在线| 免费国产在线观看不卡| 日本中文字幕免费高清视频| 亚洲国产无线乱码在线观看| 国产亚洲综合色就色| 青春禁区视频在线观看直播免费| 国产精品九九久久免费视频| 亚洲国产福利精品一区二区|