WebService 四种发布方式总结

1.CXF方式

CXF与spring搭建webservice是目前最流行的方式,但是传闻cxf与jdk1.5有些不兼容,我没有遇到过,我遇到的问题是cxf与was6.1.1不兼容,表现在cxf必须的jar包“wsdl4j-1.6.2.jar”报错,报的错为: java.lang.IncompatibleClassChangeError,明显的jar包不兼容问题,很是头痛,后来查找资料找到解决办法是,将上述jar包新建一个was共享库,可以解决,但是客户周经理不想用此种方式,因为需要修改was,于是改用了axis2方式,下文会介绍。该问题在此处做个记录,以后使用cxf与was的时候需要注意!!!


使用cxf+spring搭建WebService:

第一步,添加jar包。此处需要注意,不同环境(tomcat、was)jar也不一定相同,服务器jar包池的不同。根据错误提示缺什么补什么就可以了,注意jar包勿重复。

第二步,配置web.xml文件,如下(重要的地方已标记):

<context-param>

<param-name>contextConfigLocation</param-name>

<param-value>classpath:/applicationContext.xml</param-value>

</context-param>

<listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

</listener>

<!-- Character Encoding filter -->

<filter>

<filter-name>encodingFilter</filter-name>

<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>

<init-param>

<param-name>encoding</param-name>

<param-value>UTF-8</param-value>

</init-param>

</filter>

<filter-mapping>

<filter-name>encodingFilter</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

<servlet>

<servlet-name>CXFServlet</servlet-name><servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>

<load-on-startup>1</load-on-startup>

</servlet>

<servlet-mapping>

<servlet-name>CXFServlet</servlet-name>

<url-pattern>/webservice/*</url-pattern>

</servlet-mapping>

上述标记的地方,第一处是spring配置文件路径;第二出是wsdl地址内容;

第三步,编写接口类与实现类,注意注解

接口类

@WebService

publicinterfaceSendService {

publicbooleansendOA(@WebParam(name="param")String param);

publicbooleansendOrg(OrgEntity org);

}

实现类

@WebService(endpointInterface="com.service.SendService",serviceName="sendService")

publicclassSendServiceImplimplementsSendService{

publicbooleansendOA(String param) {

System.out.println("-------sendOA---------param:"+param);

if(param.equals("zhoujian")){

return true;

}

return false;

}

publicbooleansendOrg(OrgEntity org) {

System.out.println("-------sendOrg--begin-------");

returntrue;

}

}

第四步,Spring配置文件

<?xmlversion="1.0"encoding="UTF-8"?>

<beans

xmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:p="http://www.springframework.org/schema/p"

xmlns:jaxws="http://cxf.apache.org/jaxws"

xsi:schemaLocation="

      http://www.springframework.org/schema/beans

      http://www.springframework.org/schema/beans/spring-beans.xsd

      http://cxf.apache.org/jaxws

      http://cxf.apache.org/schemas/jaxws.xsd">

<importresource="classpath:META-INF/cxf/cxf.xml"/>

<importresource="classpath:META-INF/cxf/cxf-extension-soap.xml"/>

<importresource="classpath:META-INF/cxf/cxf-servlet.xml"/>


<jaxws:endpointid="sendServie"implementor="com.service.impl.SendServiceImpl"

address="/sendServie"/>


<!-- <jaxws:client id="sendServiceClient" serviceClass="com.service.SendService"

address="http://10.137.138.11:9080/Wb/webservice/sendServie?wsdl"  />-->


</beans>

“jaxws:client”该标签可以不必写,访问时可以手动拼接该url

第五步,发布,直接部署到服务器,访问:

http://10.137.138.11:9080/Wb/webservice/sendServie?wsdl


2.Xfire方式

据说xfire方式已经很老了,但个人感觉,xfire方式很简单且容易配置,不知为啥过时了,也没感觉cxf、axis2哪里先进,我当时卡在cxf与was搞不定时想尝试xfire方式被周经理给拒绝了。

Xfire方式发布webservice:

第一步,添加jar包

第二步,修改web.xml文件

<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>

/services/*

  </servlet-mapping>

第三步,编写接口类

接口类:

public abstract interface IBankingService {

public abstract String transferFunds(String paramString1);

}

实现类:

public class BankingService implements IBankingService{

  public String transferFunds(String fromAccount)

  {

    return fromAccount+":ok";

  }

}

第四步,编写services.xml配置文件

在WEB-INF目录下新建目录META-INF,在该目录下新建文件夹xfire,该目录下新建文件services.xml

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="http://xfire.codehaus.org/config/1.0">

<service>

<name>Banking</name>

<namespace>mybank</namespace>

<serviceClass>

com.mybank.xfire.example.IBankingService

</serviceClass>

<implementationClass>

com.mybank.xfire.impl.BankingService

</implementationClass>

</service>

</beans>

第五步,发布,部署到服务器,访问url:

http://localhost:9080/Xfire/services/Banking?wsdl


3.AXIS2方式

Axis2发布WebService有两种方式,其一是利用axis2插件打成aar包放到axis_war里面部署到服务器发布;其二是不打包发布(本例);我不清楚打包发布有什么好处,感觉很麻烦项目外还得部署一个war,现在介绍第二种不打包的方式,类似xfire,同时由于cxf与was不兼容导致wsdl.jar报错,但是xfire与axis2也用到wsdl.jar却不报错,我个人也是很费解,泰康项目目前使用的就是axis2方式。

Axis2发布WebService:

第一步,添加jar包

都是从axis.war里面WEB-INF下的lib目录复制来的。

第二步,修改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>


 

第三步,编写实现类

publicclassServiceImpl {

publicString sayHello(String name){

System.out.println("================");

return"hello:"+name;

}

}

第四步,增加WEN-INF内容

将axis.war解压下的WEN-INF文件夹内的conf、modules复制到项目WEB-INF下


第五步,在WEB-INF下创建文件夹services(名字不可改),在该目录下创建文件夹(名称随意),在该目录下创建文件夹META-INF(名称不可改),在该目录下创建文件services.xml(名称不可改),该文件内容为:

<?xmlversion="1.0"encoding="UTF-8"?>

<servicename="axisDemo">

<description>

Web Service例子

</description>

<parametername="ServiceClass">

 com.ServiceImpl

</parameter>

<messageReceivers>

<messageReceivermep="http://www.w3.org/2004/08/wsdl/in-out"

class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/>

<messageReceivermep="http://www.w3.org/2004/08/wsdl/in-only"

class="org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver"/>

</messageReceivers>

</service>

 

第六步,部署到服务器,发布URL为:

http://localhost:9080/Axis2Test/services/axisDemo?wsdl

 

4.AXIS1方式

同上,不知道AXIS1哪里不好,配置也很简单,如下:

第一步,添加jar包

第二步,修改web.xml

<servlet>

<servlet-name>AxisServlet</servlet-name>

<servlet-class>

        org.apache.axis.transport.http.AxisServlet

</servlet-class>

</servlet>

<servlet-mapping>

<servlet-name>AxisServlet</servlet-name>

<url-pattern>/services/*</url-pattern>

</servlet-mapping>

第三步,实现类与实体类

实现类:

packagecom;

publicclassAxis {

publicString sayHello(String name){

System.out.println("============:"+name);

return"hi:"+name;

}

publicString sayHelloToUser(User u){

System.out.println("============:"+u.getId());

System.out.println("============:"+u.getPath());

System.out.println("============:"+u.getAdd());

return"hi:"+u.getName();

}

}



实体类:

packagecom;

publicclassUser {

privateStringid;

privateStringname;

privateStringadd;

privateStringpath;


    getter setter ……方法


第四步,创建配置文件:在WEB-INF下新建文件“server-config.wsdd”

<?xmlversion="1.0"encoding="UTF-8"?>

<deploymentxmlns="http://xml.apache.org/axis/wsdd/"

xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">

 <!--globalConfiguration 标签内容为系统默认 无需更改à

<globalConfiguration>

<parametername="adminPassword"value="admin"/>

<parametername="attachments.Directory"value="./attachments"/>

<parametername="attachments.implementation"

value="org.apache.axis.attachments.AttachmentsImpl"/>

<parametername="sendXsiTypes"value="true"/>

<parametername="sendMultiRefs"value="true"/>

<parametername="sendXMLDeclaration"value="true"/>

<parametername="axis.sendMinimizedElements"value="true"/>

<requestFlow>

<handlertype="java:org.apache.axis.handlers.JWSHandler">

<parametername="scope"value="session"/>

</handler>

<handlertype="java:org.apache.axis.handlers.JWSHandler">

<parametername="scope"value="request"/>

<parametername="extension"value=".jwr"/>

</handler>

</requestFlow>

</globalConfiguration>

<handlername="LocalResponder"

type="java:org.apache.axis.transport.local.LocalResponder"/>

<handlername="URLMapper"

type="java:org.apache.axis.handlers.http.URLMapper"/>

<handlername="Authenticate"

type="java:org.apache.axis.handlers.SimpleAuthenticationHandler"/>

<!—service标签是需要配置的-à

<!—name是url中需要的参数-à

<servicename="axisTest"provider="java:RPC">

  <!—allowedMethods的value值是方法名

可以写*-à

<parametername="allowedMethods"value="*"/>

  <!—className的value值是类路径-à

<parametername="className"value="com.Axis"/>

  <!—wsdlTargetNamespace的wsdl文件中TargetNamespace的值-à

<parametername="wsdlTargetNamespace"value="http://service.impl.tdi.taikang.tivoli.ibm.com/"/>

   <!—此处很重要,若方法需要传实体类,则配置此处-à 

<beanMappingqname="myNS:User"xmlns:myNS="urn:BeanService"languageSpecificType="java:com.User"/>

</service>

<!—默认-à

<transportname="http">

<requestFlow>

<handlertype="URLMapper"/>

<handlertype="java:org.apache.axis.handlers.http.HTTPAuthHandler"/>

</requestFlow>

</transport>

<transportname="local">

<responseFlow>

<handlertype="LocalResponder"/>

</responseFlow>

</transport>

</deployment>

第五步,部署,同上。


5.AXIS1客户端调用

此处调用方式为axis1的调用,需要传递的参数可以是字符串或实体类,字符串方式:

Serviceservice=newService();

Callcall= (Call) service.createCall();

//wsdl地址

call.setTargetEndpointAddress(newURL(wsdlUrl));

//设定调用3分钟不返回则超时

call.setTimeout(newInteger(180000));

//命名空间(wsdl文件中的targetNameSpace属性值)以及方法名

call.setOperationName(newQName("http://com","sayHello"));

//参数类型

call.addParameter("name", XMLType.XSD_STRING, ParameterMode.IN);

//返回值类型

call.setReturnType(XMLType.XSD_STRING);

//参数值

String retXML2 = (String) call.invoke(newObject[] {"yczhang"});

System.out.println( retXML2);

实体类方式(调用axis2的接口有点问题):

UserEntity userEntry =newUserEntity();

userEntry.setId("yczhang");

userEntry.setName("yczhang");

Service service =newService();

Call call = (Call) service.createCall();

//wsdl地址

call.setTargetEndpointAddress(newURL(wsdlUrl));

//设定调用3分钟不返回则超时

call.setTimeout(newInteger(180000));

//命名空间(wsdl文件中的targetNameSpace属性值)以及方法名

call.setOperationName(newQName("http://com","sayHelloToUser"));

//注册SimpleObject的序列化类型

QName qn =newQName("urn:BeanService","UserEntity");

call.registerTypeMapping(UserEntity.class, qn,newBeanSerializerFactory(UserEntity.class, qn),newBeanDeserializerFactory(UserEntity.class, qn));

//参数类型(可省略)

call.addParameter("requestParam",org.apache.axis.encoding.XMLType.XSD_ANYTYPE, ParameterMode.IN);

//返回值类型

call.setReturnType(XMLType.XSD_BOOLEAN);

Boolean retXML1 = (Boolean) call.invoke(newObject[] {userEntry});

System.out.println( retXML1);

注意,实体类方式,当调用的是由axis2方式所发布的接口时,容易出现问题,表现在所传递的实体类的属性内容为null,但在该实体类内新建一属性传如该值时,却有值。应该是axis1对axis2的不兼容问题。并且调用axis2的接口时,需要在客户端写出namespace,即:

//call.setOperationName(new QName("http://localhost:9080/WS_Axis/services/axisTest", "sayHelloToUser"));


该种调用方式对于axis1的接口没问题。泰康项目最终使用的是axis1发布的接口,并使用该种方式调用的。

publicstaticvoidmain(String[] args)throwsServiceException, MalformedURLException, RemoteException {

String wsdlUrl ="http://localhost:9080/WS_Axis/services/axisTest?wsdl";

//实体类

User user =newUser();

user.setId("1");

user.setAdd("test");

user.setName("test");

user.setPath("test");

Service service =newService();

Call call = (Call) service.createCall();

call.setTargetEndpointAddress(newURL(wsdlUrl));

//设定调用3分钟不返回则超时

call.setTimeout(newInteger(180000));

//call.setOperationName(new QName("http://localhost:9080/WS_Axis/services/axisTest", "sayHelloToUser"));

//注册SimpleObject的序列化类型(urn:BeanService在wsdd文件内有配置)

QName qn =newQName("urn:BeanService","User");

call.registerTypeMapping(User.class, qn,newBeanSerializerFactory(User.class, qn),newBeanDeserializerFactory(User.class, qn));

//方法名

call.setOperationName("sayHelloToUser");

//“user”是接口服务端方法体中的实体类所声明的变量名(”say(User

user)”)

call.addParameter("user", org.apache.axis.encoding.XMLType.XSD_ANYTYPE, ParameterMode.IN);

//返回值类型

call.setReturnType(XMLType.XSD_STRING);

System.out.println( call.invoke(newObject[] { user }));

}

6.AXIS2客户端调用

所需jar包:

具体代码:

publicclassRPClient {

publicstaticvoidmain(String[] args)throwsAxisFault {

try{

//实体类

UserEntity ue =newUserEntity();

ue.setId("123");

ue.setAddress("test");

ue.setMail("123");

ue.setName("yczhang");

RPCServiceClient client =newRPCServiceClient();

Options options = client.getOptions();

String url ="http://localhost:9080/WS_Axis2/services/axisDemo?wsdl";

EndpointReference end =newEndpointReference(url);

options.setTo(end);


Object[] obj =newObject[] { ue };

Class[] classes =newClass[] { Boolean.class};

//命名空间  方法名

QName qname =newQName("http://com","sayHelloToUser");

System.out.println(client.invokeBlocking(qname, obj, classes)[0]);

}catch(AxisFault e) {

e.printStackTrace();

}

}

注意 该种方式缺点是客户端实体类路径即包名必须与服务端实体类路径相同!!!但该方式可以调任何方式编写的接口!!!!

7.CXF客户端调用

使用axis、axis2客户端调用cxf接口会有问题,建议使用cxf自身客户端调用或者使用webservice

Client 自动生成客户端方式

功能代码:

publicclassTT {

publicstaticvoidmain(String[] args) {

JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();

Client client = dcf.createClient("http://10.137.138.11:9080/WS_CXF/webservice/sendServie?wsdl");

try{

//此处http://service.com/需要指向接口路径而非实现类

System.out.println(client.invoke(newQName("http://service.com/","sendOA"),"test")[0]);

}catch(Exception e) {

e.printStackTrace();

}

}

}

注意:若运行程序时报错“JAXB 2.0 API ….. endorsed”则需要将以下jar包放入jdk lib和jre

lib

重启exlipse即可。

8.Web Service Client客户端调用

调用代码如下:

publicclassCXFClient {

publicstaticvoidmain(String[] args)throwsException, IllegalAccessException, InvocationTargetException {

JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();

Client client = dcf.createClient("http://localhost:9080/WS_CXF/webservice/sendServie?wsdl");

client.invoke("sendOA","aa");

}

}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,529评论 5 475
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,015评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,409评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,385评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,387评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,466评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,880评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,528评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,727评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,528评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,602评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,302评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,873评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,890评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,132评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,777评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,310评论 2 342

推荐阅读更多精彩内容