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 阅读(76) | 评论 (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 阅读(86) | 评论 (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 阅读(94) | 评论 (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 阅读(86) | 评论 (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 阅读(155) | 评论 (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 阅读(94) | 评论 (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 阅读(87) | 评论 (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 阅读(237) | 评论 (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 阅读(85) | 评论 (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 阅读(96) | 评论 (0)编辑 收藏
仅列出标题
共50页: First 上一页 7 8 9 10 11 12 13 14 15 下一页 Last