webservice记录
最近有在项目中使用到webservice记录,记录一下心得。
先来看一下百度的介绍:
Web Service是一个平台独立的,低耦合的,自包含的、基于可编程的web的应用程序,可使用开放的XML(标准通用标记语言下的一个子集)标准来描述、发布、发现、协调和配置这些应用程序,用于开发分布式的交互操作的应用程序。 [1]
Web Service技术, 能使得运行在不同机器上的不同应用无须借助附加的、专门的第三方软件或硬件, 就可相互交换数据或集成。依据Web Service规范实施的应用之间, 无论它们所使用的语言、 平台或内部协议是什么, 都可以相互交换数据。Web Service是自描述、 自包含的可用网络模块, 可以执行具体的业务功能。Web Service也很容易部署, 因为它们基于一些常规的产业标准以及已有的一些技术,诸如标准通用标记语言下的子集XML、HTTP。Web Service减少了应用接口的花费。Web Service为整个企业甚至多个组织之间的业务流程的集成提供了一个通用机制。
跨平台,跨语言的服务调用,适用于不同系统之间的数据交互和传递。简单的说就是,如果我们需要在系统中添加天气预报,转账这种功能的时候并不需要做这种服务,只需要调用气象局接口或者是银联的接口就可以了。
Java中有三种webservice规范,较为常用的是JAX-ws(soap),JAX-RS(rest)
SOAP协议
WebService通过HTTP协议发送请求和接收结果时,发送的请求内容和结果内容都采用XML格式封装,并增加了一些特定的HTTP消息头,以说明HTTP消息的内容格式,这些特定的HTTP消息头和XML内容格式就是SOAP协议规定的。
soap就是简单对象访问协议,它是用于交互xml编码信息的轻量级协议。soap是基于http的soap的组成部分如下:
1.Envelope,必须部分,以xml的根元素出现
2.Header,可选
3.Body必须的
wsdl
WebService服务器端首先要通过一个WSDL文件来说明自己有什么服务可以对外调用。简单的说,WSDL就像是一个说明书,用于描述WebService及其方法、参数和返回值。 WSDL文件保存在Web服务器上,通过一个url地址就可以访问到它。客户端要调用一个WebService服务之前,要知道该服务的WSDL文件的地址。WebService服务提供商可以通过两种方式来暴露它的WSDL文件地址:1.注册到UDDI服务器,以便被人查找;2.直接告诉给客户端调用者。
Service:相关端口的集合,包括其关联的接口、操作、消息等。
Binding:特定端口类型的具体协议和数据格式规范
portType: 服务端点,描述 web service可被执行的操作方法,以及相关的消息,通过binding指向portType
message: 定义一个操作(方法)的数据参数
types: 定义 web service 使用的全部数据类型
WSDL文档应该从下往上阅读。
1.先看service标签,看相应port的binding属性,然后通过值查找上面的binding标签。
2.通过binding标签可以获得具体协议等信息,然后查看binding的type属性
3.通过binding的type属性,查找对应的portType,可以获得可操作的方法和参数、返回值等。
4.通过portType下的operation标签的message属性,可以向上查找message获取具体的数据参数信息。
<wsdl:definitions
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="http://impl.tonyffd.com/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:ns2="http://schemas.xmlsoap.org/soap/http"
xmlns:ns1="http://tonyffd.com/" name="HelloServiceImplService" targetNamespace="http://impl.tonyffd.com/">
<wsdl:import location="http://localhost:8000/ws/hello?wsdl=HelloService.wsdl" namespace="http://tonyffd.com/"></wsdl:import>
<wsdl:binding name="HelloServiceImplServiceSoapBinding" type="ns1:HelloService">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="sayHello">
<soap:operation soapAction="" style="document"/>
<wsdl:input name="sayHello">
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="sayHelloResponse">
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="HelloServiceImplService">
<wsdl:port binding="tns:HelloServiceImplServiceSoapBinding" name="HelloServiceImplPort">
<soap:address location="http://localhost:8000/ws/hello"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
xml
WebService采用Http协议来在客户端和服务端之间传输数据。WebService使用XML来封装数据,XML主要的优点在于它是跨平台的。
ApacheCXF实现WebService
提供服务
使用maven构建一个项目,在pom,xml文件中导入下面包:
<dependencies>
<!-- 进行jawxs服务开发-->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>3.0.1</version>
</dependency>
<!-- 内置jetty web服务器-->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http-jetty</artifactId>
<version>3.0.1</version>
</dependency>
<!--日志实现-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.12</version>
</dependency>
</dependencies>
编写一个服务的接口:HelloService,使用WebService注解
@WebService //描述这是一个webservice的接口,对外服务的接口
public interface HelloService {
String sayHello(String name);
}
编写实现类:HelloServiceImpl
public class HelloServiceImpl implements HelloService {
@Override
public String sayHello(String name) {
return "hello "+name+"!!";
}
}
编写启动类进行测试:
public class ServerApp {
public static void main(String[] args) {
//启动web服务
//发布服务的工厂
JaxWsServerFactoryBean factoryBean = new JaxWsServerFactoryBean();
factoryBean.setAddress("http://localhost:8000/ws/hello"); //绑定服务地址
factoryBean.setServiceBean(new HelloServiceImpl()); //绑定服务类
factoryBean.create(); //发布服务
System.out.println("服务已经开启---");
}
}
访问http://localhost:8000/ws/hello?wsdl测试,查看wsdl说明书查看服务连通性
调用服务
创建maven项目文件,跟之前使用的依赖项目文件一样。然后把之前项目中编写的WebService接口服务类拷贝过来,待会可以使用接口代理对象的方式进行调用,很nice。编写调用服务类进行测试
public class ClientApp {
public static void main(String[] args) {
//代理工厂对象
JaxWsProxyFactoryBean factoryBean = new JaxWsProxyFactoryBean();
//设置服务调用地址
factoryBean.setAddress("http://localhost:8000/ws/hello");
//设置调用服务的远程接口类
factoryBean.setServiceClass(HelloService.class);
HelloService helloService = factoryBean.create(HelloService.class);
System.out.println(helloService);
//使用对象调用的方式进行调用即可
System.out.println(helloService.sayHello("ffd"));
}
}
使用注解更清晰的描述wsdl文档
WebService的注解都位于javax.jws包下:
@WebService-定义服务,在类上边
targetNamespace:指定命名空间
name:portType的名称
portName:port的名称
serviceName:服务名称
endpointInterface:SEI接口地址,如果一个服务类实现了多个接口,只需要发布一个接口的方法,可通过此注解指定要发布服务的接口。
@WebMethod-定义方法,在公开方法上边
operationName:方法名
exclude:设置为true表示此方法不是webservice方法,反之则表示webservice方法,默认是false
@WebResult-定义返回值,在方法返回值前边
name:返回结果值的名称
@WebParam-定义参数,在方法参数前边
name:指定参数的名称
需要注意的是如果使用postman等测试工具测试的时候请求方式应该为post,然后需要在header中设置Content-type=“text/xml;Charset=UTF-8”