基于xfire实现webservice的实例
?
?????? 首先下载xfire的jar包,并导入项目当中
?????? 下载地址:http://xfire.codehaus.org/Download
1.???? 编写实现类
a.???? 首先建一个接口把对外开放的方法添加进该接口,实际上就是开放此接口让客户端
获得
package com.test.service;
public class HelloXfireImpl implements HelloXfire {
?public String sayHello(String str) {
??return str + " this is xfire";
?}
}
2.???? 映射web.xml
通过配置web.xml来映射相应的路径,在web.xml添加如下代码
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
?version="2.5"
?xsi:schemaLocation="http://java.sun.com/xml/ns/javaee?? http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
?<servlet>
??<servlet-name>XFireServlet</servlet-name>
??<servlet-class>org.codehaus.xfire.transport.http.XFireConfigurableServlet</servlet-class>
??<load-on-startup>0</load-on-startup>
?</servlet>
?<servlet-mapping>
??<servlet-name>XFireServlet</servlet-name>
??<url-pattern>/services/*</url-pattern>
?</servlet-mapping>
?<welcome-file-list>
??<welcome-file>index.jsp</welcome-file>
?</welcome-file-list>
</web-app>
3.services配置文件
??????? 创建services文件
?????????????? 在src目录下创建META-INF目录,在该目录下创建一个xfire目录在该目录
?????????????? 下创建services.xml
通过配置此文件来公开我们的接口,客户端可以通过此文件的映射可以找到相应的需要公开的接口
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xfire.codehaus.org/config/1.0">
?<service>
??<name>HelloXfire</name>
??<serviceClass>com.test.service.HelloXfire</serviceClass>
??<implementationClass>
???com.test.service.HelloXfireImpl
??</implementationClass>
??<mce:style><!--
wrapped
--></mce:style><style mce_bogus="1">wrapped</style>
??<use>literal</use>
??<scope>application</scope>
?</service></beans>
获取wsdl文件的地址
?什么是wsdl?
?参考: http://blog.csdn.net/sunchaohuang/archive/2008/10/14/3076375.aspx
?通过web.xml与services.xml对地址的映射我们可以获得如下地址并进行访问后就可
??? ?以得到wsdl文件的url了
访问的地址:
http://localhost:9099/HelloXfire/services/HelloXfire?wsdl
访问后会得到一个类似xml格式的内容 该文件就是一个wsdl文件
4.编写客户端
?????? 客户端获得webservice的url地址后创建对外开放的接口的实体类,然后向相应的方法传递参数,经过服务端相应的处理返回需要的结果
package com.test.client;
import java.net.MalformedURLException;
import org.codehaus.xfire.XFireFactory;
import org.codehaus.xfire.client.XFireProxyFactory;
import org.codehaus.xfire.service.Service;
import org.codehaus.xfire.service.binding.ObjectServiceFactory;
import com.test.service.HelloXfire;
public class HelloXfireClient {
?/**
? * @param args
? */
?public static void main(String[] args) {
??Service srvcModel = new ObjectServiceFactory().create(HelloXfire.class);
??XFireProxyFactory factory = new XFireProxyFactory(XFireFactory
????.newInstance().getXFire());
??String helloWorldURL = "http://localhost:9099/HelloXfire/services/HelloXfire";
??try {
???HelloXfire srvc = (HelloXfire) factory.create(srvcModel,
?????helloWorldURL);
???String result = srvc.sayHello("hello ");
???System.out.print(result);
??} catch (MalformedURLException e) {
???e.printStackTrace();
??}
?}
}
不同项目的webservice调用
?????? 一般情况下webservice的调用都是在不同的项目间或者不同的语言中来使用的
?????? 如果是不同的语言调用webservice应用:
????????????? 客户端如果是其他语言,则通过得到服务端生成的wsdl或者或者wsdl文件的
??????????? 地址做相应的操作得到本语言具体的客户端实现类来调用服务端对外开放的
??????????? 方法
?? ?如果是不同项目间的调用(java语言为例)
??????? 在myeclipse下新建一个web service Client选择xfire下一步后选择wsdl的
??????????? 地址:
??????????? http://localhost:9099/HelloXfire/services/HelloXfire?wsdl
????? ?完成后会自动生成相应的客户端类。
??????? 在HelloXfireClient类中调取服务端对外开放的接口方法获得相应数据
??????? 具体代码如下
package com.test.service;
import java.net.MalformedURLException;
import java.util.Collection;
import java.util.HashMap;
import javax.xml.namespace.QName;
import org.codehaus.xfire.XFireRuntimeException;
import org.codehaus.xfire.aegis.AegisBindingProvider;
import org.codehaus.xfire.annotations.AnnotationServiceFactory;
import org.codehaus.xfire.annotations.jsr181.Jsr181WebAnnotations;
import org.codehaus.xfire.client.XFireProxyFactory;
import org.codehaus.xfire.jaxb2.JaxbTypeRegistry;
import org.codehaus.xfire.service.Endpoint;
import org.codehaus.xfire.service.Service;
import org.codehaus.xfire.soap.AbstractSoapBinding;
import org.codehaus.xfire.transport.TransportManager;
public class HelloXfireClient {
??? private static XFireProxyFactory proxyFactory = new XFireProxyFactory();
??? private HashMap endpoints = new HashMap();
??? private Service service0;
??? public HelloXfireClient() {
??????? create0();
??????? Endpoint HelloXfirePortTypeLocalEndpointEP = service0 .addEndpoint(new QName("http://service.test.com","HelloXfirePortTypeLocalEndpoint"),new QName("http://service.test.com","HelloXfirePortTypeLocalBinding"),"xfire.local://HelloXfire");
??????? endpoints.put(new QName("http://service.test.com",HelloXfirePortTypeLocalEndpointEP);
??????? Endpoint HelloXfireHttpPortEP = service0 .addEndpoint(new QName("http://service.test.com","HelloXfireHttpPort"),"HelloXfireHttpBinding"),"http://localhost:9099/HelloXfire/services/HelloXfire");
??????? endpoints.put(new QName("http://service.test.com",HelloXfireHttpPortEP);
??? }
??? public Object getEndpoint(Endpoint endpoint) {
??????? try {
??????????? return proxyFactory.create((endpoint).getBinding(),(endpoint).getUrl());
??????? } catch (MalformedURLException e) {
??????????? throw new XFireRuntimeException("Invalid URL",e);
??????? }
??? }
??? public Object getEndpoint(QName name) {
??????? Endpoint endpoint = ((Endpoint) endpoints.get((name)));
??????? if ((endpoint) == null) {
??????????? throw new IllegalStateException("No such endpoint!");
??????? }
??????? return getEndpoint((endpoint));
??? }
??? public Collection getEndpoints() {
??????? return endpoints.values();
??? }
??? private void create0() {
??????? TransportManager tm = (org.codehaus.xfire.XFireFactory.newInstance().getXFire().getTransportManager());
??????? HashMap props = new HashMap();
??????? props.put("annotations.allow.interface",true);
??????? AnnotationServiceFactory asf = new AnnotationServiceFactory(new Jsr181WebAnnotations(),tm,new AegisBindingProvider(new JaxbTypeRegistry()));
??????? asf.setBindingCreationEnabled(false);
??????? service0 = asf.create((com.test.service.HelloXfirePortType.class),props);
??????? {
??????????? AbstractSoapBinding soapBinding = asf.createSoap11Binding(service0,"urn:xfire:transport:local");
??????? }
??????? {
??????????? AbstractSoapBinding soapBinding = asf.createSoap11Binding(service0,"http://schemas.xmlsoap.org/soap/http");
??????? }
??? }
??? public HelloXfirePortType getHelloXfirePortTypeLocalEndpoint() {
??????? return ((HelloXfirePortType)(this).getEndpoint(new QName("http://service.test.com","HelloXfirePortTypeLocalEndpoint")));
??? }
??? public HelloXfirePortType getHelloXfirePortTypeLocalEndpoint(String url) {
??????? HelloXfirePortType var = getHelloXfirePortTypeLocalEndpoint();
??????? org.codehaus.xfire.client.Client.getInstance(var).setUrl(url);
??????? return var;
??? }
??? public HelloXfirePortType getHelloXfireHttpPort() {
??????? return ((HelloXfirePortType)(this).getEndpoint(new QName("http://service.test.com","HelloXfireHttpPort")));
??? }
??? public HelloXfirePortType getHelloXfireHttpPort(String url) {
??????? HelloXfirePortType var = getHelloXfireHttpPort();
??????? org.codehaus.xfire.client.Client.getInstance(var).setUrl(url);
??????? return var;
??? }
??? public static void main(String[] args) {
???????
??????? HelloXfireClient client = new HelloXfireClient();
???????
??//create a default service endpoint
??????? HelloXfirePortType service = client.getHelloXfireHttpPort();
??????? String? string=?service.sayHello("hello");
??????? System.out.println(string);
???????
??//TODO: Add custom client code here
??????? ??//
??????? ??//service.yourServiceOperationHere();
???????
??System.out.println("test client completed");
??????? ??System.exit(0);
??? }
}
如果能够成功运行并正确获得调用的方法返回的值说明webservice成功实现了
?
?
??? 常见错误及解决办法:
1.jar包冲突
?????? 如果运行后得到以下错误
org.codehaus.xfire.XFireRuntimeException: Could not invoke service.. Nested exception is org.codehaus.xfire.fault.XFireFault: Could not marshall type.
?
说明jar包有冲突
解决办法
如果发现以下的包用多个
jaxb-api-1.0.jar
jaxb-api-2.0.jar
jaxb-impl-1.0.5.jar
jaxb-impl-2.0.1.jar
则删除低版本的
?
? 2. Could?not?find?valid?implementation?for:?2.0
如果出现如下错误
java.lang.IllegalStateException: Could not find valid implementation for: 2.0
?at org.apache.xbean.spring.context.impl.XBeanHelper.createBeanDefinitionReader(XBeanHelper.java:48)
?at org.codehaus.xfire.spring.XFireConfigLoader.getXFireApplicationContext(XFireConfigLoader.java:74)
?at org.codehaus.xfire.spring.XFireConfigLoader.loadContext(XFireConfigLoader.java:41)
?at org.codehaus.xfire.transport.http.XFireConfigurableServlet.loadConfig(XFireConfigurableServlet.java:86)
?
问题的原因是因为xfire不支持spring2.0的新特性,需要修改service.xml文件,将beans元素的命名空间放到services元素上,修改后的xml如下:
<beans>
?<services xmlns="http://xfire.codehaus.org/config/1.0">
?</services>
</beans>
另外,由于我使用了MyEclipse的Spring Capailities和WebService Capailities(使用xfire),由于后者自带了Spring1.2.6的包,造成了和2.0版本的冲突,所以必须作以下工作:
??? 删除<MyEclise_Home>/eclipse/plugins/com.genuitec.eclipse.ws.xfire_5.9.100/data/1.2/lib目录的Spring1.2.6包
??? 删除Tomcat/Webapps/<项目目录>/WEB-INF/lib目录下的Spring1.2.6包(好像重新部署不能删除已经存在的包)
??? 重新启动MyEclipse
问题解决。