使用axis2进行WebService的开发

Apache Axis2 是 Apache Axis SOAP 项目的后继项目。此项目是 Web 服务核心引擎的重要改进,目标是成为 Web 服务和面向服务的体系结构(Service-Oriented Architecture,SOA)的下一代平台。
axis2 WebService开发分为服务端开发与客户端开发,服务端开发为对外提供服务,客户端开发为用户调用外部接口进行业务处理。

一、下载与安装

1.下载

下载地址:http://axis.apache.org/axis2/java/core/download.cgi
有以下下载列表:
Binary Distribution zip | MD5 | PGP 
Source Distribution zip | MD5 | PGP 
WAR Distribution zip | MD5 | PGP 
Documents Distribution zip | MD5 | PGP

注:
axis2-1.6.2-bin.zip里有axis2的jar包。
axis2-1.6.2-docs.zip里有详细的帮助文档。
axis2-1.6.2-src.zip里是源代码。
axis2-1.6.2-war.zip里是axis的管理平台,放到tomcat可直接使用。

注:本文用bin包进行命令行使用axis2,管理平台使用的是war包。

2.安装配置

将axis2-1.6.2-bin.zip解压到本地目录D:\axis2-1.6.2

设置环境变量。【注:前提需要配置java环境变量】
AXIS2_HOME 设置值 D:\axis2-1.6.2
Path 添加值 %AXIS2_HOME%\bin

二、服务端编写

1.创建服务端的java项目testAsixServer。

编写类City与类User代码如下:

  1. package com.hsinghsu.model;
  2. public class City
  3. {
  4. private int cityCode;
  5. private String cityName;
  6. public int getCityCode()
  7. {
  8. return cityCode;
  9. }
  10. public void setCityCode(int cityCode)
  11. {
  12. this.cityCode = cityCode;
  13. }
  14. public String getCityName()
  15. {
  16. return cityName;
  17. }
  18. public void setCityName(String cityName)
  19. {
  20. this.cityName = cityName;
  21. }
  22. }
  1. package com.hsinghsu.model;
  2. public class User
  3. {
  4. private int id;
  5. private String name;
  6. private String password;
  7. private City city;
  8. public int getId()
  9. {
  10. return id;
  11. }
  12. public void setId(int id)
  13. {
  14. this.id = id;
  15. }
  16. public String getName()
  17. {
  18. return name;
  19. }
  20. public void setName(String name)
  21. {
  22. this.name = name;
  23. }
  24. public String getPassword()
  25. {
  26. return password;
  27. }
  28. public void setPassword(String password)
  29. {
  30. this.password = password;
  31. }
  32. public City getCity()
  33. {
  34. return city;
  35. }
  36. public void setCity(City city)
  37. {
  38. this.city = city;
  39. }
  40. }

编写服务类UserService。该服务类即为对外提供的服务,其中对外提供2个服务getUserById与getUserList,代码如下:

  1. package com.hsinghsu.service;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. import com.hsinghsu.model.User;
  5. public class UserService
  6. {
  7. public List<User> getUserList(User user)
  8. {
  9. List<User> list = new ArrayList<User>();
  10. return list;
  11. }
  12. public User getUserById(int id)
  13. {
  14. User user = new User();
  15. return user;
  16. }
  17. }

2.发布WebService服务

发布WebService服务方式可使用axis2管理平台发布,本文另添加使用soapUI发布WebService的测试服务。

2.1 axis2管理平台发布

2.1.1 部署axis2管理平台

将axis2-1.6.1-war.zip压缩包里面的axis2.war包解压到tomcat的webapps目录下,启动tomcat,访问地址http://127.0.0.1:8080/axis2/ ,即可访问axis2的Welcome!页面。
访问地址http://127.0.0.1:8080/axis2/services/listServices 另可访问服务列表。

2.1.2 部署开发服务

编译服务端项目testAsixServer后,将UserService.class文件放到tomcat\webapps\axis2\WEB-INF\pojo目录中【注:若没有pojo目录,则手动新建该目录】。
在浏览器地址栏中输入如下的URL:
http://127.0.0.1:8080/axis2/services/listServices 即可访问刷新后的服务列表。【注:POJO类不能使用package关键字声明包,若使用axis2管理平台发布,则需要修改UserService类,去掉package字段。】

【注:发布WebService的pojo目录只是默认的,如果想在其他的目录发布WebService,可以打开axis2/WEB-INF/conf/axis2.xml文件,并在<axisconfig>元素中添加如下的子元素:
<deployer extension=".class" directory="mydir" class="org.apache.axis2.deployment.POJODeployer"/>】

访问 http://127.0.0.1:8080/axis2/services/UserService?wsdl 即可访问服务UserService的wsdl描述

【注:另可使用jar cvf命令将服务打成aar包后导入到axis2管理平台上使用。】

2.2 使用soapUI生成WAR发布WebService测试服务

2.2.1 由java生成wsdl文件

运用Java2wsdl生成wsdl文件

使用cmd命令,在命令行中输入:
java2wsdl -cn com.hsinghsu.service.UserService
【注:在testAsixServer项目的classes根目录下执行】

输出:
Using AXIS2_HOME:   D:\axis2-1.6.2
Using JAVA_HOME:    C:\Program Files\Java\jdk1.6.0_01
log4j:WARN No appenders could be found for logger (org.apache.axis2.util.Loader).
log4j:WARN Please initialize the log4j system properly.

结果:
生成UserService.wsdl文件

2.2.2 soapUI导出war包:

在soapUI导入UserService.wsdl文件。
通过soapUI生成MockService。
启动MockService,测试MockService时,在URL填写http://HSING-PC:8088/mockUserServiceSoap11Binding 后点击运行,查看是否有正确报文返回。
soapUI发送报文如下:

  1. <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="http://service.hsinghsu.com">
  2. <soapenv:Header/>
  3. <soapenv:Body>
  4. <ser:getUserById>
  5. <!--Optional:-->
  6. <ser:id>2</ser:id>
  7. </ser:getUserById>
  8. </soapenv:Body>
  9. </soapenv:Envelope>

soapUI接收报文如下:

  1. <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="http://service.hsinghsu.com" xmlns:xsd="http://model.hsinghsu.com/xsd">
  2. <soapenv:Header/>
  3. <soapenv:Body>
  4. <ser:getUserByIdResponse>
  5. <!--Optional:-->
  6. <ser:return>
  7. <!--Optional:-->
  8. <xsd:city>
  9. <!--Optional:-->
  10. <xsd:cityCode>001</xsd:cityCode>
  11. <!--Optional:-->
  12. <xsd:cityName>wh</xsd:cityName>
  13. </xsd:city>
  14. <!--Optional:-->
  15. <xsd:id>1</xsd:id>
  16. <!--Optional:-->
  17. <xsd:name>hsinghsu</xsd:name>
  18. <!--Optional:-->
  19. <xsd:password>123456</xsd:password>
  20. </ser:return>
  21. </ser:getUserByIdResponse>
  22. </soapenv:Body>
  23. </soapenv:Envelope>

在soapUI中导出war包,如testUser.war。

2.2.3 部署war包

将war包部署到tomcat目录下。【注:需要修改war包里面的WEB-INF/soapui/testUser-soapui-project.xml文件引用wsdl文件的路径】
启动tomcat,访问在war所在的路径如 http://127.0.0.1:8080/testUser/mockUserServiceSoap11Binding?WSDL ,即可查看wsdl描述文件
【注:可以使用soapUI测试接口,在soapUI测试中,URL中填写testUser.war的部署地址,如http://ip:port/testUser/mockUserServiceSoap11Binding ,点击运行,查看对应的接口是否有正确报文返回。】

三、客户端编写

Axis2支持以下4种类型的客户端:
i.  Block(阻塞式客户端),即传统客户端。一旦服务被启用,客户端的应用程序将被挂起,直到operation被执行完毕(表现为收到一个response或fault),才能重新获得控制权。这是调用Web Service最简单的方式,并且这种方式适用于多数业务情形。
ii. Non block(非阻塞式客户端),即异步客户端。使用Non-Blocking API来调用这些Web Services。Axis2提供给用户一种基于回叫机制的non-blocking API,一旦服务被起用,客户端应用程序马上得到控制权,通过使用一个callback对象来获得response。这种方式使得客户端应用程序可以很方便的同步启用多个Web Service。
iii.双工(双向传输)。以上的机制都使用单一的连接去发送请求和接收响应.这都明显在性能上落后于使用两条连接(单向或双向)进行进行请求和响应的传输 . 因此以上的机制都不能解决长时间运行的交易, 连接将在操作还没完成就会超时. 一种解决方案是使用分开的两条传输连接来传输请求和响应 . 我们叫这种方案为传输层异步。
iv. 双工非阻塞(双向且非阻塞传输)。

注:axis2 webservice client端需要的jar包有:

  1. axis2-kernel-1.6.1.jar
  2. axis2-adb-1.6.1.jar
  3. axiom-api-1.2.12.jar
  4. commons-logging-1.1.1.jar
  5. wsdl4j-1.6.2.jar
  6. XmlSchema-1.4.7.jar
  7. axiom-impl-1.2.12.jar
  8. neethi-3.0.1.jar
  9. axis2-transport-local-1.6.1.jar
  10. axis2-transport-http-1.6.1.jar
  11. commons-httpclient-3.1.jar
  12. httpcore-4.0.jar
  13. commons-codec-1.3.jar
  14. mail-1.4.jar

1.传统客户端【阻塞式客户端的编写】

新建AsixBlockClient类,获取数据,代码如下:

  1. package com.hsinghsu.asix.client;
  2. import org.apache.axiom.om.OMAbstractFactory;
  3. import org.apache.axiom.om.OMElement;
  4. import org.apache.axiom.om.OMFactory;
  5. import org.apache.axiom.om.OMNamespace;
  6. import org.apache.axis2.AxisFault;
  7. import org.apache.axis2.addressing.EndpointReference;
  8. import org.apache.axis2.client.Options;
  9. import org.apache.axis2.client.ServiceClient;
  10. /**
  11. *
  12. * Block(阻塞式客户端),即传统客户端调用WebService Axis2的底层API来调用WebService
  13. *
  14. * @author hsinghsu
  15. *
  16. */
  17. public class AsixBlockClient
  18. {
  19. private static EndpointReference targetEPR = new EndpointReference(
  20. "http://127.0.0.1:8080/testUser/mockUserServiceSoap11Binding");//接口地址
  21. public static void main(String[] args)
  22. {
  23. Options options = new Options();
  24. options.setAction("urn:getUserById");//调用接口方法
  25. options.setTo(targetEPR);
  26. ServiceClient sender = null;
  27. try
  28. {
  29. sender = new ServiceClient();
  30. sender.setOptions(options);
  31. OMFactory fac = OMAbstractFactory.getOMFactory();
  32. OMNamespace omNs = fac.createOMNamespace(
  33. "http://service.hsinghsu.com", "");
  34. OMElement method = fac.createOMElement("getUserById", omNs);
  35. OMElement name = fac.createOMElement("id", omNs);//设置入参名称
  36. name.setText("1");//设置入参值
  37. method.addChild(name);
  38. method.build();
  39. System.out.println("method:" + method.toString());// print:<getUserById xmlns="http://service.hsinghsu.com"><id>1</id></getUserById>
  40. OMElement response = sender.sendReceive(method);
  41. System.out.println("response:" + response);
  42. OMElement elementReturn = response.getFirstElement().getFirstElement().getFirstElement();
  43. System.out.println("cityCode:"+elementReturn.getText());
  44. }
  45. catch (AxisFault e)
  46. {
  47. System.out.println("Error");
  48. e.printStackTrace();
  49. }
  50. }
  51. }

执行结果如下:

  1. method:<getUserById xmlns="http://service.hsinghsu.com"><id>1</id></getUserById>
  2. response:<ser:getUserByIdResponse xmlns:ser="http://service.hsinghsu.com">
  3. <!--Optional:-->
  4. <ser:return>
  5. <!--Optional:-->
  6. <xsd:city xmlns:xsd="http://model.hsinghsu.com/xsd">
  7. <!--Optional:-->
  8. <xsd:cityCode>001</xsd:cityCode>
  9. <!--Optional:-->
  10. <xsd:cityName>wh</xsd:cityName>
  11. </xsd:city>
  12. <!--Optional:-->
  13. <xsd:id xmlns:xsd="http://model.hsinghsu.com/xsd">1</xsd:id>
  14. <!--Optional:-->
  15. <xsd:name xmlns:xsd="http://model.hsinghsu.com/xsd">hsinghsu</xsd:name>
  16. <!--Optional:-->
  17. <xsd:password xmlns:xsd="http://model.hsinghsu.com/xsd">123456</xsd:password>
  18. </ser:return>
  19. </ser:getUserByIdResponse>
  20. cityCode:001

2.使用RPC方法调用WebService

编写AsixRPCClient.java类,获取数据。注:添加User.java、City.java至项目中。
AsixRPCClient.java代码如下:

  1. package com.hsinghsu.asix.client;
  2. import javax.xml.namespace.QName;
  3. import org.apache.axis2.addressing.EndpointReference;
  4. import org.apache.axis2.client.Options;
  5. import org.apache.axis2.rpc.client.RPCServiceClient;
  6. import com.hsinghsu.model.User;
  7. /**
  8. * 使用RPC方式调用WebService
  9. *
  10. * @author hsinghsu
  11. *
  12. */
  13. public class AsixRPCClient
  14. {
  15. /**
  16. * @param args
  17. */
  18. public static void main(String[] args) throws Exception
  19. {
  20. // 使用RPC方式调用WebService
  21. RPCServiceClient serviceClient = new RPCServiceClient();
  22. Options options = serviceClient.getOptions();
  23. EndpointReference targetEPR = new EndpointReference(
  24. "http://127.0.0.1:8080/testUser/mockUserServiceSoap11Binding");// 指定调用WebService的URL
  25. options.setTo(targetEPR);
  26. Object[] opAddEntryArgs = new Object[]{new Integer(1)};// 指定getGreeting方法的参数值
  27. Class[] classes = new Class[]{User.class};// 指定getGreeting方法返回值的数据类型的Class对象
  28. QName opAddEntry = new QName("http://service.hsinghsu.com",
  29. "getUserById");// 指定要调用的getGreeting方法及WSDL文件的命名空间
  30. Object[] objects = serviceClient.invokeBlocking(opAddEntry,
  31. opAddEntryArgs, classes);// RPCServiceClient类的invokeBlocking方法调用了WebService中的方法。invokeBlocking方法有三个参数,其中第一个参数的类型是QName对象,表示要调用的方法名;第二个参数表示要调用的WebService方法的参数值,参数类型为Object[];第三个参数表示WebService方法的返回值类型的Class对象,参数类型为Class[]。当方法没有参数时,invokeBlocking方法的第二个参数值不能是null,而要使用new Object[]{}。
  32. System.out.println(" objects size-->:" + objects.length);
  33. if (objects.length >= 1)
  34. {
  35. User user = new User();
  36. user = (User) objects[0];
  37. System.out.println("==" + user.getId() + " ==" + user.getName()
  38. + " ==" + user.getCity().getCityName());
  39. }
  40. }
  41. }

运行结果:
 objects size-->:1[Ljava.lang.Object;@ba5c7a
==1 ==hsinghsu ==wh

3.使用Stub方式调用WebService

运用wsdl2java简化客户端,使用Stub方式调用WebService

3.1 生成STUB文件。

在cmd中用 wsdl2java生成stub文件。注:在wsdl文件目录下执行
输入:
wsdl2java -uri UserService.wsdl
【注:默认adb生成方式,同步生成方式,加参数-a则使用异步生成】

输出:
Using AXIS2_HOME:   D:\axis2-1.6.2
Using JAVA_HOME:    C:\Program Files\Java\jdk1.6.0_01
Retrieving document at 'UserService.wsdl'.
log4j:WARN No appenders could be found for logger (org.apache.axis2.description.WSDL11ToAllAxisServicesBuilder).
log4j:WARN Please initialize the log4j system properly.

结果:
生成build.xml、UserServiceStub.java、UserServiceCallbackHandler.java文件

3.2 编写同步调用函数

编写AsixServiceStub类,获取数据。
AsixServiceStub.java代码如下:

  1. package com.hsinghsu.asix.client;
  2. import com.hsinghsu.service.UserServiceStub;
  3. import com.hsinghsu.service.UserServiceStub.GetUserById;
  4. import com.hsinghsu.service.UserServiceStub.User;
  5. /**
  6. * 利用axis2插件生成客户端方式调用 wsdl2java简化客户端的编写
  7. *
  8. * @author hsinghsu
  9. *
  10. */
  11. public class AsixServiceStub
  12. {
  13. public static void main(String[] args) throws Exception
  14. {
  15. UserServiceStub stub = new UserServiceStub();
  16. GetUserById guid = new GetUserById();
  17. guid.setId(1);
  18. User user = stub.getUserById(guid).get_return();// 同步调用方式
  19. if (null != user)
  20. {
  21. System.out.println("==" + user.getId() + " ==" + user.getName()
  22. + " ==" + user.getCity().getCityName());
  23. }
  24. else
  25. {
  26. System.out.println("user null");
  27. }
  28. }
  29. }

运行结果:
==1 ==hsinghsu ==wh

注:添加UserServiceStub.java、UserServiceCallbackHandler.java文件至项目中,注意修改UserServiceStub.java类中服务的地址。

注:若需要使用异步调用,则需创建异步回调类AsynCallback,该类需要继承UserServiceCallbackHandler抽象类,实现回调函数receiveResultgetUserById接口。在AsixServiceStub中,只需要使用stub.startgetUserById(guid, new AsynCallback());执行即可。

05-11 19:53