最近,着手学习在Java环境中开发webservice,这里采用axis2开发。
一、 实现0配置的WebService的步骤
1.编写一个WebService类
2.编译这个WebService类
3.将编译生成的.class文件直接复制到<Tomcat安装目录>\webapps\axis2\WEB-INF\pojo目录中。如果pojo目录不存在,则新建这个目录。为什么是pojo目录,稍后自会揭晓。
下面是一个简单的WebService类
public class Axis2WebService {
public String hello(String name) {
return "Hello, " + name + "!";
}
public int getNumber() {
return new java.util.Random().nextInt();
}
public double add(double number1, double number2) {
return number1 + number2;
}
}
进行编译得到 .class 文件后执行第 3 步,启动 tomcat ( startup.bat) ,在浏览器中输入: http://localhost:8080/axis2/services/listServices
会发现下面多了一个Axis2WebService服务,如下图:
二 、调用WebService
1 直接在浏览器中调用
三个方法调用示例
http://localhost:8080/axis2/services/Axis2WebService/getNumber
http://localhost:8080/axis2/services/Axis2WebService/hello?args0=(inputparameter)
http://localhost:8080/axis2/services/Axis2WebService/add?args0=0&args1=9
其中有输入参数时,参数名要和wsdl中描述一致,调用结果如下
2 使用Java调用WebService
2.1 使用RPC调用WebService
调用步骤:
1. 创建RPCServiceClient对象
2. 创建EndPointReference对象,并指定要访问WebService的URL(不包含wsdl)
3. 创建描述WebService方法的参数值object[]对象
4. 创建描述WebService方法返回值类型的class[]对象
5. 创建QName对象,并指定要调用的WebService方法
6. 使用RPCServiceClient类的invokeBlocking方法调用WebService方法(invokeBlocking方法采用的是同步的方式)
这里写一个客户端实例来验证一下(需要先导入阿axis2\WEB-INF\lib文件下的jar包)
package cn.axis2.client;
import javax.xml.namespace.QName;
import org.apache.axis2.AxisFault;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.client.Options;
import org.apache.axis2.rpc.client.RPCServiceClient;
import org.junit.Test;
public class RPCClient {
@Test
public void test() {
try {
//创建RPCServiceClient对象
RPCServiceClient rpcClient = new RPCServiceClient();
Options options = rpcClient.getOptions();
//创建EndPointReference对象,并指定要访问WebService的URL(
EndpointReference endpoint = new EndpointReference(
"http://localhost:8080/axis2/services/Axis2WebService");
options.setTo(endpoint);
//创建描述WebService方法的参数值object[]对象
Object[] request = new Object[] { "2", "4" };
//创建描述WebService方法返回值类型的class[]对象
Class[] responseType = new Class[] { double.class };
//创建QName对象,并指定要调用的WebService方法
QName qname = new QName("http://ws.apache.org/axis2", "add");
//使用RPCServiceClient类的invokeBlocking方法调用WebService方法
Object[] response = rpcClient.invokeBlocking(qname, request,
responseType);
System.out.println(response[0]);
response = rpcClient.invokeBlocking(new QName(
"http://ws.apache.org/axis2", "getNumber"),
new Object[] {}, new Class[] { int.class });//当没有输入参数时,不能用null替代new Object[]{}
System.out.println(response[0]);
response = rpcClient.invokeBlocking(new QName(
"http://ws.apache.org/axis2", "hello"),
new Object[] { "boy" }, new Class[] { String.class });
System.out.println(response[0]);
} catch (AxisFault e) {
e.printStackTrace();
}
}
}
2.2wsdl2java简化客户端的编写
RPC方式调用WebService步骤多,复杂,不过axis2提供了一个更简单的方法来访问WebService。axis2提供一个wsdl2java命令,这个命令可以根据wsdl的内容自动生成调用WebService的客户端Stub类。
在cmd命令行下进入axis2\bin目录键入命令:
wsdl2java -uri http://localhost:8080/axis2/services/Axis2WebService?wsdl -p cn.axis.client -s -0 stub
最后在axis2\bin目录下生成stub文件夹。
这个Axis2WebServiceStub.java就是客户端类。通过调用类中方法就可以访问WebService了。
创建一个java工程,将stub文件夹下的内容拷贝至工程下
package cn.axis.client;
import java.rmi.RemoteException;
import org.apache.axis2.AxisFault;
import org.junit.Test;
public class StubClient {
@Test
public void test() {
try {
// add
Axis2WebServiceStub client = new Axis2WebServiceStub();
Axis2WebServiceStub.Add add = new Axis2WebServiceStub.Add();
add.setArgs0(1);
add.setArgs1(2);
System.out.println(client.add(add).get_return());
// getNumber
System.out.println(client.getNumber(
new Axis2WebServiceStub.GetNumber()).get_return());
// hello
Axis2WebServiceStub.Hello hello = new Axis2WebServiceStub.Hello();
hello.setArgs0("boy");
System.out.println(client.hello(hello).get_return());
} catch (AxisFault e) {
e.printStackTrace();
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
很明显,生成客户端方式简单得多。
3动态调用WebService
动态调用WebService,最为基本,基于流的方式,灵活,不需要生成客户端类。
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.net.URLConnection;
import org.junit.Test;
public class MSPJK {
@Test
public void test() {
String wsdlUrl = "http://localhost:8080/axis2/services/Axis2WebService?wsdl";
String soap = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:axis=\"http://ws.apache.org/axis2\">"
+ "<soapenv:Header/>"
+ "<soapenv:Body>"
+ "<axis:add>"
+ "<args0>4</args0>"
+ "<args1>5</args1>"
+ "</axis:add>"
+ "</soapenv:Body>" + "</soapenv:Envelope>";
String soapAction = "http://ws.apache.org/axis2/add";
String response = getSoapStream(wsdlUrl, soap, soapAction);
System.out.println(response);
}
public String getSoapStream(String wsdlUrl, String soap, String soapAction) {
try {
URL url = new URL(wsdlUrl);
URLConnection conn = url.openConnection();
conn.setUseCaches(false);
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setRequestProperty("Content-Length",
Integer.toString(soap.length()));
conn.setRequestProperty("Content-Type", "text/xml; charset=utf-8");
conn.setRequestProperty("SOAPAction", soapAction);
OutputStream os = conn.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os, "utf-8");
osw.write(soap);
osw.flush();
osw.close();
StringBuilder totalString = new StringBuilder();
String currentLine = "";
InputStream is = conn.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(
is));
while ((currentLine = reader.readLine()) != null) {
totalString.append(currentLine);
}
return totalString.toString();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
结果:
<?xml version='1.0' encoding='utf-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Body><ns:addResponse xmlns:ns="http://ws.apache.org/axis2"><return>9.0</return></ns:addResponse></soapenv:Body></soapenv:Envelope>
对这个进行解析就可以得到结果了。
三 、WebService中使用其他的类(自定义类)
在做项目时,往往需要自定义类,所以WebService能够使用自定义类很重要。下面介绍一下怎么去实现。
假设,现在服务器端有个Person类,客户端需要直接访问得到Person信息,该怎么做。
package cn.axis2.myclass;
public class Person {
private String name;
private int age;
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return this.age;
}
}
修改Axis2WebService.java,导入Person:(import cn.axis2.myclass.Person;)
并添加一个方法:
public Person getPerson() {
Person person = new Person();
person.setName("dsl");
person.setAge(21);
return person;
}
同时编译Person.java和Axis2WebService.java,Axis2WebService.class拷贝至webapps\axis2\WEB-INF\pojo目录下,Person.class拷贝至webapps\axis2\WEB-INF\classes\cn\axis2\myclass目录下(路径与包名一致)
在浏览器中刷新http://localhost:8080/axis2进入Services项,可以看见多了getPerson接口。
用wsdl2java命令重新生成客户端类,
//getPerson
Axis2WebServiceStub.GetPerson getPerson = new Axis2WebServiceStub.GetPerson();
System.out.println(client.getPerson(getPerson).get_return().getName());
System.out.println(client.getPerson(getPerson).get_return().getAge());
这样就可以输出Person信息了。自定义类的使用也就实现了。
四、在没有Servlet容器情况下使用axis2
对来axis2,它自身在二进制发行包中提供了一个简单的HTTP服务器,这个服务器默认端口是8080,与tomcat默认端口冲突,所以要用这个HTTP服务器,得先关闭tomcat。
CMD:在axis2\bin目录下输: axis2server.bat
在浏览器中刷新http://localhost:8080/axis2/services/
可以看到axis2提供的默认服务Version
五 axis2.xml配置文件
最后讲一下axis2.xml配置文件,这是axis2的核心文件,在<Tomcat安装目录>\webapps\axis2\WEB-INF\config目录下。
其中几个常用的配置有:
<!--是否热发布,即发布服务时,不需要重新启动tomcat-->
<parameter name="hotdeployment">true</parameter>
<!--是否热更新 -->
<parameter name="hotupdate">false</parameter>
<!--配置发布WebService服务目录,使用POJODeployer类发布的WebService类不能有包,这就是为什么前面发布WebService时要放在pojo目录下-->
<deployer extension=".class" directory="pojo" class="org.apache.axis2.deployment.POJODeployer"/>
<!--配置HTTP服务器 -->
<transportReceiver name="http"
class="org.apache.axis2.transport.http.SimpleHTTPServer">
<parameter name="port">8080</parameter>
</transportReceiver>