AVA 中共有三种WebService 规范,分别是
JAX-WS(JAX-RPC)、
JAXM&SAAJ、
JAX-RS。
1 Webservice客户端开发方法总结
1.1 使用客户端生成代码方法
第一步:使用wsimport或其它工具(比如cxf的wsdl2java)生成客户端的调用
第二步:使用生成代码调用webservice服务端
使用生成的service服务视图类创建服务视图对象
调用service服务对象的getPortXXX方法得到portType。
//创建服务视图对象
WeatherInterfaceImplService weatherInterfaceImplService =new WeatherInterfaceImplService();
//通过服务视图得到portType(接口类型)
WeatherInterfaceImpl weatherInterfaceImpl = weatherInterfaceImplService.getWeatherInterfaceImplPort();
//调用webservice方法
String result = weatherInterfaceImpl.queryWeather("郑州");
1.2 使用jaxws标准方法(Service类)(推荐使用)
第一步:使用wsimport或其它工具(比如cxf的wsdl2java)生成客户端的调用
第二步:使用url、qname、service调用服务端
//wsdl的路径
URL wsdlDocumentLocation = new URL("http://127.0.0.1:54321/weather?wsdl");
//从wsdl中找到服务视图
//第一个参数:wsdl的命名空间
//第二个参数:服务视图名称
QName serviceName = new QName("http://server.weather.jaxws.ws.itcast.cn/", "WeatherInterfaceImplService");
//第一步使用Service创建服务视图
Service service =Service.create(wsdlDocumentLocation, serviceName);
//从服务视图得到portType对象
//参数:portType
WeatherInterfaceImpl weatherInterfaceImpl = service.getPort(WeatherInterfaceImpl.class);
1.3 模拟http客户端调用webservice服务(掌握)
使用HttpURLConnection或apache的Httpclient模拟http请求,调用webservice。
注意:使用此方法不需要生成客户端调用代码。。
JAX-WS的服务端:
第一步:服务端开发
- 编写SEI(Service Endpoint Interface),SEI在webservice中称为portType,在java中称为接口。
代码如下:
/**
* 天气查询服务接口
* @author 传智播客 Java学院 苗润土
* @version V1.0
*/
public interface WeatherInterface {
//天气查询
public String queryWeather(String cityName);
}
- 编写SEI实现类,此类作为webservice提供服务类
代码如下:
/**
* 天气查询服务接口实现类
* @author 传智播客 Java学院 苗润土
* @version V1.0
*/
@WebService
public class WeatherInterfaceImpl implements WeatherInterface {
@Override
public String queryWeather(String cityName) {
System.out.println("from client.."+cityName);
String result = "晴朗";
System.out.println("to client..."+result);
return result;
}
public static void main(String[] args) {
//发送webservice服务
Endpoint.publish("http://192.168.1.100:1234/weather", new WeatherInterfaceImpl());
}
}
注意:
SEI实现类中至少要有一个非静态的公开方法需要作为webservice服务方法。
public class 上边要加上@WebService
- endpoint发布服务
//发送webservice服务
Endpoint.publish("http://192.168.1.100:1234/weather", new WeatherInterfaceImpl());
第二步:查看wsdl
Webservice发布成功,通过wsdl查看webservice发布的正确性
- 在地址栏输入(注意后面的参数?wsdl)
- Wsdl不是webService,只是获取一个用于描述WebService的说明文件
- wsdl- WebServiceDescriptionLanguage,是以XML文件形式来描述WebService的”说明书”,有了说明书,我们才可以知道如何使用或是调用这个服务.
第三步:Wsimport生成客户端调用类
Wsimport介绍
wsimport是jdk自带的webservice客户端工具,可以根据wsdl文档生成客户端调用代码(java代码).当然,无论服务器端的WebService是用什么语言写的,都可以生成调用webservice的客户端代码,服务端通过客户端代码调用webservice。
wsimport.exe位于JAVA_HOMEin目录下.
常用参数为:
-d<目录> - 将生成.class文件。默认参数。
-s<目录> - 将生成.java文件。
-p<生成的新包名> -将生成的类,放于指定的包下。
(wsdlurl) - http://server:port/service?wsdl,必须的参数。
示例:
C:/> wsimport -s . http://127.0.0.1:1234/weather?wsdl
注意:-s不能分开,-s后面有个小点
客户端生成注意事项:
- 可以通过java –version检查你当前的版本号保存是jdk1.6以上。Jdk1.6.0_13以后的版本支持jaxws2.1。
- 在Eclipse中创建一个空的java工程为wsimport,此工程作为存放客户端代码。
- cmd命令行进入此wsimport 工程的src目录,
输入以下命令:


参数说明:-s是指编译出源代码文件,后面的.(点)指將代码放到当前目录下.
最后面的http….是指获取wsdl说明书的地址.
- 生成完成,刷新Eclipse中wsimport工程,将src下生成.java文件代码Copy到webservice客户端工程(见下)中。
第四步:客户端编写
代码如下:
/**
* 天气查询客户端
* @author 传智播客 Java学院 苗润土
* @version V1.0
*/
public class WeatherClient {
public static void main(String[] args) {
//创建服务视图
WeatherInterfaceImplService weatherInterfaceImplService =new WeatherInterfaceImplService();
//通过服务视图得到服务端点
WeatherInterfaceImpl weatherInterfaceImpl= weatherInterfaceImplService.getPort(WeatherInterfaceImpl.class);
//调用webservice服务方法
String result = weatherInterfaceImpl.queryWeather("郑州");
System.out.println(result);
}
}
公网天气查询:
操作步骤
第一步:找到天气查询的webservice WSDL文件拷贝到D盘根目录
第二步:根据WSDL生成客户端调用类,使用wsimport生成
Wsimport –s . file:///d:WeatherWebService.wsdl
第三步:将生成的代码拷贝至工程中
第四步:编写客户端调用代码
客户端代码如下:
/**
* 互联网天气查询客户端
* @author 传智播客 Java学院 苗润土
* @version V1.0
*/
public class WebWeatherClient {
public static void main(String[] args) {
//创建服务视图
WeatherWebService weatherWebService = new WeatherWebService();
//通过服务视图得到服务端点
WeatherWebServiceSoap weatherWebServiceSoap =weatherWebService.getWeatherWebServiceSoap();
//调用webservice服务方法
ArrayOfString arrayOfString = weatherWebServiceSoap.getWeatherbyCityName("郑州");
List<String> resultlist = arrayOfString.getString();
//查询天气查询结果
for(String result:resultlist){
System.out.println(result);
}
}
}
使用javax.xml.ws.Service进行客户端编程
步骤
第一步:创建URL,指定资源地址即wsdl地址
第二步:创建Qname,指定命名空间和视图名称
第三步:创建服务视图对象service
第四步:从服务视图中得到服务端点即服务接口(这里需要服务接口类型,可使用wsimport生成后只留下porttype)
第五步:通过服务端点调用服务方法
天气查询客户端代码
/**
* 使用javax.xml.ws.Service调用webservice服务
* @author 传智播客 Java学院 苗润土
* @version V1.0
*/
public class WeatherClient2 {
public static void main(String[] args) throws MalformedURLException {
//定义url,参数为wsdl地址
URL url = new URL("http://192.168.1.100:1234/weather?wsdl");
//定义qname,第一个参数是命名空间,第二个参数名称是wsdl里边的服务名
QName qName = new QName("http://impl.sei.jaxws.ws.itcast.cn/", "WeatherInterfaceImplService");
//创建服务视图
Service service = Service.create(url, qName);
//通过服务视图得到服务端点
WeatherInterfaceImpl weatherInterfaceImpl =service.getPort(WeatherInterfaceImpl.class);
//调用webservice
System.out.println(weatherInterfaceImpl.queryWeather("郑州"));
}
}
公网天气查询客户端代码:
/**
* 使用javax.xml.ws.Service调用公网webservice服务
* @author 传智播客 Java学院 苗润土
* @version V1.0
*/
public class WebWeatherClient2 {
public static void main(String[] args) throws MalformedURLException {
//定义url,参数为wsdl地址
URL url = new URL("file:/D:/WeatherWebService.wsdl");
//定义qname,第一个参数是命名空间,第二个参数名称是wsdl里边的服务名
QName qName = new QName("http://WebXml.com.cn/", "WeatherWebService");
//创建服务视图
Service service = Service.create(url, qName);
//通过服务视图得到服务端点
WeatherWebServiceSoap weatherWebServiceSoap =service.getPort(WeatherWebServiceSoap.class);
//调用webservice
ArrayOfString arrayOfString = weatherWebServiceSoap.getWeatherbyCityName("郑州");
List<String> resultlist = arrayOfString.getString();
//查询天气查询结果
for(String result:resultlist){
System.out.println(result);
}
}
}
公网手机号归属地查询客户端代码:
/**
* 使用service类调用公网手机号归属地查询服务
*/
public class MobileClient_Service {
public static void main(String[] args) throws MalformedURLException {
//wsdl的url
URL url = new URL("http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx");
//定义servicename
QName serviceName = new QName("http://WebXml.com.cn/", "MobileCodeWS");
//得到 服务视图
Service service = Service.create(url, serviceName);
//得到portType
MobileCodeWSSoap mobileCodeWSSoap = service.getPort(MobileCodeWSSoap.class);
//设备portType的方法
String resultString = mobileCodeWSSoap.getMobileCodeInfo("1863819", "");
//查询数据
System.out.println(resultString);
}
}
使用Service调用和Wsimport代码调用方式区别:
Wsimport生成代码调用webservice无法指定webservice的地址,使用生成的服务视图类获取服务端点(postType)实例。
Service调用Webservice可以指定webservice的地址,只需要服务端点的接口即可获取服务端点实例。
总结:
第一步:阅读wsdl,搞清楚服务视图 service、 协议格式binding 服务端点porttype
第二步:创建服务视图
第三步:创建服务端点
第四步:通过服务端点调用服务方法
@WebService注解
@WebService-定义服务,在public class上边
targetNamespace:指定命名空间
name:portType的名称
portName:port的名称
serviceName:服务名称
endpointInterface:SEI接口地址,如果一个服务类实现了多个接口,只需要发布一个接口的方法,可通过此注解指定要发布服务的接口。
1.2 @WebMethod-定义方法,在公开方法上边
operationName:方法名
exclude:设置为true表示此方法不是webservice方法,反之则表示webservice方法
1.3 @WebResult-定义返回值,在方法返回值前边
name:返回结果值的名称
1.4 @WebParam-定义参数,在方法参数前边
name:指定参数的名称
注意
如果修改webservice的接口内容,比如namespace、portType,必须要重新生成客户端调用代码。
1 Cxf入门
1.1 什么是cxf
Cxf,apache下的webservice的开源框架。
Apache CXF = Celtix + Xfire,开始叫 Apache CeltiXfire,后来更名为 Apache CXF 了,以下简称为 CXF。Apache CXF 是一个开源的 web Services 框架,CXF 帮助您构建和开发 web Services ,它支持多种协议,比如:SOAP1.1,1,2、XML/HTTP、RESTful HTTP 或者 CORBA。
CORBA(Common Object Request Broker Architecture公共对象请求代理体系结构,早期语言使用的WS。C,c++,C#)
Cxf是基于SOA总线结构,依靠spring完成模块的集成,实现SOA方式。
灵活的部署:可以运行有Tomcat,Jboss,Jetty(内置),weblogic上面。
1.2 环境配置
下载cxf2.7.11版本。


从官网下载2.7.11


环境变量配置:
JAVA_HOME,
新建 CXF_HOME=cxf的目录
Path = %JAVA_HOME%in;%CXF_HOME%in;
CLASSPATH=.;%CXF_HOME%libcxf-manifest.jar
1.3 Cxf第一个程序
1.3.1 服务端
1.3.1.1 开发SEI及SEI实现类
Cxf开发SEI需要将@webservice注解加在接口中.
SEI接口:


SEI实现类:

1.3.1.2 发布服务代码:


1.3.2 客户端
客户端开发技术不受webservice服务端限制,服务端使用cxf,客户端采用多种方法,比如Service类标准方法。

1.3.2.1 客户端工程中加jar包
如果使用cxf提供客户端类或方法,需要加入cxf的jar包。
1.3.2.2 Wsdl2java工具生成客户端调用代码
使用cxf的wsdl2java工具生成。
生成源文件:




1.3.3 小结
Cxf编程方式实现webservice:
JaxWsServerFactoryBean:发布webservice服务
JaxWsProxyFactoryBean:调用webservice服务端
Cxf和spring整合后,可以将上边的编程方式修改为spring配置方式实现。
内部 使用JaxWsServerFactoryBean和JaxWsProxyFactoryBean
1.3.4 Cxf发布soap1.2
使用cxf发布soap1.2不需要下载jaxws-ri扩展包。
在服务接口的上面添加
@BindingType(javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_BINDING)
如下:
@WebService
@BindingType(javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_BINDING)
public interface WeatherServerInterface
1 Cxf和spring整合
1.1 思路
Cxf框架本身依赖spring,从官方下载cxf包中有spring的jar包。
上边使用JaxWsServerFactoryBean和JaxWsProxyFactoryBean,改为spring配置方式。
发布服务:使用spring和cxf整合的标签<jaxws:server
客户端调用服务:使用spring和cxf整合的标签<jaxws:client
上边的<jaxws:server和<jaxws:client相当于spring容器的bean,发布服务和客户端调用交给spring容器管理。
1.2 服务端
1.2.1 创建web工程


1.2.2 加入cxf的jar包

1.2.3 开发SEI和实现类
Cxf开发SEI需要将@webservice注解加在接口中.
SEI接口:

SEI实现类:

1.2.4 编写applicationContext.xml
文件中约束包括:spring的、cxf和spring整合


1.2.1 在web.xml中配置cxf的servlet
cxf的servlet用于解析cxf发布webservice。

1.2.2 在web.xml中加载spring

1.2.3 启动tomcat

1.2.4 测试注意
因为通过spring和cxf整合将webservice通过tomcat发布,webservice和应用程序共用一个端口都是8080。
测试webservice和应用程序(jsp)是否可以共存(都可以访问)。
正式上线使用80端口。
客户端
使用<jaxws:client调用服务端,<jaxws:client需要cxf和spring整合环境。
1.1.1 创建一个java工程
加入cxf的jar包。
1.1.2 使用wsdl2java/wsimport工具生成客户端调用代码

1.1.3 编写applicationContext.xml
使用<jaxws:client配置客户端调用服务端。

1.1.4 测试

1 回顾
如何使用 cxf发布soap1.1和soap1.2?
使用jaxws实现SOAP1.1,1,2。
方法1:
Cxf编程实现:
- 使用jaxwsServerFactoryBean发布 webservice服务端。
需要设置:
jaxwsServerFactoryBean.setAddress(“webservice地址”)
jaxwsServerFactoryBean.setServiceClass(“porttype类路径”);//由程序员编写的
jaxwsServerFactoryBean.setServiceBean(“porttype类对象”);
jaxwsServerFactoryBean.create();//发布一个服务
- 使用jaxwsProxyFactoryBean实现客户端调用webservice服务
jaxwsServerFactoryBean.setAddress(“webservice的wsdl地址”)
jaxwsServerFactoryBean.setServiceClass(“porttype类路径”);//portType是由wsdl2java工具生成
jaxwsServerFactoryBean.setCreate();//创建porttype对象
方法2:
Cxf和spring整合开发服务端和客户端。
- 使用<jaxws:Server 发布 webservice服务端
在<jaxws:Server设置 Address、serviceClass、serviceBean
- 使用<jaxws:Client 调用webservice服务
在<jaxws:Server设置 Address、serviceClass
1 CXF发布rest风格的webservice
1.1 什么是restFul
REST 是一种软件架构模式,只是一种风格,rest服务采用HTTP 做传输协议,REST 对于HTTP 的利用分为以下两种:资源定位和资源操作。
- 资源定位
更加准确去定位一个互联网资源。使用url定位一个互联网资源。
比如:查询一个学生信息url
资源定位要定位一个学生信息:
不使用rest的url:http://ip:port/queryUser.action?userType=XXX&studentid=001&XXXX
使用 rest的url:http://ip:port/user/student/001
使用rest方式表达url更加简单、可以准确表达这个url是一个学生信息查询url
- 资源操作
利用HTTP 的GET、POST、PUT、DELETE 四种操作来表示数据库操作的SELECT、UPDATE、INSERT、DELETE 操作。
比如:
更新学生信息:
设置http请求的方法为post。
定义rest的url:http://ip:port/user/student/001/张三/13。。
Rest方式一般要求url中不要有动词。动词采用GET、POST、PUT、DELETE表示。
Rest风格是对http协议很好的诠释。
Rest好处:
定义的url对资源定位更加准确、简单。
Rest缺点:
如果rest的url定义层级比较多,可读性较差。
1.2 Cxf发布rest风格的webservice
1.2.1 目标
使用rest风格表示webservice,cxf发布的webservice地址就是rest风格.
rest风格webservice,不采用soap,直接采用http传输数据。
需求:
Rest Get方法:
查询学生信息,传输参数学生信息id在url中定义。
比如:http://ip:port/user/student/001 001就是参数。
Rest一般返回结果:
xml或json。
1.2.2 实现
使用cxf发布rest的webservice,使用jaxrs(java开发webservice一个规范)
1.2.2.1 创建web工程

1.2.2.2 加入cxf的jar包
1.2.2.3 编写pojo
学生信息的pojo。
要使用@XmlRootElement(name="student"),将pojo转成xml。

1.2.2.4 编写SEI

1.2.2.5 编写SEI实现类
实现类中不用添加rest注解。

1.2.2.6 发布rest服务
使用JaxRSServerFactoryBean发布rest服务。

1.2.2.7 测试 rest服务
http://127.0.0.1:12345/rest/student/querylist/001?_type=xml 查询学生信息列表,返回xml
http://127.0.0.1:12345/rest/student/querylist/001?_type=json 查询学生信息列表,返回json
1.1.1.1 使用spring配置方式发布rest
编写applicationContext.xml


1.1.1.1 Rest服务的客户端ajax方式
上边发布的http的get服务。
使用http的get请求,调用rest接口(http的get请求接口)。
可以在页面使用ajax请求rest地址
可以使用httpClient方式请求rest地址。
