一、WebService概述
1.1 什么是WebService
- 基于Web的服务:服务器端整出一些资源让客户端应用访问(获取数据)
- 一个跨语言、跨平台的规范(抽象)
所谓跨编程语言和跨操作平台,就是说服务端程序采用java编写,客户端程序则可以采用其他编程语言编写,反之亦然!跨操作系统平台则是指服务端程序和客户端程序可以在不同的操作系统上运行。
- 多个跨平台、跨语言的应用间通信整合的方案(实际)
1.2 为什么要用WebService?
【问题一】
如果我们的网站需要提供一个天气预报这样一个需求的话,那我们该怎么做?????
天气预报这么一个功能并不是简单的JS组件就能够实现的,它的数据是依赖数据库分析出来的,甚至需要卫星探测…我们个人建站是不可能搞这么一个数据库的吧。
那么既然我们自己干不了,我们可以去找别人吗???我们从搜索引擎搜索,可以发现很多提供天气预报的网站,但是它返回的是一个网页,而我们仅仅需要的是对应的数据!
我们可能就在想,我们能不能仅仅只要它返回的数据,而并不是经过加工处理后返回的网页呢??
于是乎,webService就诞生了,webservice就是一个部署在Web服务器上的,它向外界暴露出一个能够通过Web进行调用的API。也就是说:当我们想要获取天气预报的信息,我们可以调用别人写好的service服务,我们调用就能够得到结果了!
【问题二】
可是我们写网站主流的就有好几个平台:Java、.net、PHP等等,那么部署在Web服务器上的服务器也就是webserice怎么能够就让我们不同的平台都能够调用呢??
我们知道java、.net这样的平台他们语言的基本数据类型、复杂数据类型就可能不一样,那么怎么能够实现调用的呢???
来引用一段话
大家在写应用程序查询数据库时,并没有考虑过为什么可以将查询结果返回给上层的应用程序,甚至认为,这就是数据库应该做的,其实不然,这是数据库通过TCP/IP协议与另一个应用程序进行交流的结果,而上层是什么样的应用程序,是用什么语言,数据库本身并不知道,它只知道接收到了一份协议,这就是SQL92查询标准协议。
无论是Java、.net、PHP等等的平台,只要是网页开发都是可以通过http协议来进行通信的,并且返回的数据格式XML也是通用的。
1.3 什么时候使用WebService?
- 同一家公司的新旧应用之间
- 不同公司的应用之间
- 一些提供数据的内容聚合应用:天气预报、股票行情
我们可以调用互联网上查询天气信息Web服务,然后将它嵌入到我们的程序(C/S或B/S程序)当中来,当用户从我们的网点看到天气信息时,他会认为我们为他提供了很多的信息服务,但其实我们什么也没有做,只是简单调用了一下服务器上的一段代码而已。 学习WebService可以将你的服务(一段代码)发布到互联网上让别人去调用,也可以调用别人机器上发布的WebService,就像使用自己的代码一样.。
1.4 WebService的特点
-
WebService通过HTTP POST方式接受客户的请求
-
WebService与客户端之间一般使用SOAP协议传输XML数据
-
WebService本身就是为了跨平台或跨语言而设计的
二、几个重要的术语
2.1 WSDL
WSDL(WebService Description Language):web 服务描述语言。就是一个xml文档,用于描述当前服务的一些信息(服务名称、服务的发布地址、服务提供的方法、方法的参数类型、方法的返回值类型等)。
- 对应.wsdl文档,一个webservice对应一个唯一的wsdl文档
- 定义了客户端与服务端发送请求和响应的数据格式和过程
- 通过XML形式说明服务在什么地方——地址
- 通过XML形式说明服务提供什么样的方法——如何调用
2.2 SOAP
SOAP(Simple Object Access Protocol):简单对象访问协议。
WebService通过HTTP协议发送请求和接收结果时,发送的请求内容和结果内容都采用XML格式封装,并增加了一些特定的HTTP消息头,以说明 HTTP消息的内容格式,这些特定的HTTP消息头和XML内容格式就是SOAP协议。SOAP提供了标准的RPC方法来调用WebService。
【SOAP的特点】
- SOAP作为一个基于XML语言的协议用于在网上传输数据
- SOAP = 在HTTP的基础上+XML数据
- SOAP是基于HTTP的
【SOAP的组成】
- Envelope:必须的部分。以XML的根元素出现。
- Headers:可选的
- Body:必须的。body部分要包含执行的服务器的方法,和发送到服务器的数据
【SOAP消息】
- 请求消息
- 响应消息
三、基于jdk1.7发布WebService服务
3.1 服务端发布
第一步:创建一个Java项目
第二步:创建一个类,加入Webservice注解
第三步:提供一个方法sayHello
第四步:在main方法中调用jdk提供的发布服务的方法
第五步:访问服务的wsdl文档(服务的发布地址+?wsdl)
http://192.168.34.1:8080/hello?wsdl(此端口号并非指tomcat)
// 1、添加注解 @WebService public class HelloService { // 2、至少包含一个可以对外公布的服务 public String sayHello(String name, int i) { System.out.println("服务端的sayHello被调用了"); return "hello" + name; } public static void main(String[] args) { // 绑定地址 String address = "http://192.168.34.1:8080/hello"; // 实现者,即谁提供服务 Object implementor = new HelloService(); // 使用端点服务,将对象绑定到一个地址和端口。同时必须要在端口后面给服务取一个名称 Endpoint.publish(address, implementor); } }
3.2 客户端调用
第一步:使用wsimport命令解析wsdl文件生成本地代码,并导入到工程中
注意:要以管理员的身份执行wsimport命令,否则会报错:
第二步:通过本地代码创建一个代理对象
第三步:通过代理对象实现远程调用
【调用时可能出现的错误】:Two classes have the same XML type name
四、apache CXF入门
4.1 CXF概述
Apache CXF 是一个开源的 WebService 框架,CXF可以用来构建和开发 WebService,这些服务可以支持多种协议,比如:SOAP、POST/HTTP、HTTP ,CXF 大大简化了WebService并且可以天然地和Spring 进行无缝集成。CXF是 Celtrix (ESB框架)和 XFire(webserivice) 合并而成,核心是org.apache.cxf.Bus(总线),类似于Spring的 ApplicationContext,CXF默认是依赖于Spring的。 CXF 发行包中的jar包,如果全部放到lib中,需要 JDK1.6 及以上,否则会报JAX-WS版本不一致的问题。CXF 内置了Jetty服务器 ,它是servlet容器。
CXF的官网:cxf.apache.org
4.2 CXF框架的特点
- 与Spring、Servlet做了无缝对接,cxf框架里面集成了Servlet容器Jetty
- 支持注解的方式来发布webservice
- 能够显示一个webservice的服务列表
- 能够添加拦截器:输入拦截器、输出拦截器 :输入日志信息拦截器、输出日志拦截器、用户权限认证的拦截器
4.3 服务端开发
第一步:创建动态web项目
第二步:导入CXF相关jar包
第三步:在web.xml中配置CXF框架提供的一个Servlet
<!--配置CXF框架提供的servlet--> <servlet> <servlet-name>cxf</servlet-name> <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class> <!--通过初始化参数指定CXF框架的配置文件位置--> <init-param> <param-name>config-location</param-name> <param-value>classpath:cxf.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>cxf</servlet-name> <url-pattern>/service/*</url-pattern> </servlet-mapping>
第四步:在类路径下提供cxf.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:soap="http://cxf.apache.org/bindings/soap" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/bindings/soap http://cxf.apache.org/schemas/configuration/soap.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"> <!-- 引入CXF Bean定义如下,早期的版本中使用 --> <import resource="classpath:META-INF/cxf/cxf.xml" /> <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" /> <import resource="classpath:META-INF/cxf/cxf-servlet.xml" /> </beans>
第五步:开发一个接口和实现类
- HelloService
@WebService public interface HelloService { public String sayHello(String name); }
-
HelloServiceImpl
public class HelloServiceImpl implements HelloService { @Override public String sayHello(String name) { System.out.println("基于CXF开发的服务端sayHello方法被调用了"); return "hello"+name; } }
第六步:在cxf.xml中注册服务
<bean id="helloService" class="cn.itcast.cxf.HelloServiceImpl"></bean> <!--注册服务--> <jaxws:server id="myService" address="/cxfService"> <jaxws:serviceBean> <ref bean="helloService"></ref> </jaxws:serviceBean> </jaxws:server>
第七步:访问服务的使用说明书——http://ip:port/projectName/service/address?wsdl
- ip:当前访问的本地ip
- port:tomcat的端口号,因为该项目是部署在tomcat上发布的
- projectName:项目名称
- service:web.xml中配置的servlet拦截路径
- address:cxf.xml中配置的address
4.4 服务端开发
【方式一:使用jdk提供的wsimport命令生成本地代码完成调用】
【方式二:使用CXF提供的方式】
第一步:创建Java项目并导入CXF相关jar包
第二步:使用wsimport或者CXF提供wsdl2java生成本地代码,只需要生成的接口文件和实体类
第三步:将接口文件复制到项目中(此处会报错,因为没有导入ObjectFactory.java文件,所以HelloService接口文件的ObjectFactory.class删除即可)
第四步:提供spring配置文件(cxf.xml),注册客户端代理对象
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:soap="http://cxf.apache.org/bindings/soap" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/bindings/soap http://cxf.apache.org/schemas/configuration/soap.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"> <!--注册CXF客户端代理对象,通过spring框架创建这个代理对象,使用代理对象实现远程调用--> <!--address:此代理对象需要调用的服务的完整地址 serviceClass:引入的接口的完整路径 --> <jaxws:client id="myClient" address="http://192.168.34.1:8080/cxf_service/service/cxfService" serviceClass="cn.itcast.client.HelloService"></jaxws:client> </beans>
第五步:读取spring配置文件,创建spring工厂,从工厂中获取代理对象,实现远程调用
public class App { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("cxf.xml"); HelloService proxy = (HelloService) context.getBean("myClient"); String ret = proxy.sayHello("test"); System.out.println(ret); } }
参考:https://www.imooc.com/article/25537?block_id=tuijian_wz
https://www.cnblogs.com/jiyukai/p/9249103.html