Web Service
解决的问题
- 不同系统、不同平台、不同语言之间的通信访问和调用
- 应用程序的集成,不同业务的整合
Web Service概述
Web Service的定义
web服务是一种服务导向架构的技术,通过标准的web协议提供服务,目的是保证不同平台的应用服务可以互操作。
从表面上看,Web service 就是一个应用程序,它向外界暴露出一个能够通过Web进行调用的API。这就是说,能够用编程的方法通过Web来调用这个应用程序。
深层次上看Web service是一种新的Web应用程序分支,它们是自包含、自描述、模块化的应用,可以在网络中被描述、发布、查找以及通过Web来调用。
Web service运行与访问过程
麦当劳点餐的例子
Web service核心组件
- XML和HTTP
- SOAP:简单对象访问协议
- WSDL:Web service描述语言
- UUDI:统一描述、发现和集成协议
Web service主流框架简介
AXIS
axis全称Apache Extensible Interaction System 即阿帕奇可扩展交互系统
Axis是一款开源的Web Service运行引擎,本质上就是一个SOAP引擎,提供创建服务器端、客户端和网关SOAP操作的基本框架。
Axis分为1.x系列和2系列,两个系列体系结构和使用上有较大的区别,相对而言,Axis1.x更加稳定,文档也比较齐全。
官网:http://axis.apache.org/
XFire
XFire是下一代的java SOAP框架。XFire提供了非常方便的API,使用这些API可以开发面向服务(SOA)的程序。它支持各种标准,性能优良(基于低内存的STAX模型)。
CXF
Apache CXF = Celtix + XFire
Apache CXF的前身叫Apache CeltiXfire,现在已经正式更名为 Apache CXF了,以下简称CXF。CXF 继承了 Celtix 和 XFire 两大开源项目的精华,提供了对 JAX-WS 全面的支持,并且提供了多种 Binding 、DataBinding、Transport 以及各种 Format 的支持,并且可以根据实际项目的需要,采用代码优先(Code First)或者 WSDL 优先(WSDL First)来轻松地实现 Web Services 的发布和使用。Apache CXF已经是一个正式的Apache顶级项目。
官网:https://cxf.apache.org/
CXF之HelloWorld
- 建工程添jar包
- 建HelloWorld服务接口(@WebService注解添加)
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
@WebService
public interface HelloWorld {
@WebMethod
@WebResult(name="sayHelloRetValue")
public String sayHello(@WebParam(name="userName")String name,@WebParam(name="userAge")int age);
}
- 建HelloWorldImpl服务实现类
public class HelloWorldImpl implements HelloWorld {
@Override
public String sayHello(String name, int age) {
return "cxf hello" + name + "\t" + age;
}
}
- 建MainServer服务启动类(JaxWsServerFactoryBean)
import org.apache.cxf.endpoint.Server;
import org.apache.cxf.jaxws.JaxWsServerFactoryBean;
public class MainServer {
public static void main(String[] args) {
JaxWsServerFactoryBean jaxWsServerFactoryBean =new JaxWsServerFactoryBean();
jaxWsServerFactoryBean.setAddress("http://localhost:9999/cxf_service");
jaxWsServerFactoryBean.setServiceClass(HelloWorldImpl.class);
Server server = jaxWsServerFactoryBean.create();
server.start();
}
}
- 测试访问有两种方法:
1)通过myeclipse工具直接调用,工具调用
2)建ClientTest调用对外暴露的服务,编码测试(JaxWsProxyFactoryBean)
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
public class ClientTest {
public static void main(String[] args) {
JaxWsProxyFactoryBean jaxWsProxyFactoryBean = new JaxWsProxyFactoryBean();
jaxWsProxyFactoryBean.setAddress("http://localhost:9999/cxf_service");
jaxWsProxyFactoryBean.setServiceClass(HelloWorld.class);
HelloWorld helloWorld = (HelloWorld)jaxWsProxyFactoryBean.create();
String result = helloWorld.sayHello("z4", 25);
System.out.println("************"+result);
}
}
SOAP协议+TCP/IP Moniter监控
SOAP协议是什么
- 简单对象访问协议(Simple Object Access Protocol,SOAP)是一种轻量级的、简单的、基于XML的协议,它被设计成在WEB上交换结构化的和固定化的信息。
- SOAP是基于XML的简易协议,可使应用程序在HTTP之上进行信息交换。
SOAP什么样
一条SOAP消息就是一个普通的XML文档,包含下列元素
- 必需的Envelope元素,可把此XML文档标识为一条SOAP消息
- 可选的Header元素,包含头部信息
- 必需的Body元素,包含所有的调用和响应信息
- 可选的Fault元素,提供有关在处理此消息所发生错误的信息
结论:SOAP是用于访问网络服务的协议。
一次Web Service的调用,不是方法的调用,而是soap消息(xml格式规范的文档片段)之间的输入与输出。
抓抓看
输入
<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:sayHello xmlns:ns2="http://test.cxf.tyust.cn/">
<arg0>z3</arg0>
<arg1>18</arg1>
</ns2:sayHello>
</soap:Body>
</soap:Envelope>
输出
<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:sayHelloResponse
xmlns:ns2="http://test.cxf.tyust.cn/">
<return>cxf helloz3 18</return>
</ns2:sayHelloResponse>
</soap:Body>
</soap:Envelope>
SOAP小总结
- 客户端到UUID上寻找Service目录
- 客户端获得WSDL文件
- 客户端按照WSDL文件的约束和规范创建SOAP客户端
- 客户端通过SOAP访问Service
WSDL文件解析
WSDL报文总体概述
<definitions>
<types>
定义web service使用的数据类型
</types>
<message>
每个消息均由一个或多个部件组成。可以把它当做java中一个函数调用的参数。
</message>
<portType>
它类似于java中的一个函数库(或一个模块、或一个类)
</portType>
<binding>
为每个端口定义消息格式和协议细节
</binding>
</definitions>
WSDL报文之wsdl:definitions
<wsdl:definitions>
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="http://test.cxf.tyust.cn/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:ns1="http://schemas.xmlsoap.org/soap/http"
name="HelloWorldImplService"
targetNamespace="http://test.cxf.tyust.cn/">
</wsdl:definitions>
xmlns:tns | 相当于java里面的import,包名反转 |
---|---|
name | 我们java程序中服务接口的实现类,SEI定义是:服务接口类+Service后缀,Service自动追加 |
targetNamespace | 命名空间,相当于java里面的package,刚好和我们java定义中的包名相反 |
其他 | 不变化、不关心 |
WSDL报文之wsdl:types
java定义的服务接口中某方法的输入参数和返回值。
WSDL报文之wsdl:message
通信消息的数据结构的抽象类型定义化定义。使用Types所定义的类型来定义整个消息的数据结构。
Web Service中每个方法包含两部分:
一个是方法的输入参数;另一个是方法的输出参数。
其实质都是基于SOAP协议将其封装为消息,所以每一个方法对应有两个消息,一个输入一个输出回应。简单而言,就是方法和Message的关系是N:2N的关系,一对二。
Message中的具体内容是part,message中的part内容可以在types中看到,它会引用types的相关内容。
WSDL报文之wsdl:portType
portType = 接口 operation = 接口中定义的方法
WSDL报文之wsdl:binding
特定端口类型的具体协议和数据格式规范的绑定
WSDL报文之wsdl:service
负责将网络通信地址赋给一个具体的绑定
JAXB
是什么
JAXB = Java Architecture for XML Binding
JAXB提供了一种快捷的方式将Java对象与XML对象进行转换。
在JAX-WS(Java的Web Service规范之一)中,JDK1.6自带的版本JAX-WS2.1,其底层支持就是JAXB。
能干嘛
JAXB可以实现POJO对象和XML之间相互转换
Marshaller接口,将Java对象序列化为XML数据。
Unmarshaller接口,将XML数据反序列化为Java对象。
怎么用
Marshaller,POJO-------->xml
Unmarshaller,xml-------->POJO
步骤:
- 定义POJO类Book.java,添加@XmlRootElement
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Book {
private long id;
private String bookName;
private double price;
public Book() {}
public Book(long id, String bookName, double price) {
super();
this.id = id;
this.bookName = bookName;
this.price = price;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getBookName() {
return bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
@Override
public String toString() {
return "Book [id=" + id + ", bookName=" + bookName + ", price=" + price + "]";
}
}
- 编写Marshaller/Unmarshaller程序
import java.io.StringReader;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
public class JAXBTest {
public static void myMarshaller() throws JAXBException{
JAXBContext jaxbContext = JAXBContext.newInstance(Book.class);
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setProperty(Marshaller.JAXB_ENCODING, "utf-8");
marshaller.marshal(new Book(11,"java",25.8d), System.out);
}
public static void myUnMarshaller() throws JAXBException{
String xmlString = "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>\r\n" +
"<book>\r\n" +
" <bookName>java</bookName>\r\n" +
" <id>11</id>\r\n" +
" <price>25.8</price>\r\n" +
"</book>\r\n" ;
JAXBContext jaxbContext = JAXBContext.newInstance(Book.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
Book book = (Book) unmarshaller.unmarshal(new StringReader(xmlString));
System.out.println(book.toString());
}
public static void main(String[] args) throws JAXBException {
myMarshaller();
myUnMarshaller();
}
}
- 输出XML报文/POJO
JAX-WS
是什么
JAX-WS = Java API for XML Web Services
JAX-WS规范是一组XML web services的JAVA API,它运行时实现会将这些API的调用转换成为对应的SOAP消息,是Sun公司提出的一套关于Web Service的开发标准。
能干嘛
JAX-WS可以完成wsdl到java的转换,即wsdl或合同契约优先
怎么用
E:\apache-cxf-3.3.7\bin目录下运行wsdl2java命令,完成wsdl到java
命令完成后结果:
用自动生成的代码完成调用访问:
单纯产生Client端口作为请求访问代码:
保留最少client访问代码
Spring整合CXF
整合步骤:
- 建工程添jar包改配置
- 修改applicationContext.xm
<?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:p="http://www.springspringframework.org/schema/p"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schema/jaxws.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml" />
<jaxws:endpoint id="helloworld"
implementor="cn.tyust.cxf.spring.HelloWorldImpl" address="/HelloWorld"></jaxws:endpoint>
</beans>
- 修改web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<servlet>
<servlet-name>cxf01</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>cxf01</servlet-name>
<url-pattern>/service/*</url-pattern>
</servlet-mapping>
</web-app>
- 编码
@WebService
public interface HelloWorld {
@WebMethod
@WebResult(name="sayHelloRetValue")
public String sayHello(@WebParam(name="userName")String name,@WebParam(name="userAge")int age);
}
public class HelloWorldImpl implements HelloWorld {
@Override
@WebMethod
@WebResult(name="sayHelloResult")
public String sayHello(@WebParam(name="userName")String name,@WebParam(name="userAge")int age) {
return "cxf hello" + name + "\t" + age;
}
}
- 部署工程到Tomcat然后启动Tomcat并访问
Restful Web Service(JAX-RS)
是什么
JAX-RS = Java API for RESTful Web Services(JSR311)
JAX-RS是JAVA EE6 引入的一个新技术。是一个Java 编程语言的应用程序接口,支持按照表述性状态转移(REST)架构风格创建Web服务。
JAX-RS使用了Java SE5引入的Java注解来简化Web服务的客户端和服务端的开发和部署。
JAX-RS提供了一些注解将一个资源类,一个POJO Java类,封装为Web资源。
包括:
@Path,标注资源类或者方法的相对路径
@GET,@PUT,@POST,@DELETE,标注方法是HTTP请求的类型。
@Produces,标注返回的MIME媒体类型
@Consumes,标注可接受请求的MIME媒体类型
@PathParam,@QueryParam,@HeaderParam,@CookieParam,@MatrixParam,@FormParam,分别标注方法的参数来自于HTTP请求的不同位置,例如
@PathParam来自于URL的路径,
@QueryParam来自于URL的查询参数,
@HeaderParam来自于HTTP请求的头信息,
@CookieParam来自于HTTP请求的Cookie。
基于JAX-RS实现的框架有Jersey,RESTEasy等。
这两个框架创建的应用可以很方便地部署到Servlet 容器中
怎么用
步骤:
- 建工程添jar包
- 建Employee.java的entity并添加注解@XmlRootElement
- 建EmployeeService接口并添加Restful风格相关的注解
- 编写EmployeeServiceImpl实现类
- 编写MainService类,启动Restful的WebService
启动后注意目前用的是rest而不是soap了,所以没有WSDL的描述了 - 浏览器地址栏里面按照Restful风格的路径进行访问+测试
HttpClient
是什么?
HttpClient 是Apache Jakarta Common 下的子项目,可以用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。它不是一个浏览器,它是一个客户端的HTTP通信实现库。HttpClient的目标是发送和接收HTTP报文。它最重要的功能是执行HTTP方法。一个HTTP方法的执行包含一个或多个HTTP请求/HTTP响应交换,通常由HttpClient的内部来处理。
怎么用
使用HttpClient需要以下6个步骤:
- 创建 HttpClient 的实例
- 创建某种连接方法的实例
- 调用第一步中创建好的实例的 execute 方法来执行第二步中创建好的连接类实例
- 读 response获取HttpEntity
- 对得到后的内容进行处理
- 释放连接。无论执行方法是否成功,都必须释放连接