目前开源的webservice实现有很多。今天主要学习了apache的axis2。webservice本质上是对soap(简单对象描述语言)的统一格式解析和数据传输。具体的理论性的东西就不在赘述。这里主要记录学习axis2的笔记心得。我们可以从apache的官网下载到最新的axis2版本。这里使用1.62版本。下载地址为:
http://axis.apache.org/axis2/java/core/download.cgi
这里下载binaryDistribution 。部署axis2
创建web项目,然后将lib目录下的jar包拷贝到WEB-INF/lib目录下。
将webapp/axis2-web目录拷贝到webRoot项目根目录下。这个目录下的内容正式部署是可删除,可以作为开发时的验证和查看。
将webapp/WEB-INF/web.xml文件中关于axis2的配置拷贝到项目的web.xml文件中。
将conf目录拷贝到项目WEB-INF/目录下,主要是axis2.xml文件,里面配置了axis2的几种部署方式及其他基本配置。
然后启动tomcat,完成后,输入http://localhost:8080/springmvc/services/listServices如果出现下面内容表示部署成功。
一、使用pojo方式部署
axis2有一种简单快速的方式部署,创建一个java类,将class文件拷贝到WEB-INF/pojo/目录下即可。该方法会将该类中所有的公共方法发布为webservice服务。代码如下:
/**
*pojo方式发布webservice
* @author nmm
*
*/
public class HelloWorldPojo {
public String sayHello(String name) {
String str = "hello " + name;
System.out.println(str);
return str;
}
}
重新输入
http://localhost:8080/springmvc/services/listServices看到刚刚部署的服务
点击链接会看到相应的wsdl文件。
说明:
1.此方式部署的服务,源文件不能带包,即必须放在src目录下。
2.WEB-INF/pojo目录可以修改,如果修改,大家打开axis2.xml文件,会看到此段代码,这里是配置pojo的部署目录的
3.axis2.xml配置文件默认为热部署的,但不是热更新。即我们拷贝过去服务可以自动发布,但是不能自动更新,如果更新需要重启服务器。当然我们可以配置为热更新。
下面写一下客户端调用代码:
1.axis1方式的调用:
Service service = new Service();
Call call = (Call) service.createCall();
String url = "http://localhost:8080/springmvc/services/HelloWorldPojo";
call.setTargetEndpointAddress(url);
//这里指定调用方法的名称空间,和调用方法,这里的url后面会自动补充?wsdl的参数。
//另外这里如果不指定名空间,会默认采用axis1的名称空间,对于其他的服务端程序可能调用不成功。
// http://server.webservice.jb.com
call.setOperationName(new QName("http://ws.apache.org/axis2","sayHello"));
Object obj = call.invoke(new Object[]{"aaaa"});
System.out.println("调用了:" + obj);
其中qName要和截图中标出的一致才可以
2.通过axis2的客户端调用:
//采用RPC方式调用
RPCServiceClient client = new RPCServiceClient();
Options opera = client.getOptions();
// opera.setManageSession(true);打开回话状态管理
//指定调用的URL
EndpointReference ref = new EndpointReference("http://localhost:8080/springmvc/services/HelloWorldPojo");
opera.setTo(ref);
//指定名称空间和方法
QName qname = new QName("http://ws.apache.org/axis2","sayHello");
//可以看到,采用此方法,返回的值会封装到数组中,同时,如果不指定第3个参数,返回值为返回的webservicexml文件。
Object obj = client.invokeBlocking(qname, new Object[]{"张三"},new Class[]{String.class});
System.out.println("调用了:" + obj);
如果看到任务台输出表示访问成功。需要说明的是axis2的客户端调用会将返回值作为数组返回。
二、通过services.xml文件部署带包目录的pojo服务。
上面的方法虽然可以快速部署服务,但是不能够将服务放在具体的包路径下就不太好了。这里我们将服务放到目录下然后部署。首先服务代码为:
package com.jb.webservice.server;
import com.jb.webservice.data.DataService;
/**
* 带包的发布
* @author nmm
*
*/
public class HelloPojoPackage {
public String sayHello(String name) {
String str = "hello " + name;
DataService ds = new DataService();
str = ds.getData(name);
return str;
}
public String test(String name) {
String str = "test " + name;
return str;
}
}
dataservice文件内容为:
package com.jb.webservice.data;
import org.springframework.stereotype.Service;
/**
* 调用的方法类。
* @author nmm
*
*/
public class DataService {
public String getData(String name){
String str = "您获得的数据:" + name;
return str;
}
}
这时,要求dataservice的编译文件放在WEB-INF/classes/正确的包目录结构下。
创建services.xml文件内容如下:(介绍了两种配置方式)
<service name="firsPackagePojo">
<description><!-- 描述 -->
第一个带包的pojoservice发布
</description>
<!-- 配置消息过滤,此方法默认将所有公共函数发布为service服务。
<messageReceivers>
<messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-only"
class="org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver"/>
<messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out"
class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/>
</messageReceivers>
-->
<!-- 配置实现类 -->
<parameter name="ServiceClass">com.jb.webservice.server.HelloPojoPackage</parameter>
<!-- 此方法指定方法发布服务
-->
<operation name="sayHello">
<messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out"
class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/>
</operation>
</service>
将HelloPojoPackage文件打包成jar文件,并修改扩展名为.aar(axis2官方推荐)。另外需要将上述services.xml文件打包到jar文件中,并且放到META-INF目录下。
对于services.xml的发布打包,我们如果全部采用spring进行管理开发,那么就只需要发布services.xml文件即可,我们可以将META-INF文件夹放在src/services目录下,然后编写下面ant脚本执行即可:(脚本在WebRoot下)
<?xml version="1.0" encoding="UTF-8"?>
<project default="jar" basedir=".">
<target name="jar">
<delete file="${basedir}/WEB-INF/services/services.aar" />
<jar destfile="${basedir}/WEB-INF/services/services.aar" compress="true">
<fileset dir="../src/services/" includes="**/*.*" />
</jar>
</target>
</project>
将.aar文件拷贝到WEB-INF/services目录下。启动服务并方位如果看到发布的服务表明发布成功:
三、整合spring
在axis2的官方网站提供了一种整合方案,即除了正常的配置spring外,同时将spring的的配置文件applicationContext.xml放在项目的根目录下即和WEB-INF目录同级。然后再services.xml文件中改为如下配置:
<parameter name="ServiceObjectSupplier" >org.apache.axis2.extensions.spring.receivers.SpringAppContextAwareObjectSupplier</parameter>
<parameter name="SpringBeanName" >weatherSpringService</parameter>
经过测试该方法在不使用mvc的情况下没有问题,楼主没有仔细尝试,主要是觉得这种方式还有修改原来项目的配置文件目录,过于麻烦,而且不清楚对于注解是否好使,由于自己实现了一个Supplier类,用于提供对象支持。当然这里没有考虑太多细节,真正使用时需要大家自己完善下,以下为实现代码:
package com.jb.webservice.data;
import org.apache.axis2.AxisFault;
import org.apache.axis2.ServiceObjectSupplier;
import org.apache.axis2.description.AxisService;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;
@Service("objectSupplier")
public class ObjectSupplier implements ServiceObjectSupplier ,ApplicationContextAware{
private static ApplicationContext ac;
public Object getServiceObject(AxisService as) throws AxisFault {
Object springBean = as.getParameter("SpringBeanName").getValue();
if(springBean != null) {
return ac.getBean(springBean.toString());
}
return null;
}
public void setApplicationContext(ApplicationContext app)
throws BeansException {
System.out.println(111);
ac = app;
}
}
这时,如果在weblogic下部署报nullpointException的话,表示weblogic加载内存管理不同,共享资源不能获取,或者是axis2的servlet的启动顺序设置的比spring高。
针对前一种情况我们可以考虑创建一个新的类,专门提供spring容器,而不是在这个类里进行容器获取及共享,具体代码如下:
package com.jb.webservice.suplier;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;
/**
*
* @Package: com.jb.webservice.suplier<br>
* @ClassName: SpringContextSupplier<br>
* @Description: spring容器提供者<br>
*/
@Service("springContext")
public class SpringContextSupplier implements ApplicationContextAware {
private static ApplicationContext ac;
public void setApplicationContext(ApplicationContext arg0)
throws BeansException {
ac = arg0;
}
/**
*
* @Title: getContext
* @Description: 获取spring容器
* @return
* ApplicationContext
* @throws
*/
public static ApplicationContext getContext(){
return ac;
}
}
services.xml配置文件改为:
<service name="getSpringData">
<!-- 配置spring的整合 --><!-- 服务类提供方案 -->
<parameter name="ServiceObjectSupplier">com.jb.webservice.data.ObjectSupplier</parameter>
<parameter name="SpringBeanName">helloPojoSpring</parameter>
<!--配置serviceClass后,就不需要将class文件打包大发布的.aar文件中-->
<parameter name="ServiceClass">com.jb.webservice.server.HelloPojoPackage</parameter>
<operation name="getSpringData">
<messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out"
class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/>
</operation>
</service>
需要说明的是这种使用spring配置文件发布服务的话,打包的.aar文件中可以只含有services.xml文件即可,其他编译文件均放到相应编译目录下。不需要打包的文件中。
四、axis2与weblogic9.2整合
由于axis21.6.2版本用的是jdk1.6,所以在weblogic中直接部署时,在客户端调用会抛异常javax.xml.supportDTD之类的,这时我们需要在WEB-INF/目录下增加weblogic.xml文件,指定weblogic下有限加载项目jar包:即可
<?xml version="1.0" encoding="UTF-8"?>
<weblogic-web-app>
<container-descriptor>
<prefer-web-inf-classes>true</prefer-web-inf-classes>
</container-descriptor>
</weblogic-web-app>
http://download.youkuaiyun.com/detail/niemingming/5909025