文章目录
- 1、webservice 简介
- 2、CXF 框架(xml调用)
- 2.1、创建服务端项目,发布xml
- 2.2、创建客户端项目,解析xml
- 3、调取别人发布的webservice 思路
- 4、区别版本
1、webservice 简介
常见的web服务:
- 天气信息
- 手机淘宝、京东
- 股票查询
…
这些信息都是公开的,服务商家通常会提供一个xml的web信息接口,供开发者调用。
webservice是可以跨语言传送数据的。
Java 中共有三种WebService 规范,分别是JAXM&SAAJ、JAX-WS(JAX-RPC)、JAX-RS。
- JAXM&SAAJ : 基于javax.messaging.*包 (需要手动下载这个包)
- JAX-WS(JAX-RPC):基于javax.xml.ws.*包(原生java支持)
- JAX-RS : 基于java.ws.rs.*包(restful风格)
我们常用JAX-WS 规范、JAX-RS规范获取数据。
使用JAX-WS 规范涉及的名词:
SOAP协议 = HTTP + XML 数据。
wsdl :是一种 XML 文档,描述某个 Web service。
UDDI : 就是一个目录,这个目录中存放一些关于web服务的信息。
2、CXF 框架(xml调用)
2.1、创建服务端项目,发布xml
先创建一个空项目,再新建一个maven子模块
填写一下子模块的基本信息,完事下一步就可以
接下添加依赖
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>3.0.1</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http-jetty</artifactId>
<version>3.0.1</version>
</dependency>
创建一个service:HelloService.java
import javax.jws.WebService;
/**
* 对外发布服务的接口
* **/
@WebService
public interface HelloService {
// 对外发布服务的接口的方法
public String sayHello(String name);
}
HelloServiceImpl.java
public class HelloServiceImpl implements HelloService {
@Override
public String sayHello(String name) {
return name+",hello haha";
}
}
创建Server.java发布项目
import com.haha.service.HelloServiceImpl;
import org.apache.cxf.jaxws.JaxWsServerFactoryBean;
/**
* 发布项目
* **/
public class Server {
public static void main(String[] args) {
// 发布服务的工厂
JaxWsServerFactoryBean f = new JaxWsServerFactoryBean();
// 设置服务地址
f.setAddress("http://localhost:8000/ws/hello");
// 设置服务类
f.setServiceBean(new HelloServiceImpl());
//发布服务
f.create();
System.out.println("发布成功,端口8000。。。");
}
}
浏览器访问:http://localhost:8000/ws/hello
访问连接后面加个?wsdl
2.2、创建客户端项目,解析xml
新建一个模块
加入依赖
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>3.0.1</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http-jetty</artifactId>
<version>3.0.1</version>
</dependency>
然后创建一个与服务端同名、同包路径的接口
HelloService.java
import javax.jws.WebService;
/**
* 对外发布服务的接口
* **/
@WebService
public interface HelloService {
// 对外发布服务的接口的方法
public String sayHello(String name);
}
然后获取数据Client.java
import com.haha.service.HelloService;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
public class Client {
public static void main(String[] args) {
JaxWsProxyFactoryBean f = new JaxWsProxyFactoryBean();
f.setAddress("http://localhost:8000/ws/hello");
f.setServiceClass(HelloService.class);
HelloService helloService = f.create(HelloService.class);
System.out.println(helloService.getClass());
String content = helloService.sayHello("Jet");
System.out.println(content);
}
}
运行
3、调取别人发布的webservice 思路
使用之前必看:
调用别人的wsdl文件要注意他采用的什么版本,不同的版本采用的jdk版本不同
区别版本请看标题 “4、区别版本”
第一步:使用wsimport生成java接口
wsimport是jdk自带的工具
wsimport参数:
-keep:是否生成java源文件
-d:指定.class文件的输出目录
-s:指定.java文件的输出目录
-p:定义生成类的包名,不定义的话有默认包名
-verbose:在控制台显示输出信息
-b:指定jaxws/jaxb绑定文件或额外的schemas
-extension:使用扩展来支持SOAP1.2
在cmd输入指令:wsimport -keep -s D:\Workspaces -p com.cn.phone -verbose 接口url
注意D:\Workspaces需要提前创建好
示例接口地址:http://www.webxml.com.cn/WebServices/IpAddressSearchWebService.asmx?wsdl
下面是生成好的内容
第二步:新建一个maven项目,导入cxf框架的依赖
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>3.0.1</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http-jetty</artifactId>
<version>3.0.1</version>
</dependency>
第三步:创建接口对应的包名(一定要和接口文件里一样),然后将生成的接口放进去
第四步:创建客户端类
import com.cn.phone.ArrayOfString;
import com.cn.phone.IpAddressSearchWebServiceSoap;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import java.rmi.RemoteException;
public class Client {
public static void main(String[] args) throws RemoteException {
JaxWsProxyFactoryBean f = new JaxWsProxyFactoryBean();
f.setAddress("http://www.webxml.com.cn/WebServices/IpAddressSearchWebService.asmx");
f.setServiceClass(IpAddressSearchWebServiceSoap.class);
IpAddressSearchWebServiceSoap h =f.create(IpAddressSearchWebServiceSoap.class);
// System.out.println(helloService.getClass());
//传参数
// String content = helloService.sayHello("Jet");
ArrayOfString content = h.getCountryCityByIp("183.69.220.193");
System.out.println(content.getString());
}
}
在执行wsimport中,如果出现undefined simple or complex type 'soapenc:Array’这样的错误,可能是由于wsdl文档版本过低造成的,可以按照如下例修改
这个问题是版本不同造成的,如下操作不一定能解决问题,建议更换jdk版本
修改前的文档
<s:schema targetNamespace="http://tempuri.org/AbstractTypes">
<s:import namespace="http://schemas.xmlsoap.org/soap/encoding/" />
<s:complexType name="ArrayOfString">
<s:sequence>
<s:element minOccurs="0" maxOccurs="unbounded" name="string" nillable="true" type="s:string" />
</s:sequence>
</s:complexType>
<s:complexType name="StringArray">
<s:complexContent mixed="false">
<s:restriction base="soapenc:Array">
<s:sequence>
<s:element minOccurs="0" maxOccurs="unbounded" name="String" type="s:string" />
</s:sequence>
</s:restriction>
</s:complexContent>
</s:complexType>
修改后的文档
<s:schema targetNamespace="http://tempuri.org/AbstractTypes">
<s:import namespace="http://schemas.xmlsoap.org/soap/encoding/" />
<s:complexType name="ArrayOfString">
<s:sequence>
<s:element minOccurs="0" maxOccurs="unbounded" name="string" nillable="true" type="s:string" />
</s:sequence>
</s:complexType>
</s:schema>
4、区别版本
SOAP协议到目前有两个版本:SOAP1.1和SOAP1.2
区别:
- 他们的WSDL文件的命名空间是不一样的。
- SOAP1.1存在SOAPAction的请求头、.SOAP1.2没有SOAPAction的请求头。
- 在CXF中两种协议请求的方式也不一样。SOAP1.1为content-Type:text/xm;charset=UTF-8、SOAP1.2为content-Type:application/soap+xml;charset=UTF-8。
- SOAP1.1 对应jdk1.6、SOAP1.2 对应jdk1.8
- cxf 两个版本都支持
SOAP1.1 的WSDL文件命名空间:
xmlns:soap=“http://schemas.xmlsoap.org/soap/envelope/ “
SOAP1.2 的WSDL文件命名空间:
xmlns:soap="http://www.w3.org/2003/05/soap-envelope“
在定义Service部分差别如下:
Soap1.1是以:soap:address定义。
Soap1.2是以: soap12:address定义。
jdk1.6不支持Soap1.2形式的访问。