本博客分为
1.CXF编写webservice 服务端代码
2.HttpClient调用webservice代码
3.客户端调用服务端遇到的问题及解决方案
*********************************************
一.CXF编写webservice 服务端代码
我的项目spring是3.1.4版本建议使用cxf-core-3.0.12版本
在项目为spring3.1.4的框架中使用cxf的步骤
如果没有相关jar包请在apache官网上下载"cxf 3.0.12"版本解压后copy以下jar包到项目中
导入必须jar包(导入前先确保项目是正常运行的)
cxf-core-3.0.12.jar
cxf-rt-bindings-soap-3.0.12.jar
cxf-rt-databinding-jaxb-3.0.12.jar
cxf-rt-frontend-jaxws-3.0.12.jar
cxf-rt-frontend-simple-3.0.12.jar
cxf-rt-transports-http-3.0.12.jar
cxf-rt-transports-udp-3.0.12.jar
cxf-rt-ws-addr-3.0.12.jar
cxf-rt-ws-policy-3.0.12.jar
cxf-rt-wsdl-3.0.12.jar
cxf-services-sts-core-3.0.12.jar
geronimo-jaxws_2.2_spec-1.2.jar
geronimo-servlet_3.0_spec-1.0.jar
neethi-3.0.3.jar
stax2-api-3.1.4.jar
woodstox-core-asl-4.4.1.jar
wsdl4j-1.6.3.jar
xmlschema-core-2.2.1.jar
导入后请启动项目确保没有jar包冲突
(也许还需要其他包依赖,我的项目就导入了这些,故不知其他的依赖包的信息)
------------------------------------------------------
一、配置文件
1.配置web.xml加入以下配置
<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>
-------------------------------------------------------
开始编写代码
1.新建接口
package com.xxxx.xx.xxxx.webservice.server;
import javax.jws.WebParam;
import javax.jws.WebService;
@WebService
public interface UserService {
public String getUserName(@WebParam(name="name22") String name);
public String getUserName2();
}
---------------------------------------------------
2.新建接口实现类
package com.xxxx.xx.xxxx.webservice.server.impl;
import javax.jws.WebService;
import com.xxxx.xx.xxxx.webservice.server.UserService;
public class UserServiceImpl implements UserService {
public String getUserName2() {
System.out.println("返回成功!");
return "123456";
}
@Override
public String getUserName(String name) {
System.out.println("param"+name);
return createXml(name);
}
/**
* 根据传递的字符串生成对应的xml。
*
* @param 传递过来的参数name
* @return 返回xml的字符串
*/
public String createXml(String name) {
StringBuffer sb = new StringBuffer();
sb.append("<?xml version='1.0' encoding='UTF-8'?>");
sb.append("<Result>");
sb.append("<Name>小小鸟</cinamaName>");
sb.append("<director>" + name + "</director>");
sb.append("<introduce>好的系统,不错!!!</introduce>");
sb.append("<price>25</price>");
sb.append("</Result>");
return sb.toString();
}
}
------------------------------------------------
2.新建applicationContext-CXFServer.xml
复制一份之前的spring配置文件修改其名字为applicationContext-CXFServer.xml,
在其基础上进行更改。
加入
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws="http://cxf.apache.org/jaxws"
和
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd
以下为cxf配置内容
<bean id="userServiceImpl" class="com.xxxx.xx.xxxx.webservice.server.impl.UserServiceImpl" />
<!-- 2:通过jaxws:server方式来配置webservice -->
<jaxws:server serviceClass="com.xxxx.xx.xxxx.webservice.server.UserService"
address="/User">
<jaxws:serviceBean>
<ref bean="userServiceImpl" />
</jaxws:serviceBean>
</jaxws:server>
--------------------------------------------------------------------
配置完后,启动项目。(带有xx的请替换为您的真实路径)
启动成功后在浏览器中访问: http://10.191.40.214:8080/systemName/webservice/User?wsdl
如果有许多信息显示,那说明服务端代码已经好了!!!
*********************************************************************************************
二.客户端 httpClient方式调用CXF框架 webService
第一种
public class TestHttp {
public static void main(String[] args) {
DefaultHttpClient httpClient = null;
try {
httpClient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://10.191.40.214:8080/systemName/webservice/User"); //webservice服务地址
String soapRequestData = getRequestXml(); //soap协议的格式,定义了方法和参数
HttpEntity re = new StringEntity(soapRequestData,HTTP.UTF_8);
//必须加上这段,否则报空指针异常
httppost.setHeader("Content-Type","application/soap+xml; charset=utf-8");
httppost.setEntity(re);
HttpResponse response = httpClient.execute(httppost); //调用接口
//返回是否成功的状态
System.out.println(response.getStatusLine().getStatusCode());
if(response.getStatusLine().getStatusCode() == 200) {
//获得输出的字符串
String xmlString = EntityUtils.toString(response.getEntity());
System.out.println(xmlString);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
httpClient.getConnectionManager().shutdown(); //关闭连接
}
}
/**
* 获得请求XML
* @return
*/
private static String getRequestXml(){
StringBuilder sb = new StringBuilder();
sb.append("<?xml version=\"1.0\"?>");
sb.append("<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" ");
sb.append(" xmlns:sam=\"http://server.webservice.xxxx.xx.xxxx.com/\" ");//要特别注意结尾必须带有"/",这一串由服务端提供
sb.append(" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"");
sb.append(" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"); // 要特别注意结尾必须带有"/"
sb.append("<soap:Header/>");
sb.append("<soap:Body>");
sb.append("<sam:getUserName2>"); //“getUserName"调用方法名
sb.append("<name22>老A</name22>"); //传参 name22为接口上定义的名称
sb.append("</sam:getUserName2>");
sb.append("</soap:Body>");
sb.append("</soap:Envelope>");
return sb.toString();
}
}
//
第二种方式
public class UserClient {
public static void main(String[] args) {
httpClientPost();
}
private static void httpClientPost(){
HttpClient client=new DefaultHttpClient();
HttpPost httpPost=new HttpPost("http://10.191.40.214:8080/systemName/webservice/User");
try {
ContentProducer cP=new ContentProducer(){
@Override
public void writeTo(OutputStream out) throws IOException {
Writer writer=new OutputStreamWriter(out,"UTF-8");
//获取请求xml数据
String requestXml=getRequestXmlTest();
writer.write(requestXml);
writer.flush();
}
};
//必须加上这段,否则报空指针异常
httpPost.setHeader("Content-Type","application/soap+xml; charset=utf-8");
httpPost.setEntity(new EntityTemplate(cP));
HttpResponse response=client.execute(httpPost);
//输出响应xml
System.out.println(EntityUtils.toString(response.getEntity()));
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private static String getRequestXmlTest(){
StringBuilder sb = new StringBuilder();
sb.append("<?xml version=\"1.0\"?>");
sb.append("<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" ");
sb.append(" xmlns:sam=\"http://server.webservice.xxxx.xx.xxxx.com/\" "); //要特别注意结尾必须带有"/",这一串由服务端提供
sb.append(" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"");
sb.append(" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"); //要特别注意结尾必须带有"/"
sb.append("<soap:Header/>");
sb.append("<soap:Body>");
sb.append("<sam:getUserName>"); //“getUserName”调用方法名
sb.append("<name22>老A</name22>"); //name22接口中定义的参数名
sb.append("</sam:getUserName>");
sb.append("</soap:Body>");
sb.append("</soap:Envelope>");
return sb.toString();
}
}
************************************************************************
三.客户端调用服务端遇到的问题总结
6.服务端报错
org.apache.cxf.binding.soap.SoapFault: A SOAP 1.2 message is not valid when sent to a SOAP 1.1 only endpoint.
at org.apache.cxf.binding.soap.interceptor.ReadHeadersInterceptor.handleMessage(ReadHeadersInterceptor.java:179)
at org.apache.cxf.binding.soap.interceptor.ReadHeadersInterceptor.handleMessage(ReadHeadersInterceptor.java:69)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:307)
at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121)
org.apache.cxf.binding.soap.SoapFault: "http://www.w3.org/2003/05/soap-envelope/", the namespace on the "Envelope" element, is not a valid SOAP version.
at org.apache.cxf.binding.soap.interceptor.ReadHeadersInterceptor.readVersion(ReadHeadersInterceptor.java:131)
at org.apache.cxf.binding.soap.interceptor.ReadHeadersInterceptor.handleMessage(ReadHeadersInterceptor.java:174)
at org.apache.cxf.binding.soap.interceptor.ReadHeadersInterceptor.handleMessage(ReadHeadersInterceptor.java:69)
解决方案:
//StringBuilder sb = new StringBuilder();
sb.append("<soap:Envelope xmlns:soap=\"http://www.w3.org/2003/05/soap-envelope/\"");
改为
sb.append("<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"");
5.服务端异常
org.apache.cxf.interceptor.Fault: Unmarshalling Error: unexpected element (uri:"http://server.webservice.cpic.naiu.cpic.com/", local:"name22"). Expected elements are <{}name22>
at org.apache.cxf.jaxb.JAXBEncoderDecoder.unmarshall(JAXBEncoderDecoder.java:909)
at org.apache.cxf.jaxb.JAXBEncoderDecoder.unmarshall(JAXBEncoderDecoder.java:712)
at org.apache.cxf.jaxb.io.DataReaderImpl.read(DataReaderImpl.java:179)
sb.append("<soap:Body>");
sb.append("<sam:getUserName>");
sb.append("<sam:name22>小吧</sam:name22>");
sb.append("</sam:getUserName>");
sb.append("</soap:Body>");
sb.append("<sam:name22>小吧</sam:name22>");改为sb.append("<name22>小吧<name22>");
4.服务器端异常
Caused by: javax.xml.bind.UnmarshalException
- with linked exception:
[javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"name22"). Expected elements are (none)]
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.handleStreamException(Unknown Source)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(Unknown Source)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(Unknown Source)
at org.apache.cxf.jaxb.JAXBEncoderDecoder.doUnmarshal(JAXBEncoderDecoder.java:858)
解决方案: sb.append("<soap:Body>");
sb.append("<sam:getUserName>");
sb.append("<name22>小吧<name22>");
sb.append("</sam:getUserName>");
sb.append("</soap:Body>");
sb.append("<name22>小吧<name22>"); 改为sb.append("<name22>小吧</name22>");
3.
客户端:<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><soap:Fault><faultcode>soap:Client</faultcode><faultstring>Error reading XMLStreamReader: Unexpected character 'x' (code 120) excepted space, or '>' or "/>"
at [row,col {unknown-source}]: [1,70]</faultstring></soap:Fault></soap:Body></soap:Envelope>
服务端:org.apache.cxf.binding.soap.SoapFault: Error reading XMLStreamReader: Unexpected character 'x' (code 120) excepted space, or '>' or "/>"
at [row,col {unknown-source}]: [1,70]
at org.apache.cxf.binding.soap.interceptor.ReadHeadersInterceptor.handleMessage(ReadHeadersInterceptor.java:288)
at org.apache.cxf.binding.soap.interceptor.ReadHeadersInterceptor.handleMessage(ReadHeadersInterceptor.java:69)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:307)
at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121)
解决方案:查看客户端拼接 ququestxml中 xmlns或其他标签 是否有空格 正常情况下两个标签是需要空格隔开的。
2.httpclient访问 cxf webservice 空指针异常
客户端:<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><soap:Fault><faultcode>soap:Server</faultcode><faultstring>Fault occurred while processing.</faultstring></soap:Fault></soap:Body></soap:Envelope>
服务端:java.lang.NullPointerException
at org.apache.cxf.binding.soap.interceptor.StartBodyInterceptor.handleMessage(StartBodyInterceptor.java:59)
at org.apache.cxf.binding.soap.interceptor.StartBodyInterceptor.handleMessage(StartBodyInterceptor.java:37)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:307)
解决方案:
HttpPost httpPost=new HttpPost("http://10.x.x:8080/xx/webservice/User");
在客户端设置httpPost.setHeader("Content-Type","application/soap+xml; charset=utf-8"); 解决了空指针异常
1.客户端httpclient调用 cxf webservice访问不到服务器端代码
客户端 :Interceptor for {http://server.webservice.cpic.naiu.cpic.com/}UserServiceService#{http://server.webservice.cpic.naiu.cpic.com/}getUserName2 has thrown exception, unwinding now
服务端:org.apache.cxf.interceptor.Fault: Unexpected wrapper element {http://server.webservice.cpic.naiu.cpic.com}getUserName2 found. Expected {http://server.webservice.cpic.naiu.cpic.com/}getUserName2.
at org.apache.cxf.wsdl.interceptors.DocLiteralInInterceptor.handleMessage(DocLiteralInInterceptor.java:107)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:307)
at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121)
at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:252)
解决方案: StringBuilder sb = new StringBuilder();
1.sb.append("<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope\"");
2.sb.append(" xmlns:sam=\"http://server.webservice.cpic.naiu.cpic.com\">");
3.sb.append(" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"");//new
4.sb.append(" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" ");//new
第一行和第二行必须已 /结尾
1.sb.append("<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope\"");
2.sb.append(" xmlns:sam=\"http://server.webservice.cpic.naiu.cpic.com\">");
必须改为
1.sb.append("<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"");
2.sb.append(" xmlns:sam=\"http://server.webservice.cpic.naiu.cpic.com/\">");