6.6.1  用JAX-RPC应用一个Web Service

为了要使用这个Babel Fish web service,得创建一个定义这个服务的接口。查看一下WSDL,你会发现Babel Fish web service只有一个操作叫做:BabelFish。这个操作有两个参数:一个是字符串,表示翻译模式(参考工具条);另一个也是字符串,表示原始的尚未翻译的文本。它返回一个包含了翻译后文本的字符串。BabelFishRemote.java(程序清单6.4)展示了定义这个服务的远程接口。

 程序清单6.4  Bable Fish web service的远程服务接口

 

  package com.springinaction.chapter06.babelfish;

 

  import java.rmi.Remote;

  import java.rmi.RemoteException;

 

  public interface BabelFishRemote extends Remote {

    public String BabelFish(String translationMode,

         String sourceData) throws RemoteException;

  }

n

工具条:翻译模式由两种语言代码组成,用下划线(_)分隔。一些正确的语言代码是:英语用“en”,法语用“fr”,德语用“dr”,西班牙语用“es”。在下划线之前的语言代码表示原始文本的语言,下划线之后的语言代码表示原始文本要翻译成的目标语言。例如,一个“de_en”的翻译模式将把德语文本翻译到英语文本。

 

BabelFishRemote接口包含了一个方法:BabelFish()。这个方法名是从WSDL的操作名中过来的。不巧的是,这个web service以一个大写的“B”开始,不像Java规范中,方法名用小写字母开始。下面的代码展示了如何使用一个传统的JAX-RPC(也就是说,没有Spring的帮助)来获得一个Babel Fish服务的引用。

 

  String wsdlDocumentUrl =

        "http://www.xmethods.com/sd/2001/BabelFishService.wsdl";

  String namespaceUri =

        "http://www.xmethods.net/sd/BabelFishService.wsdl";

  String serviceName = "BabelFishService";

  String portName = "BabelFishPort";

  QName serviceQN = new QName(namespaceUri, serviceName);

  QName portQN = new QName(namespaceUri, portName);

 

  ServiceFactory sf = ServiceFactory.newInstance();

  Service service =

        sf.createService(new URL(wsdlDocumentUrl), serviceQN);

 

  BabelFishRemote babelFish = (BabelFishRemote)

        service.getPort(BabelFishRemote.class, portQN);

手头有了一个指向这个服务的引用,你就能用它来翻译任何你想翻译的文本。例如,把“Hello world”从英语(en)翻译到西班牙语(es):

 

  String translated = babelFish.BabelFish("en_es", "Hello World");

 

同样,可以使用下面语句把西班牙语(es)翻译为法语(fr):

 

  String translated = babelFish.BabelFish("es_fr", "Hola Mundo");

 

或者从法语(fr)到德语(de):

 

  String translated = babelFish.BabelFish("fr_de", "Bonjour Monde");

 

Babel Fish服务是很有趣的,但是标准JAX-RPC方法的一个问题就是它引入了一大堆代码,仅仅是为了查找这个babel fish服务。为了让它变得更简单些,可以用JSR-109(实现企业级Web Service,或Implementing Enterprise Web Services)建议的方法,用JNDI来检索web service:

 

  Context ic = new InitialContext();

  BabelFishService babelFishService =

        (BabelFishService) ic.lookup("java:comp/env/service/BabelFish");

  BabelFishRemote babelFish =

        (BabelFishRemote) babelFishService.getBabelFishPort();

 

但是,即使这个JNDI版本比原来简练了,它仍然让客户端负责获得它自己的指向这个服务的引用。这样做的话,就违反了反转控制的精神。并且,它把处理RemoteException的重担放在客户端上了。

现在,你已经看到使用JAX-RPC访问web service的常规方法了,让我们再看看在Spring里是怎么做的。