帝国软件
  设为首页 加入收藏 关于我们
 
解密帝国网站管理系统
栏 目:
 
您的位置:首页 > 技术文档 > JAVA编程
Web Service 和 J2EE
作者:佚名 发布时间:2005-04-02 来源:不详
 
  在前面的文章中,我们
解了一些高级的Web servic
全。本文中我们将开始研究
已经掌握了如何开发、配置和使
e概念,这其中包括状态Web ser
Web service是如何在J2EE环境
用简单的 Web service。我们也了
vice、远程调用和Web service 安
中工作的。
  理解Web Services和J2EE 集成原理                              
  当今,许多应用将三层
service几乎使它们被普遍
组件体系结构使得这个过程
业务逻辑作为标准的J2EE组件来
应用,同时这也提供了一种集成
变得相对容易。
实现。将这些组件用于SOAP Web
这些组件的简单机制。J2EE的标准

  本文中,我们将解释如
Java Message Service (JM
Beans(EJBs),这是因为EJB
方法也适用于其他的J2EE组
何使J2EE组件以Web service的
S)可靠地发送SOAP报文。我们将
s是业务逻辑实现中使用最为广
件,例如JDBC数据源和JMS队列
形式发布,同时也会演示如何应用
主要讨论Enterprise Java
泛的J2EE组件,当然所有演示过的

  标准的J2EE处理                                                            
  我们首先来概括一下有关J2EE平台的
用JNDI查找服务器方的J2EE组件。例如,
客户端代理。客户端在后面将使用这个代
发生在RMI上。
一些重要事实。传统上来说,J2EE客户端应用程序使
客户端应用程序查找JNDI中的EJB引用并收到一个EJB
理来访问EJB组件。所有的J2EE通信在正常情况下都

  

  图 1:标准的JNDI使用                                                   
  J2EE - 基本方法                                                       
  有两种通过SOAP访问J2EE资源的方法
在EJB周围创建Web service wrapper。该
接映射到单独EJB并且还需要J2EE 组件的
码实现透明集成的方法。这种方法的主要
service的形式动态发布。这种方法允许
有的基于SOAP的J2EE应用。
。我们首先来看看最显而易见的方法,这种方法可以
方法特别适合于这样的情况:Web service应用不直
附加信息。我们在第二个例子中将介绍一种以较少代
目标就是将现有的J2EE应用尽可能迅速的以Web
我们无须编写或者修改任何代码就可以高效的访问现

  简单的股票报价EJB Wrapper 演示样本                                
  在这个演示样本中,我
无状态session bean:股票
应用。各种实现之间只存在
。这种方法要求所实现的We
到SOAP与 RMI之间的桥梁作
成适合EJB 组件的RMI 请求
J2EE资源。为了用该方法来
除孤立的有状态资源。
们将介绍EJB wrapper Web serv
报价EJB。该方法虽然很简单但
一些细微的区别,这些实现通常
b service包含一个或者多个现
用。客户端将SOAP请求到这个wr
。我们特别推荐将该方法主要用
访问有状态的资源,您将需要设

ice 方法,该方法可以访问简单的
是却在许多SOAP框架中得到了广泛
会与开发流程的自动化水平相吻合
有的J2EE 组件。而这个wrapper起
apper,然后由wrapper把请求转换
于诸如无状态Bean之类的无状态
置额外的生命周期服务来正确地删

  我们首先需要执行一些简单的安装和配置步骤。                                   
  注意:如果您还没有下载用来创建指
需要下载演示样本的源代码demo sources
c:wasp_demo目录。指导实例中所提到的
得到的src子目录中找到。它们位于com.s
程序都位于bin子目录。尽管您并不需要
烈推荐您这样做。
导实例的软件,请参考30分钟创建WebService。您还
。 这里我们假设您已经把这个文件拷贝到
所有Java源代码都可以在解压缩文件demo sources后
ystinet.demos.包中。同样,演示样本中的所有脚本
下载和使用该软件来理解这些文章,但是我们还是强

  额外的安装步骤:我们
website下载所需的软件)
行时间以便使用Sun J2EE R
目录中的 env.bat脚本程序
将在J2EE环境中使用Sun J2EE 1
。在安装完J2EE 1.3 RI之后,
I。这里提到的配置可以通过修
来实现。首先将下面一行变为注
.3。(您可以从Sun的 Java
您需要配置WASP Web service 运
改WASP Advanced高级安装的Bin子
释(在该行开始之处添加rem):
  set INSTALLATION_TYPE=standalone              
  然后删除同一文件中的下面一行的注释:                                         
  set INSTALLATION_TYPE=j2ee                          
  您需要修改位于c:was
WASP_HOME和WASP_DEMO设定
p_demobin directory的env.ba
正确的取值。
t文件。请为环境变量J2EE_HOME,


  一旦您完成了上面提到
J2EE 服务器并运行WASP We
的安装和配置步骤,请通过使用
b service。
startJ2EE 和 startserver启动


  下一步,运行deploy_j2ee 来编译Ja
va源代码并配置我们在演示样本使用的EJBs。

  注:在配置EJB之后,您需要重新启动J2EE 服务器。                       

  如果您查看com.systinet.demos.sto
StockQuoteHome类 和StockQuoteBean 类
状态session bean。我们已经通过调用de
J2EE的管理工具对所有的EJBs进行了正确
动管理工具。
ck包中的Java源代码,就会发现StockQuote,
使用一个简单getQuote方法实现了一个相当简单的无
ploy 脚本程序对这个EJB进行了配置。您要确保使用
配置。调用演示样本bin目录下的J2EEAdmin程序将启


  现在我们来集中关注图
法包含一个简单的EJB 调用
它将在EJB上调用方法 getQ
端。在下面的代码中您可以
2中wrapper Web service 的实
。首先,它从JNDI得到EJB的有
uote,然后删除该EJB。最后,
看到这些步骤:
现。它实现了方法getQuote,该方
效引用并创建一个EJB实例。然后
调用结果返回到Web service 客户


  package com.systinet.demos.stock;            
  import javax.naming.InitialContext;        
  import javax.naming.Context;                      
  import javax.naming.NamingException;      
  import java.rmi.RemoteException;              
  public class StockQuoteService {              
   public double ge
tQuote(String symbol) throws
Exception {
   // get the JNDI initial context
   System.err.println("
;Getting J2EE initial context");
   Context jndi
Context = new InitialContext
();
   // lookup the EJB home                  
   System.err.p
rintln("Looking up EJB
Home");
   Object homeRef = jndiCon
text.lookup("Stock");
   StockQuoteHome home =                   
   (StockQuoteH
ome)javax.rmi.PortableRemote
Object.narrow(
   homeRef, StockQuoteHome.class);
   // create the EJB instance          
   System.err.println("
;Creating EJB");
   StockQuote ejb = home.create();
   // call the getQuote method        
   System.err.p
rintln("Calling getQuot
e");
   double quote
= ejb.getQuote("SUNW&q
uot;);
   System.err.println("
;SUNW "+quote);
   // remove the EJB                            
   System.err.p
rintln("Removing EJB&qu
ot;);
   ejb.remove();                                    
   return quote;                                    
   }                                                                    
                                                                         
  }                                                                            
  图 2:简单的 Web service EJB wrap
per (StockQuoteService.java)
   现在我们可以通过运行deploy_serv
后,运行run_wrapper 脚本程序来启动We
service来调用EJB。
ice 脚本程序来配置EJB wrapper Web services。然
b service 客户端。客户端将会通过wrapper Web

  注:为了说明wrapper
的应用通常会复杂一些。wr
情况下,wrapper服务通常
方法的基本原来,我们尽可能使
apper 服务常用于集成多个EJBs
会显现不同的编程接口而不是原
这个演示样本简单。然而,实际中
的功能和其他的J2EE资源。在这些
始的beans。
  透明的J2EE 集成integration                                    
  访问J2EE资源的另一方
一个wrapper服务或者改变
通过因特网访问J2EE资源,
法就是使用透明的集成框架。这
最初的J2EE代码。如果您希望SO
这种方法就非常有用了。
里,透明是指我们没有必要来编写
AP客户端利用现有的J2EE资源或者

  下面所描述的透明的J2EE 集成框架
问J2EE资源的抽象机制。正如我们先前所
的lookup方法,而客户端的JNDI提供者把
JNDI给客户端返回一个 J2EE代理。客户
个示例中,我们所使用的客户端JNDI的提
,当客户端使用这个提供者发布一个JNDI
。 这个JNDI web service将在应用程序
JNDI web service将一个基于SOAP的客户
能够使用这个远程引用来调用J2EE资源。
代理会把请求重新定向到实际的J2EE资源
进行修改。只需在客户端实施一个配置更
将充分利用JNDI框架的优势,这种优势提供了一种访
说的,在J2EE的正常流程中,J2EE客户端将调用JNDI
这个请求通过RMI传递给J2EE服务器中的JNDI服务。
端使用这个代理,通过RMI远程调用J2EE资源。在这
供者支持SOAP而不支持RMI。正如您在图3中所看到的
请求时,该请求将通过SOAP发送到JNDI web service
服务器JNDI中进行实际的查找并获得J2EE代理。然后
端远程引用返回给J2EE代理。客户端应用程序此时就
每一种方法调用都将通过SOAP传递给J2EE代理。J2EE
。您可能会注意到J2EE资源或者客户端代码都不需要
改而已,即指向基于SOAP的JNDI提供者。
  

  图 3: Web service有权使用JNDI                             
  注:大多数Web service运行时间服
。因此,调用重定向方法将会非常迅速,
务器和应用程序服务器是在相同的上下文环境中运转
并且不会降低性能。
  这种方法也适用于非Ja
任何的SOAP客户端都能够充
端可以调用JNDI Web servi
va的客户端。因为JNDI Web ser
分利用它的透明调用框架。例如
ce上的方法查询并且获得所请求
vice是一种标准的Web service,
, Microsoft Visual Basic 客户
的J2EE资源的Web service代理。
  对于在Web service运
集。当客户端应用程序显式
。但是在松散连接条件下的
要跟踪并管理所有动态创建
资源既快速又透明的SOAP访
无状态和有状态的session
JDBC和其他的J2EE资源。对
合于通过SOAP对现有系统提
行时间创建的所有组件,JNDI W
丢弃远程组件时,根据相关请求
Web services并不能保证做到适
资源的原因。这种方法的主要优
问方式。这里所说的JNDI中的J2
beans、entity beans和 messag
这些J2EE资源无需进行任何修改
供快速而又简便的访问。我们来
eb service将执行自动远程碎片账
,这些组件中的大多数也会被丢弃
当删除。这就是LifeCycle服务需
势就在于它提供了对JNDI中的J2EE
EE资源包括所有类型的EJB组件 (
e-driven beans),还有JMS、
和包装。很显然,这种方法非常适
看一个具体的示例吧。
  透明的J2EE集成演示样本                                                    
  这个演示样本将说明一
EJB。
个Web service调用了运行在Sun

的 J2EE 1.3 引用实现引擎中的

  我们首先来检验一下服
个标准的有状态session be
务器端的EJB代码。正如您在下
an,它将保存简单计算器的状态
面的代码列表中所看到的,这是一


  package com.systinet.demos.counter;        
  import javax.ejb.CreateException;            
  import javax.ejb.SessionBean;                    
  import javax.ejb.SessionContext;              

  import javax.ejb.Ses
sionSynchronization;
  public class CounterEJB implemen
ts SessionBean {
   private SessionContext context;        
   private int count = 0;                          
   /**                                                                
   * No argument c
onstructor required by conta
iner.
   */                                                                
   public CounterEJB() {                            
   }                                                                    
   /**                                                                
   * Create method
specified in EJB 1.1 sectio
n 6.10.3
   */                                                                
   public void ejbCreate() {                    
   }                                                                    
   /* Methods required by Sessi
onBean Interface. EJB 1.1 section 6.5.1. */
   /**                                                                
   * @see javax.ej
b.SessionBean#setContext(jav
ax.ejb.SessionContext)
   */                                                                
   public void setSessionContex
t(SessionContext context){
   this.context = context;                
   }                                                                    
   /**                                                                

   * @see javax.ej
b.SessionBean#ejbActivate()
   */                                                                
   public void ejbActivate() {                
   }                                                                    
   /**                                                                

   * @see javax.ej
b.SessionBean#ejbPassivate()
   */                                                                
   public void ejbPassivate() {              
   }                                                                    
   /**                                                                
   * @see javax.ejb.SessionBea
n#ejbRemove()
   */                                                                
   public void ejbRemove() {                    
   }                                                                    
   public long getCount() {                      
   return count++;                                
   }                                                                    
  }                                                                            
  图 4: 简单的EJB计数器——服务器端EJB代码                            
  其他的 EJB资源就相当
。我们已经在第一个演示样
们并不需要将任何特定的We
明显了。您可以看到Counter远
本中通过调用deploy_j2ee命令
b service配置为Web service
程和CounterHome本地接口的代码
,并对EJB进行了配置。请注意我
运行时间。
  客户端应用程序是一个标准的EJB客
使用了不同的JNDI属性。
户端,不同之处就是它在方法getInitialContext中

  package com.systinet.demos.counter;        
  import javax.naming.InitialContext;        
  import javax.naming.Context;                      
  import javax.naming.NamingException;      
  import java.rmi.RemoteException;              
  public class CounterClient {                      
   public CounterClient() {                      
   }                                                                    
   public static void main(Strin
g [] args){
   try {                                                    

   // get th
e JNDI initial context
   System.err.println(&q
uot;Getting J2EE initial context");
   Context jndiContext =
getInitialContext();
   // lookup the EJB home            
   System.err.println(&q
uot;Looking up EJB Home");
   Object homeRef = jndi
Context.lookup("Counter");
   CounterHome home =                   
  (CounterHome)javax.rmi.PortableR
;
emoteObject.narrow(homeRef, CounterHome.class)

   // create the EJB instance    
   System.er
r.println("Creating EJB
");
   Counter ejb = home.create();
   System.ou
t.println("Calling coun
t "+ejb.getCount());
   System.out.println(&q
uot;Calling count "+ejb.getCount());
   System.out.println(&q
uot;Calling count "+ejb.getCount());
   // remove the EJB                      
   System.err.println(&q
uot;Removing EJB");
   ejb.remove();                              
                                                                 
   }                                                           
   catch(java.rmi.RemoteExc
eption re) {
   re.printStackTrace();            
   }                                                            
   catch(Throwable t) {                      
   t.printStackTrace();              
   }                                                            
                                                                 
   }                                                                    
                                                                             
   static public Co
g.NamingException {
ntext getInitialContext() th

rows javax.namin

   java.util.Properties jnd
iProperties = new java.util.Properties();
   jndiProperties.put("
;java.naming.factory.initial",
  "com.idoox.jndi.InitialCont              
  extFactoryImpl");                                  
   jndiProperti
es.put("java.naming.pro
vider.url","
  http://localhost:6060");                    
   return new InitialContex
t(jndiProperties);
   }                                                                    
  }                                                                            
  图 5:简单的EJB客户端计数器(CounterClient.java)      
  请注意为了简单起见,
重新定向到JNDI Web servi
java.naming.provider.url
是将其代码固化在客户端应
我们固化了所有的JNDI特定参数
ce: 参数java.naming.factory
。这些参数通常是存储在应用程
用程序中。这种情况下,就没有
。需要定义两个参数来把JNDI查询
.initial 和 参数
序的properties属性文件中,而不
必要对代码再次进行编译。
  下一步就是使用run脚本来编译和运
getCount被调用了三次。客户端应用程序
您也会看到状态(计数器的取值)也得到了
行J2EE 客户端应用程序。您将会看到EJB的方法
与服务器方的所有通信都是通过 SOAP报文实现的。
适当的保存和处理。
  通过JMS发送可靠的SOAP报文                                              
  当今,大多数的Web service使用HTT
要优势就是通过HTTP代理和防火墙来实现
能满足需求。HTTP 具有单向性并且缺少
且,在异步报文的路由选择中,HTTP所提
是使用JMS传送SOAP报文。JMS可以为企业
保证的报文传送、报文处理中的入队和出
优于HTTP协议的性能和稳定性。
P传输协议进行通信。HTTP适合于多种应用。它的主
应用集成的灵活性。 但是对一些应用而言, HTTP不
企业级的功能,例如可靠性、持久性和事务处理。而
供的支持也不是很理想。表述这些问题的一种方法就
级应用的通信提供充分的益处。这是因为JMS支持有
队以及同步报文和异步报文的语义。JMS也可以提供

  下一个示例,SOAP是具
的Web service,但是这次
一下传送给客户端lookup
有真正意义上的传输协议独立性
我们将要通过JMS发送SOAP消息
方法的查找URL即可:
。我们将访问在第一个示例中开发
。实现非常简单。我们只需要修改

  package com.systinet.demos.jms;                
  import org.idoox.wasp.Context;                  
  import org.idoox.webservice.clie
nt.WebServiceLookup;
  public final class StockClient {              
   /**                                                                    
   * @param args not used.                        
   */                                                                    
   public static void main( Str
ing[] args ) throws Exception {
  System.setProperty(&
quot;java.naming.factory.ini
tial",
  "com.idoox.jndi.InitialCont
extFacto
  ryImpl");                                               
   System.setProp
erty("java.naming.provi
der.url","
  http://localhost:6060");                    
   System.setProperty("i
"true");
doox.demo.transport.j2ee",

   // lookup service                                
   WebServiceLookup lookup =               
  (WebServiceLookup)Context.getIns
tance(Context.WEBSERVICE_LOOKUP);
   // bind to StockQuoteService          
   StockQuoteServ
oxy)lookup.lookup
iceProxy quoteService = (Sto

ckQuoteServicePr

  ("jms://jms/Que
ue@jms/QueueConnectionFactor
y~

  /StockEJBService/&qu
ot;,StockQuoteServiceProx
  y.class);                                                            
   // use StockQuoteService                  
   System.out.println("G
etting SUNW quote");
   System.out.println("-
-----------------------");
   System.out.pri
("SUNW"));
ntln("SUNW "+quote

Service.getQuote

   System.out.println("");
   }                                                                    
  }                                                                            
  图 6: 简单的JMS客户端(StockClient.java)              
  我们通过运行run_jms
提供完全透明的映射。所以
services、远程引用和 SOA
脚本程序来编译和运行JMS客户
,无需修改Java代码,前面提到
P故障等)都可以在JMS之上正常
端示例。SOAP框架为底层传输协议
的所有功能(例如,有状态Web
运转。
  注:预先配置Web serv
ice运行时间来侦听jms/Queue J
MS 队列中的SOAP报文。
  删除                                                                          
  既然我们完成了所有的
用程序服务器和Web servic
演示样本,请使用undeploy_j2e
e运行时间的Web service中删除
e 和 undeploy_service 脚本从应
EJB。


                                                 
  
评论】【加入收藏夹】【 】【打印】【关闭
※ 相关链接
 ·组件对象开发Web应用的实例分析  (2005-03-12)
 ·规划Web开发战略  (2005-03-12)
 ·通过asp入侵web server,窃取文件  (2005-03-12)
 ·建立Web站点  (2005-03-12)
 ·新增一个Web页面  (2005-03-12)
 ·asp实现在web中显示电子表格数据  (2005-03-12)
 ·asp实现在web中显示电子表格数据  (2005-03-12)
 ·asp实现在web中显示电子表格数据  (2005-03-12)
 ·asp实现在web中显示电子表格数据  (2005-03-12)
 ·Carello Web 使 ASP 源码暴露 (A  (2005-03-12)

   栏目导行
  PHP编程
  ASP编程
  ASP.NET编程
  JAVA编程
   站点最新
·致合作伙伴的欢迎信
·媒体报道
·帝国软件合作伙伴计划协议
·DiscuzX2.5会员整合通行证发布
·帝国CMS 7.0版本功能建议收集
·帝国网站管理系统2012年授权购买说
·PHPWind8.7会员整合通行证发布
·[官方插件]帝国CMS-访问统计插件
·[官方插件]帝国CMS-sitemap插件
·[官方插件]帝国CMS内容页评论AJAX分
   类别最新
·谈谈JDBC
·JDBC专题介绍
·JDBC接口技术
·利用weblogic的POOL(连接池)连接
·Jsp中调用Oracle存储过程的小例子
·JSP数据库操作例程
·JSP数据库连接大全
·用连接池提高Servlet访问数据库的效
·一种简单JDBC连接池的实现
·数据库连接池Java实现小结
 
关于帝国 | 广告服务 | 联系我们 | 程序开发 | 网站地图 | 留言板 帝国网站管理系统