前文提到了WebService是一种跨语言和操作系统的远程调用技术,WebService如此强大,市面上关于它的技术也是层出不穷,下面便是WebService的JAVA原生实现–JAX-WS:
JAX-WS(Java API for XML Web Services)规范是一组XML web services的JAVA
API,JAX-WS允许开发者可以选择RPC-oriented或者message-oriented 来实现自己的web services。
JDK6开始支持WebService,JAX-WS是Sun公司完全基于schema标准实现的WebService协议栈,是非常易于适用的轻量级框架。虽然JWS可以轻松实现JAVA平台与其他平台的互操作,但是其他语言无法使用JAX-WS发布WebService服务,这也是JAX-WS的缺憾之一。
JAX-WS的服务发布方式很简单,只需要使用@WebService注解便能够完成服务的发布:
首先,编写待发布服务的接口,通过@WebService注解来表明这是一个SEI(Service Endpoint Interface),这是强制性的,缺少该注解会引发RuntimeModelerException异常:
/**
* @program: webservice-server
* @description:
* @author: Lucifinil
* @create: 2019-12-19
**/
@WebService
public interface IMapWebService {
/**
* 根据地名获取国家名
* @param placeName 地名
* @return 国家名
*/
String getCountry(String placeName);
}
SEI的实现类使用@WebService注解来表明这是一个SIB(Service Implements Bean),网上许多资料提到实现类可以不使用@WebService注释,经过试验,我发现在JDK1.8中实现类不添加@WebService会抛出IllegalArgumentException异常:
事实上,该注解对于SEI和SIB都是强制性的,但其中的参数是非必需的。
/**
* @program: webservice-server
* @description:
* @author: Lucifinil
* @create: 2019-12-19
**/
@WebService(endpointInterface = "com.pers.IMapWebService", serviceName = "IMapWebService")
public class MapWebService implements IMapWebService {
private static final String CHENGDU = "成都";
private static final String SAN_FRANCISCO = "旧金山";
@Override
public String getCountry(String placeName) {
if (CHENGDU.equals(placeName)) {
return "中国";
} else if (SAN_FRANCISCO.equals(placeName)) {
return "美国";
} else {
return "该地名暂不支持查询";
}
}
}
以上代码模拟了一个查询国名的服务,只要传入数据库(假装有数据库)中存在的地名,便会返回相应国名:)
接下来,万事大吉,只差发布了,定义一个发布器:
/**
* @program: webservice-server
* @description:
* @author: Lucifinil
* @create: 2019-12-19
**/
public class WebServicePublisher {
public static void main(String[] args) {
System.out.println("启动发布服务...");
IMapWebService mapWebService = new MapWebService();
String mapWebServiceAddress = "http://localhost:9999/map";
Endpoint.publish(mapWebServiceAddress,mapWebService);
System.out.println("正在提供国名查询服务...");
}
}
Endpoint是JAX-WS中发布服务的关键类,提供的静态方法 publish(String address, Object implementor) 可以在给定的地址创建并发布指定的实现者对象的端点。
OK!运行:
说好的JAX-WS简单呢…怎么发布都这么多!!!
只是看着多啦,发布完成后,便给广大粉丝生成说明书吧。
打开浏览器,访问发布器定义的发布地址加上"?wsdl":
"http://localhost:9999/map?wsdl";
如果出现这一步,WebService服务就已经成功发布了》。》
在之前生成的WSDL,虽然我们也可以人为阅读,但出于效率与正确性,肯定不如机器。
JAVA提供了wsimport来为我们阅读WSDL并生成相应的调用客户端,所以JAX-WS是相当简单无脑的,不过,我喜欢,嘿嘿嘿(^)。
wsimport通过命令行使用:
比较常用的几个参数:
-keep:是否生成java源文件
-d:指定.class文件的输出目录
-s:指定.java文件的输出目录
-p:定义生成类的包名,不定义的话有默认包名
-verbose:在控制台显示输出信息
-b:指定jaxws/jaxb绑定文件或额外的schemas
-encoding : 指定编码格式
实例:
wsimport -encoding utf-8 -d D:\webservice -p com.pers -keep -verbose http://127.0.0.1:9999/map?wsdl
对上述命令做一个小小解析:
-encoding utf-8 表示wsimport使用utf8编码;
-d D:\webservice表示将编译文件输出到D:\webservice;
-p com.pers指定生成的程序代码的包为com.pers,可以不配置,默认包名为服务端的包名;
-keep表示在编译目录下同时生成java源文件,否则只有编译文件,等价于:
wsimport -encoding utf-8 -d D:\webservice -p com.pers -s D:\webservice -verbose http://127.0.0.1:9999/map?wsdl
-verbose表示在控制台显示过程信息。
大家可以根据实际情况配置参数:)
最终效果:
一般来说,我们只使用源文件就行了:
wsimport -encoding utf-8 -p com.pers -s D:\webservice -verbose http://127.0.0.1:9999/map?wsdl
接下来便是调用了,把整个包cv到客户端工程:
调用客户端的接口来获取数据:
/**
* @program: webservice-client
* @description:
* @author: Lucifinil
* @create: 2019-12-19
**/
public class Client {
public static void main(String[] args) {
IMapWebService iMapWebService = new IMapWebService();
IMapServer iMapServer = iMapWebService.getMapWebServicePort();
String country = iMapServer.getCountry("旧金山");
System.out.println(country);
}
}
解析:IMapWebService并非所谓的服务器类,IMapWebService类继承自javax.xml.ws.Service类,提供Web服务的客户端视图。
getMapWebServicePort()方法是对Service中getPort()的封装,其返回值实际是指定服务端点接口的对象代理实例。
通过iMapServer调用服务端提供的查询接口getCountry(),得到查询结果。
到这里,JAX-WS的发布服务于服务调用流程就结束了。
@webservice(javax.jws.WebService),作用于Class,用于描述一个JWS文件实现一个webservice时候的细节,提供以下参数:
属性 | 说明 |
---|---|
serviceName | XML: |
name | XML: |
portName | XML: |
endpointInterface | 服务接口全路径, 指定做SEI(Service EndPoint Interface)服务端点接口 。 |
targetNamespace | 指定你想要的名称空间,默认是使用接口实现类的包名的反缀 |
wsdlLocation | 指定用于定义 Web Service 的 WSDL 文档的 Web 地址。Web 地址可以是相对路径或绝对路径。 |
@WebMethod(javax.jws.WebMethod),作用于方法,表示作为一项 Web Service 操作的方法,提供以下参数:
属性 | 说明 |
---|---|
operationName | XML: |
action | 对于SOAP绑定,确定XML:SOAP:action中header的值,定义此操作的行为,缺省值为该方法名称。 |
exclude | 是否拒绝该方法的发布,缺省值为 false。 |
@Oneway注解,javax.jws.Oneway,作用于方法,注释将一个方法表示为只有输入消息而没有输出消息的 Web Service 单向操作。
该注解须和@WebMethod配合使用,且必须用于void修饰的方法。
@WebParam(javax.jws.WebParam),该注解作用于方法入参,表示单个参数至 Web Service 消息部件和 XML 元素的映射或者参数行为。
属性 | 说明 |
---|---|
name | 对于RPC风格的操作,如果未指定partName,该属性与 |
partName | XML: |
targetNamespace | 参数的XML命名空间。这个值只在document风格的webservice使用,从而参数映射为XML元素。默认值是这个webservice的targetNamespace。 |
mode | 参数的流向(IN、OUT 或 INOUT 之一,对应enum为WebParam.Mode.IN,WebParam.Mode.OUT,WebParam.Mode.INOUT。)缺省值为WebParam.Mode.IN。 |
header | 指定参数是在SOAP header还是SOAP body中,缺省值为 false。 |
@WebResult(javax.jws.WebResult),该注解作用于SEI和SIB上,指定返回值到 WSDL 部分和 XML 元素的映射关系。
属性 | 说明 |
---|---|
name | 指定该返回值的名称。对于 RPC 绑定,该属性与 |
partName | XML: |
targetNamespace | 指定返回值的 XML 名称空间。只在document风格的操作且参数样式为 BARE 时可用 |
header | 指定参数是在SOAP header还是SOAP body中,缺省值为 false。 |
@SOAPBinding(javax.jws.SOAPBinding),该注解作用于SEI和SIB上,指定 Web Service 与 SOAP 消息协议之间的映射。
属性 | 说明 |
---|---|
use | 定义用于发送至 Web Service 和来自 Web Service 的消息的格式,缺省值为 LITERAL。ENCODED 在 Feature Pack for Web Services 中不受支持。 |
style | 定义发送至 Web Service 和来自 Web Service 的消息的编码样式,有效值为DOCUMENT 和 RPC。缺省值为DOCUMENT。 |
parameterStyle | 确定方法的参数是否表示整个消息体,或者参数是否是封装在执行操作之后命名的顶级元素中的元素。有效值为 WRAPPED 或 BARE。对于DOCUMENT 类型的绑定只能使用BARE 值。缺省值为 WRAPPED。 |
@HandlerChain :已过时
总的来说,JAX-WS还是蛮简单的,不用导入任何包,使用注解便能完成服务的发布,JAX-WS并非一蹴而就的,最开始的版本是JAX-RPC,在它的发展历程中,也经历了许多的迭代,有兴趣可以了解一下。
转载请注明出处,来自路西菲尔的博客https://blog.csdn.net/csdn_1364491554/article/details/103613414!