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里是怎么做的。