一、WebService概述
1.1 WebService是什么
WebService是一种跨编程语言和跨操作系统平台的远程调用技术。
Web service是一个平*立的,低耦合的,自包含的、基于可编程的web的应用程序,可使用开放的XML(标准通用标记语言下的一个子集)标准来描述、发布、发现、协调和配置这些应用程序,用于开发分布式的互操作的应用程序。
Web Service技术, 能使得运行在不同机器上的不同应用无须借助附加的、专门的第三方软件或硬件, 就可相互交换数据或集成。依据Web Service规范实施的应用之间, 无论它们所使用的语言、 平台或内部协议是什么, 都可以相互交换数据。Web Service是自描述、 自包含的可用网络模块, 可以执行具体的业务功能。Web Service也很容易部署, 因为它们基于一些常规的产业标准以及已有的一些技术,诸如标准通用标记语言下的子集XML、HTTP。
Web Service减少了应用接口的花费。Web Service为整个企业甚至多个组织之间的业务流程的集成提供了一个通用机制。
1.2 WebService能做什么
- 不同系统、不同平台、不同语言之间的通信访问和远程调用
- 应用程序的集成,不同业务的整合
1.3 WebService的两种类型
- 一种是以SOAP协议风格的Webservice
- 一种是Restful风格的Webservice
1.4 WebService核心组件
- XML和HTTP
- SOAP: 简单对象访问协议
- WSDL: WebService描述语言
- UDDI:统一描述、发现和集成协议
SOAP
soap就是调用中用的协议
Web service建好以后,你或者其他人就会去调用它。简单对象访问协议(SOAP)提供了标准的RPC方法来调用Web service。实际上,SOAP在这里有点用词不当:它意味着下面的Web service是以对象的方式表示的,但事实并不一定如此:你完全可以把你的Web service写成一系列的C函数,并仍然使用SOAP进行调用。SOAP规范定义了SOAP消息的格式,以及怎样通过HTTP协议来使用SOAP。SOAP也是基于XML(标准通用标记语言下的一个子集)和XSD的,XML是SOAP的数据编码方式。
WSDL
wsdl只要描述的就是系统中有哪些接口,接口名是什么,有哪些参数,返回值是什么。
你会怎样向别人介绍你的Web service有什么功能,以及每个函数调用时的参数呢?你可能会自己写一套文档,你甚至可能会口头上告诉需要使用你的Web service的人。这些非正式的方法至少都有一个严重的问题:当程序员坐到电脑前,想要使用你的Web service的时候,他们的工具(如Visual Studio)无法给他们提供任何帮助,因为这些工具根本就不了解你的Web service。
解决方法是:用机器能阅读的方式提供一个正式的描述文档。Web service描述语言(WSDL)就是这样一个基于XML(标准通用标记语言下的一个子集)的语言,用于描述Web service及其函数、参数和返回值。WSDL既是机器可阅读的,又是人可阅读的,这将是一个很大的好处。一些最新的开发工具既能根据你的Web service生成WSDL文档,又能导入WSDL文档,生成调用相应Web service的代码。
UDDI
可以理解为查询服务的,就是获取wsdl的
webservice访问的流程
二、WebService的使用
1、Demo
步骤:
1、创建工程
搭建maven项目,引入依赖
<dependencies>
<!-- https://mvnrepository.com/artifact/org.apache.cxf/cxf-rt-frontend-jaxws -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>3.2.7</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.cxf/cxf-rt-transports-http-jetty -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http-jetty</artifactId>
<version>3.2.7</version>
</dependency>
</dependencies>
2、写接口
注意在接口上加@WebService
package com.keller.web.service;
import javax.jws.WebService;
@WebService
public interface DemoService {
String sayHello(String name, int age);
}
3、写实现类
public class DemoServiceImpl implements DemoService {
public String sayHello(String name, int age) {
return "Hello!!!" + name + "(" + age + " years old)";
}
}
4、写服务端启动类
public class MainService {
public static void main(String[] args) {
JaxWsServerFactoryBean serverFactoryBean = new JaxWsServerFactoryBean();
serverFactoryBean.setAddress("http://localhost:8080/demo");
serverFactoryBean.setServiceClass(DemoService.class);
Server server = serverFactoryBean.create();
server.start();
System.out.println("服务端已启动");
}
}
5、写客户端调用类
public class MainClient {
public static void main(String[] args) {
JaxWsProxyFactoryBean jaxWsProxyFactoryBean = new JaxWsProxyFactoryBean();
jaxWsProxyFactoryBean.setAddress("http://localhost:8080/demo");
jaxWsProxyFactoryBean.setServiceClass(Demo.class);
Demo demo = (Demo)jaxWsProxyFactoryBean.create();
System.out.println(demo.sayHello("hgx", 24));
}
}
三、soap协议
3.1 SOAP协议是什么?
- 简单对象访问协议(Simple Object Access Protocol,SOAP)是一种轻量的、简单的、基于XML的协议,它被设计成在WEB上交换结构化的和固化的信息。
- SOAP 是基于 XML 的简易协议,可使应用程序在 HTTP 之上进行信息交换。
3.2 SOAP协议什么样?
一条 SOAP 消息就是一个普通的 XML 文档,包含下列元素:
Envelope 元素,必有,可把此 XML 文档标识为一条 SOAP 消息
Header 元素,可选,包含头部信息
Body 元素,必有,包含所有的调用和响应信息
Fault 元素,可选,提供有关在处理此消息所发生错误的信息
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<soap:Fault>
<faultcode>soap:Server</faultcode>
<faultstring>
No binding operation info while invoking unknown method with params unknown.
</faultstring>
</soap:Fault>
</soap:Body>
</soap:Envelope>
四、WSDL文件解读
首先看一个wsdl文件的样子
<definitions> 相当于import,但是包名(看上图中xmls:tns)是反转过来的,那么表示了实现类,但是多了个service
<types> 能看到方法的参数
</types>
<message> 有两个,输入一个,输出一个
</message>
<portType> 相当于接口名
</portType>
<binding> 表示了宇那个接口进行绑定
</binding>
<service> 可以看到实现类是哪个
</service>
</definitions>
看wsdl文件的时候,首先通过查看实现类是哪个,然后通过查看接口名和接口中的方法,再通过看方法有哪些参数。
五、JAX-WS工具
5.1 作用
服务端开发完成后,客户端需要全部自己写,比较麻烦,JAX-WS就是可以自动生成客户端的代码
5.2 使用方法
- 下载的压缩包里面包含了工具,下载地址:http://cxf.apache.org/download.html
- bin目录下运行wsdl2java命令,通过wsdl生成java代码,例如使用:
wsdl2java
根据wsdl生成文件
D:\apache-cxf-3.2.7\bin>wsdl2java http://localhost:8080/demo?wsdl
-
正常执行后,在bin目录下会生成一个文件包
其中包含了大部分客户端代码
六、Spring整合cxf(rest风格)
6.1 加依赖
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.1.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>
<!-- 添加CXF dependency -->
<!-- https://mvnrepository.com/artifact/org.apache.cxf/cxf-rt-frontend-jaxws -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>3.2.7</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.cxf/cxf-rt-transports-http -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>3.2.7</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.cxf/cxf-rt-frontend-jaxrs -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxrs</artifactId>
<version>3.2.7</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.cxf/cxf-rt-transports-http-jetty -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http-jetty</artifactId>
<version>3.2.7</version>
</dependency>
<!--没有这两个依赖会:No message body writer has been found for class com.hgx.web.service.restful.bean.Student, ContentType: application/json-->
<!--https://mvnrepository.com/artifact/org.apache.cxf/cxf-rt-rs-extension-providers-->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-rs-extension-providers</artifactId>
<version>3.2.7</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.codehaus.jettison/jettison -->
<dependency>
<groupId>org.codehaus.jettison</groupId>
<artifactId>jettison</artifactId>
<version>1.4.0</version>
</dependency>
<!--解决rest风格的api没有wadl-->
<!-- https://mvnrepository.com/artifact/org.apache.cxf/cxf-rt-rs-service-description -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-rs-service-description</artifactId>
<version>3.2.7</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.5</version>
</dependency>
</dependencies>
6.2 加配置
resources下的application-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:jaxrs="http://cxf.apache.org/jaxrs"
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 http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml"/>
<jaxws:endpoint id="helloworld" implementor="com.keller.webservice.CustomerServiceimpl" address="/HelloWorld"></jaxws:endpoint>
<!--注意:坑爹的idea 导入的jaxrs-common.xsd不正确 应该是jaxrs.xsd -->
<jaxrs:server id="customerService" address="/CustService">
<jaxrs:serviceBeans>
<bean class="com.keller.webservice.CustomerServiceimpl"/>
</jaxrs:serviceBeans>
</jaxrs:server>
</beans>
web.xml
<web-app>
<display-name>Archetype Created Web Application</display-name>
<!-- 配置 Spring 配置文件的名称和位置 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:application-cxf.xml</param-value>
</context-param>
<!-- 启动 IOC 容器的 ServletContextListener -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--webservice 重要 -->
<servlet>
<servlet-name>spring-cxf</servlet-name>
<display-name>spring-cxf</display-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>spring-cxf</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<!--webservice-->
</web-app>
6.3 写接口
@Path("/crm")
public interface CustomerService {
@GET
@Path("/customer/{customer_id}")
@Produces("application/json")
public Customer getCustomerById(@PathParam("customer_id") String customer_id);
}
6.4 写实现类
@Path("/crm")
public class CustomerServiceimpl implements CustomerService{
@GET
@Path("/customer/{customer_id}")
@Produces("application/json")
public Customer getCustomerById(@PathParam("customer_id") String customer_id) {
Customer customer = new Customer(customer_id, "z3", 18);
System.out.println(customer);
return customer;
}
}
6.5 添加启动类
public class MainServer {
public static void main(String[] args) {
JAXRSServerFactoryBean jaxrsServerFactoryBean = new JAXRSServerFactoryBean();
jaxrsServerFactoryBean.setAddress("http://localhost:8080/cxfspring");
jaxrsServerFactoryBean.setResourceClasses(CustomerServiceimpl.class);
jaxrsServerFactoryBean.create();
}
}
6.6 测试
在浏览器中输入:
http://localhost:8080/cxfspring/crm/customer/2222
输出结果:
{"customer":{"age":18,"id":2222,"name":"z3"}}
特别注意:实体类上一定要加上@XmlRootElement注解,不然会下面这个错误
No message body writer has been found for class
关于rest的介绍,看了下面这个图片还是不能描述出来。