编写服务代码, 如 /* * Account.java */ package com.hcycom.n7; public class Account { public static int balance = 5000; // 存款 public String deposit (int amount

Similar documents
智力测试故事

30,000,000 75,000,000 75,000, (i) (ii) (iii) (iv)

I. 1-2 II. 3 III. 4 IV. 5 V. 5 VI. 5 VII. 5 VIII. 6-9 IX. 9 X XI XII. 12 XIII. 13 XIV XV XVI. 16

奇闻怪录

Microsoft Word - John_Ch_1202

全唐诗50

施 的 年 度 維 修 工 程 已 於 4 月 15 日 完 成, 並 於 4 月 16 日 重 新 開 放 給 市 民 使 用 ii. 天 水 圍 游 泳 池 的 年 度 維 修 工 程 已 於 3 月 31 日 完 成, 並 於 4 月 1 日 重 新 開 放 給 市 民 使 用 iii. 元

2015年廉政公署民意調查

Microsoft Word - Entry-Level Occupational Competencies for TCM in Canada200910_ch _2_.doc

-i-

Microsoft Word - 强迫性活动一览表.docx


Microsoft Word - COC HKROO App I _Chi_ Jan2012.doc

EJB-Programming-4-cn.doc

对联故事

中国民用航空规章

RDEC-RES

(譯本)

全唐诗28

(b)

我国服装行业企业社会责任问题的探讨.pages


II II

<4D F736F F D20BB4FAA46BFA4B2C4A447B4C15F D313038A67E5FBAEEA658B56FAE69B9EAAC49A4E8AED72D5FAED6A977A5BB5F >

<D6D0B9FAB9C5CAB757512E6D7073>

財 務 委 員 會 審 核 2014 至 2015 年 度 開 支 預 算 的 報 告 2014 年 7 月

一、

Microsoft Word - Final Chi-Report _PlanD-KlnEast_V7_ES_.doc

Microsoft Word - MP2018_Report_Chi _12Apr2012_.doc

南華大學數位論文

李天命的思考藝術

皮肤病防治.doc

性病防治

中国南北特色风味名菜 _一)

全唐诗24

509 (ii) (iii) (iv) (v) 200, , , , C 57

我 非 常 希 望 该 小 组 的 建 议 尤 其 是 其 执 行 摘 要 能 受 到 将 于 2000 年 9 月 来 纽 约 参 加 千 年 首 脑 会 议 的 所 有 领 导 人 的 注 意 这 次 历 史 性 的 高 级 别 会 议 提 供 了 一 个 独 特 的 机 会 使 我 们 能 够

歡 迎 您 成 為 滙 豐 銀 聯 雙 幣 信 用 卡 持 卡 人 滙 豐 銀 聯 雙 幣 信 用 卡 同 時 兼 備 港 幣 及 人 民 幣 戶 口, 讓 您 的 中 港 消 費 均 可 以 當 地 貨 幣 結 算, 靈 活 方 便 此 外, 您 更 可 憑 卡 於 全 球 近 400 萬 家 特

中国石化齐鲁股份有限公司


_Chi.ps, page Preflight ( _Chi.indd )

2. 我 沒 有 說 實 話, 因 為 我 的 鞋 子 其 實 是 [ 黑 色 / 藍 色 / 其 他 顏 色.]. 如 果 我 說 我 現 在 是 坐 著 的, 我 說 的 是 實 話 嗎? [ 我 說 的 對 還 是 不 對 ]? [ 等 對 方 回 答 ] 3. 這 是 [ 實 話 / 對 的


「保險中介人資格考試」手冊

(TestFailure) JUnit Framework AssertionFailedError JUnit Composite TestSuite Test TestSuite run() run() JUnit

西施劇本_04Dec2003.doc

OOP with Java 通知 Project 4: 4 月 18 日晚 9 点 关于抄袭 没有分数

<4D F736F F D203938BEC7A67EABD7B942B0CAC15AC075B3E6BF57A9DBA5CDC2B2B3B92DA5BFBD542E646F63>

(i) (ii) (iii) (iv) (v) (vi) (vii) (viii) (ix) (x) (i) (ii)(iii) (iv) (v)

《小王子》 (法)圣埃克苏佩里 原著

穨學前教育課程指引.PDF

國立中山大學學位論文典藏.PDF

眼病防治

中国南北特色风味名菜 _八)

<4D F736F F D20B6ABD0CBD6A4C8AFB9C9B7DDD3D0CFDEB9ABCBBECAD7B4CEB9ABBFAAB7A2D0D0B9C9C6B1D5D0B9C9CBB5C3F7CAE9A3A8C9EAB1A8B8E C4EA33D4C23131C8D5B1A8CBCDA3A92E646F63>

「保險中介人資格考試」手冊

山东出版传媒招股说明书

- 2 - 获 豁 免 计 算 入 总 楼 面 面 积 及 / 或 上 盖 面 积 的 环 保 及 创 新 设 施 根 据 建 筑 物 条 例 的 规 定 4. 以 下 的 环 保 设 施 如 符 合 某 些 条 件, 并 由 有 关 人 士 提 出 豁 免 申 请, 则 可 获 豁 免 计 算 入

穨ecr2_c.PDF

電腦相關罪行跨部門工作小組-報告書

i

发展党员工作手册

i

39898.indb

目 录 院 领 导 职 责... 1 院 长 职 责... 1 医 疗 副 院 长 职 责... 1 教 学 副 院 长 职 责... 2 科 研 副 院 长 职 责... 2 后 勤 副 院 长 职 责... 3 主 管 南 院 区 副 院 长 职 责... 3 党 委 书 记 职 责... 4

(b) 3 (a) (b) 7 (a) (i) (ii) (iii) (iv) (v) (vi) (vii) 57

款 及 赔 偿 限 额 及 限 制 给 付 下 述 保 险 金, 但 有 关 医 疗 费 用 及 受 保 服 务 必 须 是 : i. 医 学 上 合 适 及 必 须 的, 及 ii. 由 医 疗 服 务 提 供 者 开 单 收 费 的, 及 iii. 符 合 通 常 惯 性 及 合 理 水 平 的

(i) (ii) (iii) (iv) (v) (vi) (vii) (viii) (ix) (x) (xi) 60.99%39.01%

Microsoft Word - NCH final report_CHI _091118_ revised on 10 Dec.doc

兒 童 會 4 摩 爾 門 經 本 教 材 專 為 8-11 歲 的 兒 童 設 計 耶 穌 基 督 後 期 聖 徒 教 會 台 北 發 行 中 心 印 行

<4D F736F F D205B345DB5D8AE4CACD AECAAFC5C1C9C1DCBDD0AB48A4CEB3F8A657AAED>

BPS6.0 Web服务集成和短流程功能使用手册

群科課程綱要總體課程計畫書

- 1 - ( ) ( ) ( )


Microsoft Word - 01.DOC

第 二 輯 目 錄.indd 2 目 錄 編 寫 說 明 附 : 香 港 中 學 文 憑 中 國 語 文 科 評 核 模 式 概 述 綜 合 能 力 考 核 考 試 簡 介 及 應 試 技 巧 常 用 實 用 文 文 體 格 式 及 寫 作 技 巧 綜 合 能 力 分 項 等 級 描 述 練 習 一

chp6.ppt

68003 (Project Unity TC)_.indb

Microsoft Word - 0B 封裡面.doc

nbqw.PDF

<4D F736F F D20CDF2B4EFB5E7D3B0D4BACFDFB9C9B7DDD3D0CFDEB9ABCBBECAD7B4CEB9ABBFAAB7A2D0D0B9C9C6B1D5D0B9C9CBB5C3F7CAE9A3A8C9EAB1A8B8E C4EA34D4C23137C8D5B1A8CBCDA3A92E646F63>

Microsoft Word - Panel Paper on T&D-Chinese _as at __final_.doc

untitled

江苏宁沪高速公路股份有限公司.PDF

绝妙故事

<4D F736F F D20B1B1BEA9D6B8C4CFD5EBBFC6BCBCB7A2D5B9B9C9B7DDD3D0CFDEB9ABCBBEB4B4D2B5B0E5CAD7B4CEB9ABBFAAB7A2D0D0B9C9C6B1D5D0B9C9CBB5C3F7CAE9A3A8C9EAB1A8B8E C4EA36D4C23230C8D5B1A8CBCDA3A92E646F63>

Hong Kong Filmography Vol VIII ( )

5498 立 法 會 2013 年 3 月 27 日 李 國 麟 議 員, S.B.S., J.P. 林 健 鋒 議 員, G.B.S., J.P. 梁 君 彥 議 員, G.B.S., J.P. 黃 定 光 議 員, S.B.S., J.P. 湯 家 驊 議 員, S.C. 何 秀 蘭 議 員 李

Microsoft Word - report final.doc

榫 卯 是 什 麼? 何 時 開 始 應 用 於 建 築 中? 38 中 國 傳 統 建 築 的 屋 頂 有 哪 幾 種 形 式? 40 大 內 高 手 的 大 內 指 什 麼? 42 街 坊 四 鄰 的 坊 和 街 分 別 指 什 麼? 44 北 京 四 合 院 的 典 型 格 局 是 怎 樣 的

尿路感染防治.doc

心理障碍防治(下).doc

1.JasperReport ireport JasperReport ireport JDK JDK JDK JDK ant ant...6

H

Microsoft Word - Paper on PA (Chi)_ docx

JavaIO.PDF

Page i

C Ann.indd

捕捉儿童敏感期

Transcription:

使用 AXIS( 版本 1.4) 的方法 邢飞 先配置好 JDK 和 Tomcat 本文中使用的是 JDK 5.0( 源代码是 1.4 的 ) Tomcat 是 5.0.28 下载 AXIS 1.4, 地址 http://ws.apache.org/ 安装 AXIS 解压开 axis 1_4.zip, 将 axis 1_4/webapps/axis 拷贝到 $TOMCAT_HOME/webapps/ 下启动 tomcat, 打开页面 http://localhost:8080/axi s 页面正常, 表示 axis 安装正确 I

编写服务代码, 如 /* * Account.java */ package com.hcycom.n7; public class Account { public static int balance = 5000; // 存款 public String deposit (int amount) { String ret = "success"; if(amount > 0){ balance += amount; ret = "success"; else { return ret = "failure"; ret; // 取款 public String withdraw (int amount) { String ret = "success"; if(amount > 0 && amount <= getbalance()){ balance = amount; ret = "success"; else { ret = "failure"; return ret; // 获取余额 public int getbalance () { return balance; 需要发布的方法为 deposit, withdraw, getbalance 将编译好的 Account.class 文件放在文件夹 $TOMCAT_HOME/webapps/axis/WEB INF/classes/com/hcycom/n7 如果使用 IDE, 可以将输出文件夹设为 $TOMCAT_HOME/webapps/axis/WEB INF/classes 中 II

编写部署描述符 /home/xingfei/axis/ deploy.wsdd 内容如下 <deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"> <service scope="session" name="account " provider=" java:rpc "> <parameter name="classname" value=" com.hcycom.n7.account "/> <parameter name="allowedmethods" value=" *"/> </service> </deployment> 注意红色部分, account 表示服务的名称 java:rpc 表示调用服务的方法 com.hcycom.n7.account 表示服务要调用的类的名称 * 表示要公布的方法, 也可以公布一个类的某几个方法, 使用逗号隔 III

部署服务 account, 将 axis 所需 jar 文件全部加到 classpath 中, 执行以下命令 得到结果 <Admin>Done 表示部署成功 processing</admin> 也可以在 IDE 中使用如下方法部署 public class Deploy { % java org.apache.axis.client.adminclient \ public static void main(string[] args) { String[] arguments = { /home/xingfei/axis/ deploy.wsdd" ; /home/xingfei/axis/ deploy.wsdd org.apache.axis.client. AdminClient.main(arguments); IV

编写客户端调用代码, 如下 package com.hcycom.n7; import javax.xml.namespace.qname; import org.apache.axis.client.call; import org.apache.axis.client.service; public class AccountClient { public static void main(string[] args) { String endpoint = "http://localhost:8080/axis/services/account"; try { Service service = new Service(); Call call = (Call) service.createcall(); call.settargetendpointaddress( new java.net.url(endpoint) ); call.setoperationname(new QName("http://soapinterop.org/", "deposit ")); // 上面设置了操作为 deposit, 这里意思是存 300 String ret = (String)call.invoke(new Object[]{new Integer(300)); if(ret.equals("success")) { System.out.println("Deposit operation has been successfully done"); call.setoperationname(new QName("http://soapinterop.org/", "getbalance ")); // 操作为获取余额, 这里得到整型的余额数 Integer balance = (Integer)call.invoke(new Object[0]); System.out.println("Now the balance is " + balance.intvalue()); else if(ret.equals("failure")) { System.out.println("Deposit operation has done something wrong"); catch (Exception e) { System.err.println(e.toString()); 其中红色部分为实际调用 account 服务的代码 V

以上所写的, 只适用于简单情况 : 输入参数和输出结果都是基本类型 但是如果输入参数和输出结果中有我们自定义的复杂类型的话, 就会出错 因为客户端和服务器端使用的是 SOAP 消息进行通信 发送方将 Java 对象序列化为 XML, 而接收方又将 XML 反序列化成 Java 对象 双方应该知道 Java 对象和 XML 之间是如何对应的, 才能 正确的工作 AXIS 可以在配置文件中使用 <beanmapping>,<typemapping> 和反序列化 下面是一个例子 : <typemapping deserializer =" /> org.apache.axis.encoding.ser.beandeserializerfactory" encodingstyle=" http://schemas.xmlsoap.org/soap/encoding/" qname ="ns5:contact" serializer =" org.apache.axis.encoding.ser.beanserializerfactory" type ="java:com.hcycom.user.contact" xmlns:ns5="http://www.hcycom.com/n7/user" 来说明 Java 对象如何序列化 其中 type 指我们要处理的 Java 对象 serializer,deserializer 指将这个 Java 对象进行序列化和反序列化的 工具 类 qname 指的是这个 Java 对象的命名空间 这些可以自己写, 也可以由 AXIS 自动帮我们完成, 下面介绍一个综合的例子, 看看 AXIS 如何 为我们自动化的生成这些代码的 例子是一个非常简单的用户管理服务 可以添加, 删除和查看用户的信息 用户有 name,age,sex 和 contact 字段, 而 contact 又是一个 bean, 由 phone 和 email 两个字段 UserManager 是服务的定义, 它定义了对 User 的操作 以下将详细说明 VI

服务定义你要向外提供什么样的服务, 可以先写一个 interface 来描述它 这个 interface 必需继承自 java.rmi.remote, 而且每个方法必需抛出 java.rmi.remoteexception 本例中的服务定义为 : package com.hcycom.user; import import java.rmi.remote; java.rmi.remoteexception; public interface UserManager extends Remote { /** * add a user * 输入部分有复杂类型 */ public int adduser(user user) throws RemoteException ; /** * delete a user */ public int deleteuser(string name) throws RemoteException ; /** * get all the users * 输出为复杂类型 */ public User[] getallusers() throws RemoteException ; /** * get a user by name * 输出为复杂类型 */ public User getuser( String name) throws RemoteException ; 注意, 红色部分是必需的, 不然 AXIS 将不认识这个服务 VII

其中 User 的定义为, 一个标准的 JavaBean package com.hcycom.user; public class User { private String name; private int age; private int sex; private Contact contact; public User() { super();... getters and setters Contact 定义, 也是一个标准的 JavaBean package com.hcycom.user; public class Contact { private String phone; private String email; public Contact() { super();... getters and settters 这两个类都是标准的 JavaBean: 都有默认的构造方法和符合命名规范的 getters 和 setters VIII

生成 WSDL 文件 WSDL 是对服务的描述, 比如服务的名称, 能够进行的操作, 和输入 / 输出的参数 axis 所需的 jar 文件全都包含到 classpath 里边, 然后执行如下命令 java cp.:$axis_classpath o UserManager.wsdl P UserManagerPortType b UserManagerSoapBinding org.apache.axis.wsdl.java2wsdl l http://localhost:8080/axis/services/usermanager n http://www.hcycom.com/n7/user pcom.hcycom.user=http://www.hcycom.com/n7/user y rpc com.hcycom.user.usermanager 参数含义如下 o, output <WSDL file> 指定输出的 WSDL 文件名 若没有指定, 一个适当的默认 WSDL 文件名将被写到当前目录 l, location <location> 指定 Web 服务位置的 URL 最后的斜线或反斜线后的名字是服务端口(service ( 除非被 s 选项覆盖 ) 服务端口的地址位置属性被分配为该指定值 port) 的名字 P, porttypename 指定 porttype 元素的名字 如果未指定, 则使用 class of porttype 的名字 b, bindingname <name> 指定 binding 元素的名字 若未指定, 使用值 serviceportname + "SOAPBinding" n, namespace <target namespace> 指定生成的 WSDL 的目标名称空间 p, PkgtoNS <package> <namespace> 指定包结构到命名空间的映射 若遇到一个没有指定命名空间映射的包, 则 Java2WSDL 将生成 一个适当的命名空间名 这个选项可以指定多次 y, style <argument> 指示 WSDL 文档的风格, 有 DOCUMENT, RPC 和 WRAPPED 三种 默认为 RPC com.hcycom.user.usermanager 就是服务定义接口 执行完上述命令之后会生成一个 UserManager.wsdl 文件 ( 注意 : p 和后边的参数之间不能有空格, 这是本人的经验 ) IX

生成服务器端和客户端代码有了 WSDL 文件我们就可以生成服务器端和客户端的代码框架, 然后再将我们具体的业务逻辑填进去就可以了 axis 所需的 jar 文件全都包含到 classpath 里边, 执行如下命令 java cp.:$axis_classpath org.apache.axis.wsdl.wsdl2java s p com.hcycom.user c com.hcycom.user.usermanagerimpl UserManager.wsdl 参数含义如下 s, server side emit server side bindings for web service p, package <argument> override all namespace to package mappings, use this package name instead c, implementationclassname <argument> custom name of web service implementation UserManager.wsdl 上一步产生的 wsdl 文件 执行完上述命令将产生如下文件 ( 位于 /home/xingfei/axis/com/hcycom/user) deploy.wsdd undeploy.wsdd 部署 ( 反部署 ) 描述符文件 Contact.java User.java 和前面自己写的一样, 用哪个都可以 UserManagerPortType.java 和接口 UserManager 一样, 就是名字变了 本文中用这个类 UserManagerImpl.java 实现 UserManagerPortType 的类 具体的逻辑还得自己去填充 UserManagerPortTypeService.java 用于获取 UserManagerPortType, 是一个接口 UserManagerPortTypeServiceLocator.java UserManagerPortTypeService 的实现 UserManagerSoapBindingStub.java 方便客户端调用服务的 Stub 类 X

实现服务前面只是定义了服务, 没有具体实现, 下面要将具体实现, 填入到 UserManagerImpl.java 中 因为这只是个例子, 所以简单的使用一个 HashMap 来保存用户信息 具体情况下可能需要将用户信息保存到数据库等等持久设备中 代码如下 : package com.hcycom.user; import java.rmi.remoteexception; import java.util.hashmap; import java.util.iterator; public class UserManagerImpl private static HashMap users = new HashMap(); implements com.hcycom.user.usermanagerporttype{ public synchronized int adduser(com.hcycom.user.user in0) throws RemoteException { if(users.containskey(in0.getname())) { throw new RemoteException("user users.put(in0.getname(), in0); int ret = users.size(); return ret; already exists"); public synchronized int deleteuser(java.lang.string in0) throws RemoteException { if(!users.containskey(in0)) { throw new RemoteException("user users.remove(in0); int ret = users.size(); return ret; does not exist"); public synchronized User[] getallusers() throws RemoteException { int num = users.size(); User[] userlist = new User[num]; int idx = 0; for(iterator it = users.values().iterator();it.hasnext();) userlist[idx++] = (User)it.next(); return userlist; XI

public synchronized User getuser(java.lang.string in0) throws RemoteException { if(!users.containskey(in0)) { throw new RemoteException("user doen not exist"); User user = (User)users.get(in0); return user; 这里只是示例, 写的很简单 因为 web 服务是运行在多线程的情况下, 实际中要注意线程安全 部署服务 UserManager 先打开 Tomcat, 然后 axis 所需的 jar 文件全都包含到 classpath 里边, 执行如下命令 java cp.:$axis_classpath /path/to/deploy.wsdd org.apache.axis.client.adminclient 得到结果 <Admin>Done 表示部署成功 processing</admin> 这个和前面部署是一样的, 打开浏览器, 访问 http://localhost:8080/axis/servlet/axisservlet 可以看到 UserManager 服务已经成功部署, 它有 4 个可以调用的方法 XII

编写客户端客户端可以用两种方式, 第一是使用 AXIS 刚刚生成的 Stub, 第二是使用动态调用 下面用代码来说明 1. 使用 Stub, 代码如下 : import java.rmi.remoteexception; import javax.xml.rpc.serviceexception; import com.hcycom.user. *; public class UserClientUsingStub { static UserManagerPortTypeService getusermanagerporttypeservice() { return new UserManagerPortTypeServiceLocator(); public static void main(string[] args) { UserManagerPortTypeService service = getusermanagerporttypeservice(); try { UserManagerPortType usermanager = service.getusermanager(); User user = new User(); user.setage(20); user.setname("james Gosling"); user.setsex(0); Contact contact = new Contact(); contact.setemail("james@sun.com"); contact.setphone("123456789"); user.setcontact(contact); usermanager.adduser(user); user.setage(30); user.setname("scott McNealy"); user.setsex(0); contact.setemail("scott@sun.com"); contact.setphone("987654321"); user.setcontact(contact); usermanager.adduser(user); User[] users = usermanager.getallusers(); for(int i=0;i<users.length;i++) { System.out.println(users[i]); System.out.println(); catch (ServiceException e) { e.printstacktrace(); catch (RemoteException e) { e.printstacktrace(); XIII

执行的结果如下 : Name:Scott Age :30 Sex :Male Contact : McNealy Phone:987654321 Email:scott@sun.com Name:James Age :20 Sex :Male Contact : Gosling Phone:123456789 Email:james@sun.com 2. 使用动态调用, 和前面 Account 例子的调用代码一样, 代码如下 : import java.net.malformedurlexception; import java.rmi.remoteexception; import javax.xml.rpc.serviceexception; import org.apache.axis.client.call; import org.apache.axis.client.service; XIV

public class UserClientUsingDynamicInvocation { public static void main(string[] args) { String endpoint = "http://localhost:8080/axis/services/usermanager"; Service service = new Service(); try { Call call = (Call)service.createCall(); call.settargetendpointaddress(new java.net.url(endpoint)); call.setoperationname(new javax.xml.namespace.qname("http://soapinterop.org", "deleteuser")); Integer num = (Integer)call.invoke(new Object[]{"James Gosling"); System.out.println(num); num = (Integer)call.invoke(new Object[]{"Scott McNealy"); System.out.println(num); catch (ServiceException e) { e.printstacktrace(); catch (MalformedURLException e) { e.printstacktrace(); catch (RemoteException e) { e.printstacktrace(); 执行结果 1 0 两种方法各有各的好处 使用 Stub 很方便, 但是生成的文件很多, 不利于管理 使用 DII, 可 以将调用代码包装, 做到重用, 但是对于比较复杂的情况, 难以适用 实际中也可将两种情况结合起来 仔细看 Stub 的代码的话, 其实它也是适用了 DII, 只不过它的包装只限于对应的服务, 不能用于所有的服务 XV

AXIS 的服务定义都在 $TOMCAT_HOME/webapps/ axis/web INF/server config.wsdd 里边 我们用 AdminClient 进行部署的时候, 也不过是将 deploy.wsdd 的内容添加到这个文件里罢了 其实, 自己编辑这个文件也是可以的, 拷贝, 粘贴即可 还有, 这个文件大部分语法都是很简单的, 非常容易看懂 只要明白了那些标签都代表了什么含义, 就可以自己编辑它, 而不用再 java2wsdl,wsdl2java 了 部署服务还可以使用 JWS 的方式, 但是这种方式有很多缺点, 也不灵活, 这里就不介绍了 对于输入参数和返回值中的非标准 JavaBean, 要自己写 serializer,deserializer 另外 AXIS 还提供类似 Servlet 中 Filter 作用的 Handler, 可以对服务请求进行过滤 ( 日志, 访 问控制, 加密解密等 ) 关于 WSDL,SOAP,Web Service 可以参看 http://www.w3schools.com/wsdl/default.asp http://www.w3schools.com/soap/default.asp http://www.w3schools.com/webservices/default.asp XVI