Web Service之AXIS(一)
1、Axis 全称是 Apache Extensible Interaction System :阿帕奇可扩展交互系统。是一个开源、基于XML的Web服务框架。包含了Java和C++语言实现的SOAP服务器,以及各种公用服务及API以生成和部署Web服务应用。可创造出可操作的、分布式的计算应用。
开发环境:Myeclipse、Tomcat、jdk、AXis2
首先可以下载如下两个zip包:
axis2-1.7.6-bin.zip
axis2-1.7.6-war.zip
其中 axis2-1.7.6-bin.zip文件中包含了Axis2中所有的jar文件,
axis2-1.7.6-war.zip文件用于将WebService发布到Web容器中。
将axis2-1.7.6-war.zip文件解压到相应的目录,将目录中的axis2.war文件放到<Tomcat安装目录>\webapps目录中,
并启动Tomcat,在浏览器地址栏中输入如下的URL:
http://localhost:8080/axis2/
如看到axis2的主页面则安装成功。
将axis2-1.7.6-war.zip压缩包里面的axis2.war包解压到tomcat的webapps目录下,启动tomcat,访问地址http://localhost:8080/axis2/ ,即可访问axis2的Welcome!页面。
访问地址http://localhost:8080/axis2/services/listServices 另可访问服务列表。
http://localhost:8080/axis2/services/Version?method=getVersion 获取版本
使用Axis2方式发布webService的三种方式
1、简单的pojo方式(无需配置):
在Axis2中不需要进行任何的配置,就可以直接将一个简单的POJO发布成WebService。其中POJO中所有的public方法将被发布成WebService方法。
示例代码如下:(这个POJO的类名必须是XXXService格式,否则报错)
将HelloService.class文件放到tomcat\webapps\axis2\WEB-INF\pojo目录中【注:若没有pojo目录,则手动新建该目录】。
在浏览器地址栏中输入如下的URL:
http://127.0.0.1:8080/axis2/services/listServices 即可访问刷新后的服务列表。【注:POJO类不能使用package关键字声明包,若使用axis2管理平台发布,则需要修改HelloService类,去掉package字段。】
在浏览器地址栏中输入如下的两个URL来分别测试sayHelloToPerson和sayHello方法:
1.http://localhost:8080/axis2/services/HelloService/sayHello
2.http://localhost:8080/axis2/services/HelloService/sayHelloToPerson?name=huadi
【注:发布WebService的pojo目录只是默认的,如果想在其他的目录发布WebService,可以打开axis2/WEB-INF/conf/axis2.xml文件,并在<axisconfig>元素中添加如下的子元素:
<deployer extension=".class" directory="my" class="org.apache.axis2.deployment.POJODeployer"/>
上面的配置允许在<Tomcat安装目录>\webapps\axis2\WEB-INF\my目录中发布WebService。 例如,将本例中的HelloService.class复制到my目录中也可以成功发布(但要删除pojo目录中的SimpleService.class,否则WebService会重名)。
访问 http://127.0.0.1:8080/axis2/services/HelloService?wsdl 即可访问服务UserService的wsdl描述
2. Axis2在默认情况下可以热发布WebService,也就是说,将WebService的.class文件复制到pojo目录中时, Tomcat不需要重新启动就可以自动发布WebService。 如果想取消Axis2的热发布功能,可以打开<Tomcat安装目录>\webapps\axis2\WEB-INF\conf\axis2.xml,
找到如下的配置代码:
<parameter name="hotdeployment">true</parameter>
将true改为false即可。要注意的是,Axis2在默认情况下虽然是热发布,但并不是热更新.也就是说,一旦成功发布了WebService,再想更新该WebService,就必须重启Tomcat。这对于开发人员调试WebService非常不方便,因此,在开发WebService时,可以将Axis2设为热更新。
在axis2.xml文件中找到如下的配置代码:
<parameter name="hotupdate">false</parameter>
将false改为true即可。
3. 在浏览器中测试WebService时,如果WebService方法有参数,需要使用URL的请求参数来指定该WebService方法,参数的值,请求参数名与方法参数名要一致,例如,要测试sayHelloToPerson方法,请求参数名应为name,如上面的URL所示。
2、打jar包的方式:
用Axis2实现Web Service,虽然可以将POJO类放在axis2\WEB-INF\pojo目录中直接发布成Web Service, 这样做不需要进行任何配置,但这些POJO类不能在任何包中。这似乎有些不方便. 为此,Axis2也允许将带包的POJO类发布成Web Service。先实现一个POJO类,代码如下:
package com.axis; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Random; public class HelloWSDD { public String getName(String name) { return "Welcome " + name; } public Double getPrice() { return Math.random(); } public int getNum() { return new Random().nextInt(100); } public List<String> getList() { List<String> list = new ArrayList<String>(); list.add("num1"); list.add("num2"); list.add("num3"); list.add("num4"); list.add("num5"); return list; } public Map<String, String> getMap() { Map<String, String> map = new HashMap<String, String>(); map.put("NO.1", "Y1"); map.put("NO.2", "Y2"); map.put("NO.3", "Y3"); map.put("NO.4", "Y4"); map.put("NO.5", "Y5"); return map; } }
问题解决:
信息: Error parsing HTTP request header
Note: further occurrences of HTTP header parsing errors will be logged at DEBUG level.
java.lang.IllegalArgumentException: Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986
at org.apache.coyote.http11.InternalAprInputBuffer.parseRequestLine(InternalAprInputBuffer.java:238)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1028)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:637)
at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2555)
at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2544)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:662)
解决方法:
Plan 1:
更换低版本的Tomcat来规避这种问题。
Plan 2:
在conf/catalina.properties中最后添加一行:
org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true
这个案例整理了半天,才成功。下面讲解一下步骤
1。生成services.xml文档。
<?xml version="1.0" encoding="UTF-8"?> <service name="HelloWSDDService" targetNamespace="http://ws.apache.org/ax2"> <schema schemaNamespace="http://sdjxd.com.cn" /> <description>Web Service实例一</description> <parameter name="ServiceClass">com.axis.HelloWSDDService</parameter> <messageReceivers> <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out" class="org.apache.axis2.rpc.receivers.RPCMessageReceiver" /> <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-only" class="org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver" /> </messageReceivers> </service>
2.放置同一目录下
3.cmd命令行运行
4.将生成的aws.aar压缩包放置在tomacta安装目录\webapps\axis2\WEB-INF\services下
5.运行tomact。查看服务
打jar的方式可以借助插件工具:
下载插件http://axis.apache.org/axis2/java/core/download.html
一、new---》other----》Axis
:填写服务器端类的.class文件的地址目录
完成
3、不打jar包的方式:
有一个最简单的方法就是把axis2.war中的内容作为Web Project的基础, 来进行开发.
不过为了更清楚的了解如何在一个已有的Web Project中嵌入axis2, 那就手动来配置。大致分如下几个步骤:
一、新建Web Project,名为“20171030”
二、下载axis2-1.6.1-war.zip包,解压缩
将axis2/WEB-INF/lib 里的jar包拷贝到 WebServiceDemo/WebRoot/WEB-INF/lib/
将axis2.war/axis2-web拷贝至WebServiceDemo/ WebRoot/axis2-web/
三、配置axis2 servlet
打开WebServiceDemo/WebRoot/WEB-INF/web.xml,增加如下配置:
<servlet> <servlet-name>AxisServlet</servlet-name> <servlet-class>org.apache.axis2.transport.http.AxisServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>AxisServlet</servlet-name> <url-pattern>/services/*</url-pattern> </servlet-mapping>
四、写一个简单的web服务类
package com.axis;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
public class HelloWSDDService {
public String getName(String name) {
return "Welcome " + name;
}
public Double getPrice() {
return Math.random();
}
public int getNum() {
return new Random().nextInt(100);
}
public List<String> getList() {
List<String> list = new ArrayList<String>();
list.add("num1");
list.add("num2");
list.add("num3");
list.add("num4");
list.add("num5");
return list;
}
public Map<String, String> getMap() {
Map<String, String> map = new HashMap<String, String>();
map.put("NO.1", "Y1");
map.put("NO.2", "Y2");
map.put("NO.3", "Y3");
map.put("NO.4", "Y4");
map.put("NO.5", "Y5");
return map;
}
}
五、配置Web Service.
由于axis2已嵌入到20171030项目中,所以web service就不用打包成aar,而是直接在/WEB-INF目录下创建相应的文件夹和services.xml,目录结构如下图:
六、services.xml
<?xml version="1.0" encoding="UTF-8"?>
<service name="HelloWSDDService" targetNamespace="http://ws.apache.org/ax2">
<schema schemaNamespace="http://sdjxd.com.cn" />
<description>Web Service实例一</description>
<parameter name="ServiceClass">com.axis.HelloWSDDService</parameter>
<messageReceivers>
<messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out"
class="org.apache.axis2.rpc.receivers.RPCMessageReceiver" />
<messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-only"
class="org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver" />
</messageReceivers>
</service>
七、在浏览器中访问http://localhost:8080/20171030/services/listServices
可以看到myService服务,说明服务已部署成功
输入http://localhost:8080/20171030/services/HelloWSDDService?wsdl
可以查看到该Web服务的描述文件
以上是Axis2的发布方式,你查看资料也会发现将.java转变成.jws进行发布的。这里要说明一下。Axis1和Axis2发布方式是有所不同的,希望大家不要混淆。这里我也给出axis-1_4的发布方式。
环境 tomcat、myeclipse、axis-1_4
下载地址: http://www.apache.org/dist/axis/axis/java/1.4/
解压axis-bin-1_4.zip。进入axis-1_4\webapps目录下。复制文件夹axis到Tomact的webapps目录下。启动Tomcat,在浏览器测试一下Axis是否成功,如出现如下页面表示成功。地址:http://localhost:8080/axis
1、即时发布
①、将java文件扩展名.java重命名为.jws文件,并放在Web应用程序的根目录下,如下所示:
②、在浏览器中运行http://localhost:8080/axis/HelloService.jws,出现下面界面:
点击链接,可查看wsdl文件
测试代码,编写客户端:
public class CallService { public static void main(String[] args) { // 请求地址 指明服务所在位置 String url = "http://localhost:8080/axis/HelloService.jws"; // 创建服务 创建一个Service实例,注意是必须的! Service service = new Service(); try { // 调用服务 创建Call实例,也是必须的! Call call = (Call) service.createCall(); // 服务地址 为Call 设置服务的位置 call.setTargetEndpointAddress(url); // 请求方法 注意方法名与 HelloWorld.java中一样 call.setOperationName(new QName(url, "sayHelloToPerson")); // 执行调用 String result = (String) call.invoke(new Object[] { "huadiyatou" }); System.out.println(result); // 请求方法 call.setOperationName(new QName(url, "sayHello")); // 执行调用 String result1 = (String) call.invoke(new Object[] {}); System.out.println(result1); } catch (ServiceException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
结果如下,即时发布完成。
即时发布的特点:只能使用原始数据类型和非常普通的Java类如Date,作为方法参数和返回类型,不能使用自定义的类。不支持带package包的出现
2、定制发布(WSDD :Web Service Deployment Descriptor)
步骤一、编写服务器端代码,并编译该程序
package com.axis; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Random; public class HelloWSDD { public String getName(String name) { return "Welcome " + name; } public Double getPrice() { return Math.random(); } public int getNum() { return new Random().nextInt(100); } public List<String> getList() { List<String> list = new ArrayList<String>(); list.add("num1"); list.add("num2"); list.add("num3"); list.add("num4"); list.add("num5"); return list; } public Map<String, String> getMap() { Map<String, String> map = new HashMap<String, String>(); map.put("NO.1", "Y1"); map.put("NO.2", "Y2"); map.put("NO.3", "Y3"); map.put("NO.4", "Y4"); map.put("NO.5", "Y5"); return map; } }
步骤二、把编译后的文件(带包路径)拷贝到 (本地服务器)apache-tomcat-7.0.42\webapps\axis\WEB-INF\classes下
步骤三、编写发布文件.wsdd,并复制到tomact的webapps\axis\WEB-INF目录下,通常命名为deploy.wsdd,即SOAP服务发布描述文件
<!-- deployment元素:指定wsdd所用的XML名字空间。deployment是其根元素,可以定义多个Service元素 -->
<deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"> <!-- Services from VisualWebService WSDL service -->
<!-- service元素:定义一项SOAP服务,他有name和provider两个属性,name代表这项服务的唯一标示符,即服务的名字。SOAP 会根据name属性访问该SOAP服务,provider指定了实现这项服务的语言及服务方式。-->
<service name="HelloWS" provider="java:RPC"> <!--parameter元素:包含name和value属性,如果name值为className,则指定该服务的类名,如果name为allowedMethods,则指定该项服务包含的方法-->
<parameter name="className" value="com.axis.HelloWSDD"/> <!--接口文件位置--> <parameter name="allowedMethods" value="*"/> </service> </deployment>
步骤四、控制台,进入目录F:\apache-tomcat-7.0.82\webapps\axis\WEB-INF下。键入:java -Djava.ext.dirs=lib org.apache.axis.client.AdminClient wsdd全名,一般wsdd的名字为deploy.wsdd(注:服务器Tomcat必须已经启动)
你会发现目录下多了一个server-config.wsdd文件,这就是AXIS的配置文件,以后所有的服务发布描述都会在里面找到。(当然,你可以直接修改它,不用再写deploy.wsdd。但server-config.wsdd文件应该存放在apache-tomcat-7.0.42\webapps\axis\WEB-INF 下)
得到结果<Admin>Doneprocessing</Admin>表示部署成功。或者查看 http://localhost:8080/axis/servlet/AxisServlet 是否发布成功
步骤五、
浏览器访问:http://localhost:8080/axis/services/HelloWS?method=getName&name=hahaha
java程序访问:
package com.axis; import java.rmi.RemoteException; import java.util.Map; import java.util.Map.Entry; import javax.xml.namespace.QName; import javax.xml.rpc.ServiceException; import org.apache.axis.client.Call; import org.apache.axis.client.Service; public class CallHelloWSDD { public static void main(String[] args) { // 请求地址 String url = "http://localhost:8080/axis/services/HelloWS"; // 创建服务 Service service = new Service(); try { // 调用服务 Call call = (Call) service.createCall(); // 服务地址 call.setTargetEndpointAddress(url); // 请求方法 call.setOperationName(new QName(url, "getName")); // 执行调用 String result = (String) call.invoke(new Object[] { "Mswangg" }); System.out.println(result); // 请求方法 call.setOperationName(new QName(url, "getPrice")); // 执行调用 double result1 = (Double) call.invoke(new Object[] {}); System.out.println(result1); // 请求方法 call.setOperationName(new QName(url, "getNum")); // 执行调用 int result2 = (Integer) call.invoke(new Object[] {}); System.out.println(result2); // 请求方法 call.setOperationName(new QName(url, "getList")); // 执行调用 Object result3 = call.invoke(new Object[] {}); System.out.println(result3); System.out.println("***********************"); // 请求方法 call.setOperationName(new QName(url, "getMap")); // 执行调用 Map<String, String> result4 = (Map<String, String>) call .invoke(new Object[] {}); for (Entry<String, String> e : result4.entrySet()) { System.out.println(e.getKey() + ":" + e.getValue()); } } catch (ServiceException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
即时发布和定制发布的客户端代码区别在于:
即时发布:String url = "http://localhost:8080/axis/HelloService.jws";
定制发布:String url = "http://localhost:8080/axis/services/HelloWS";