WebService简介
Web Service也叫XML Web Service, WebService是一种可以接收从Internet或者Intranet上的其它系统中传递过来的请求,轻量级的独立的通讯技术。是通过SOAP在Web上提供的软件服务,使用WSDL文件进行说明,并通过UDDI进行注册。WebService是一种跨编程语言和跨操作系统平台的远程调用技术。
还可以从多个角度来理解WebService,从表面看,WebService就是一个应用程序向外界暴露出一个能通过Web进行调用的API,也就是说能用编程的方法通过Web来调用这个应用程序。我们把调用这个WebService的应用程序叫做客户端,而把提供这个WebService的应用程序叫做服务端。从深层次看,WebService是建立可互操作的分布式应用程序的新平台,是一个平台,是一套标准。它定义了应用程序如何在Web上实现互操作性,你可以用任何你喜欢的语言,在任何你喜欢的平台上写Web service ,只要我们可以通过Web service标准对这些服务进行查询和访问。
WebService三要素
SOAP、WSDL、UDDI(UniversalDescriptionDiscovery andIntegration)三者构成了WebService的三要素。下面详细阐述这三大技术:
SOAP
WebService通过HTTP协议发送请求和接收结果时,发送的请求内容和结果内容都采用XML格式封装,并增加了一些特定的HTTP消息头,以说明HTTP消息的内容格式,这些特定的HTTP消息头和XML内容格式就是SOAP协议。SOAP提供了标准的RPC(远程调用技术)方法来调用Web Service。
SOAP协议组成:
SOAP协议 = HTTP协议 + XML数据格式
SOAP协议定义了SOAP消息的格式,SOAP协议是基于HTTP协议的,SOAP也是基于XML的,XML是SOAP的数据编码方式。
WSDL
好比我们去商店买东西,首先要知道商店里有什么东西可买,然后再来购买,商家的做法就是张贴广告海报。 WebService也一样,WebService客户端要调用一个WebService服务,首先要有知道这个服务的地址在哪,以及这个服务里有什么方法可以调用,所以,WebService务器端首先要通过一个WSDL文件来说明自己家里有啥服务可以对外调用,服务是什么(服务中有哪些方法,方法接受的参数是什么,返回值是什么),服务的网络地址用哪个url地址表示,服务通过什么方式来调用。
WSDL(Web Services Description Language)就是这样一个基于XML的语言,用于描述Web Service及其函数、参数和返回值。它是WebService客户端和服务器端都能理解的标准格式。因为是基于XML的,所以WSDL既是机器可阅读的,又是人可阅读的,这将是一个很大的好处。一些最新的开发工具既能根据你的Web service生成WSDL文档,又能导入WSDL文档,生成调用相应WebService的代理类代码。
UDDI
uddi是一个跨产业,跨平台的开放性架构,可以帮助 Web 服务提供商在互联网上发布 Web 服务的信息。UDDI 是一种目录服务,企业可以通过 UDDI 来注册和搜索 Web 服务。简单来说,UDDI 就是一个目录,只不过在这个目录中存放的是一些关于 Web 服务的信息而已。
为什么要使用WebService
- 跨平台调用
- 跨语言调用
- 远程调用
发布WebService。
3.1服务端
3.1.1定义接口
/**
* 定义一个有关天气的服务
* @author admin
*
*/
public interface IWeatherService {
public String queryWeather(String cityName);
}
3.1.2定义实现类
@WebService // 用该注解修改表示当前类是一个服务类,只发布public修饰的方式
public class WeatherServiceImpl implements IWeatherService {
@Override
public String queryWeather(String cityName) {
System.out.println("WeatherServiceImpl.queryWeather() " + cityName);
return "晴天";
}
}
@WebMethod(exclude=true)方法上面添该注解表示不发布这个方法
3.1.3发布服务
public class WeatherService {
public static void main(String[] args) {
/**
* 参数1:服务地址
* 参数2:服务类
*/
Endpoint.publish("http://localhost:8080/weatherService", new WeatherServiceImpl());
System.out.println("服务发布成功");
}
}
3.1.4 wsdl结构
<service>
服务视图名称,WebService的服务端点
<binding>
Web Services的通信协议,还描述Web Services的方法、输入、输出。
<portType>
描述了WebService可执行的操作,通过binding指向portType
<message>
描述了服务中发布的方法,包括参数,返回值等。
<types>
定义了WebService中使用的数据类型
3.2客户端
3.2.1生成客户端代码
通过wsimport命令生成客户端代码(通过cmd进入到当前项目的src路径下,wsimport.exe命令是在jdk的bin目录下)
第一种方式【远程地址】 wsimport -s . http://127.0.0.1:8088/weather?wsdl
第二种方式【xml文件】 wsimport -s . 文件路径(文件路径后面不需要加?wsdl)
3.2.2 客户端调用第一种方式
// 1.创建服务视图(视图是从service标签的name属性获取)
WeatherServiceImplService weatherServiceImplService = new WeatherServiceImplService();
// 2.获取服务实现类(实现类从portType的name属性获取)
WeatherServiceImpl serviceImpl = weatherServiceImplService.getPort(WeatherServiceImpl.class);
// 3.调用方法(从portType的operation标签获取 )
String result = serviceImpl.queryWeather("深圳");
// 4.输出服务端返回的结果
System.out.println(result);
3.2.3 客户端调用第二种方式(常用)
// 1.设置服务端地址
URL url = new URL("http://localhost:8080/weatherService?wsdl");
// 2.设置服务名称和命名空间
// 参数1:wsdl的命名空间(targetNamespace)
// 参数2:是服务视图的名称(service的name值)
QName qName = new QName("http://impl.service.qf.com/", "WeatherServiceImplService");
// 3.创建服务视图
Service service = Service.create(url, qName);
// 3.得到服务视图的实现类
WeatherServiceImpl weatherServiceImpl = service.getPort(WeatherServiceImpl.class);
// 4.调用方法
String result = weatherServiceImpl.queryWeather("青海");
// 5.输出服务端返回结果
System.out.println(result);
3.2.4 客户端调用第三种方式
// 1.创建服务地址,不是WSDL地址
URL url = new URL("http://localhost:8080/weatherService");
// 2.打开一个通向服务地址的连接
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// 3.设置参数,
connection.setRequestMethod("POST"); // POST必须大写,否则抛出异常
// 这里是text/xml不是text/html
connection.setRequestProperty("content-Type", "text/xml;charset=utf-8");
// 4.设置输入输出,默认是false没有读写的权限
connection.setDoOutput(true);
connection.setDoInput(true);
// 5.组织SOAP数据,发送请求
String soapXml = getXml("青海");
connection.getOutputStream().write(soapXml.getBytes());
if (connection.getResponseCode() == 200) {
InputStream ips = connection.getInputStream();
Scanner scanner = new Scanner(ips);
StringBuffer buffer = new StringBuffer();
while(scanner.hasNextLine()){
buffer.append(scanner.nextLine());
}
scanner.close();
String result = parseXmlToString(buffer);
System.out.println("result:"+result);
}
private String parseXmlToString(StringBuffer buffer) {
try {
Document document = DocumentHelper.parseText(buffer.toString());
// "//"从任意位置的节点上选择名称为 item 的节点。
Node node = document.selectSingleNode("//return");
return node.getText();
} catch (DocumentException e) {
e.printStackTrace();
}
return null;
}
private String getXml(String string) {
String xml = "<?xml version=\"1.0\" ?>" + "<S:Envelope xmlns:S=\"http://schemas.xmlsoap.org/soap/envelope/\">"
+ "<S:Body>" + "<ns2:queryWeather xmlns:ns2=\"http://impl.service.qf.com/\">" + "<arg0>" + string
+ "</arg0>" + "</ns2:queryWeather>" + "</S:Body>" + "</S:Envelope>\"";
return xml;
}
SelectNodes的用法
SelectNodes("item")
从当前节点的儿子节点中选择名称为 item 的节点。
SelectNodes("/item")
从根节点的儿子节点中选择名称为 item 的节点。
SelectNodes("//item")
从任意位置的节点上选择名称为 item 的节点。要重点突出这个任意位置,它不受当前节点的影响,也就是说假如当前节点是在第 100 层(有点夸张),也可以选择第一层的名称为 item 的节点。
SelectNodes(".")
选择当前节点。
SelectNodes("..")
选择当前节点的父节点。
SelectNodes("//item[@name]")
在 SelectNodes("//item") 的基础上,增加了一个限制,就是要求拥有 name 属性。
SelectNodes("//item[@name='111']")
在 SelectNodes("//item[@name]") 的基础上,增加了一个限制,就是要求 name 属性值为 111。注意语法中有引号;如果没有引号,则表示是数字类型,对于数字类型可以使用大于号、小于号等,比如:SelectNodes("//item[@v>333]")。
SelectNodes("//item[1]")
选择第一个 item,注意是第一个,不是第二个。
还有这里是指亲兄弟间的第一个 item,也就是说:父级若有三个 item,则选择第一个;若父级第二个 item 的有两个名称同样为 item 的儿子,则第一个儿子会被选择出来;若父级第三个 item 的也有两个名称同样为 item 的儿子,则第一个儿子也会被选择出来……
SelectNodes("//item[last()-1]")
倒数第二个节点,同样是指亲兄弟间的倒数第二个。
SelectNodes("//item[position()<=2]")
位置为第一和第二的节点(第一个节点的 position() 为 1),同样是指亲兄弟间的位置。
SelectNodes("//@name")
SelectNodes("/root/item/@name") 取 item 的 name 属性
选择 name 属性,注意这下选择的是属性,而不是节点了。用 Value 属性获取属性集合的属性值。
SelectNodes("/root/item")
根节点 root 下的 item 儿子节点。
SelectNodes("/root//item")
根节点 root 下的不管是儿子、孙子、重孙子……,只要是名称为 item 的统统选取出来。
案例
地址:http://www.webxml.com.cn/zh_cn/web_services.aspx
5.1天气预报
5.2手机归属地
6.Eclipse提供的WebService客户端
7.监听工具TCP/IP Monitor
Eclipse中提供了一个很好的端口监听的工具TCP/IP Monitor,通过这个工具,我们可以监听目标端口输入输出的数据。
事实上,这个TCP/IP Monitor相当于一个“ 拦截器”,所有我们向目标服务器发送的数据包和服务器返回的数据包都要经过这个拦截器(也叫作代理服务器),进而拦截到数据包。
7.1配置TCP/IP Monitor
我们点击eclipse菜单栏的windows->Preferences->Run/Debug->TCP/IP Mointor,然后,我们点击Add按钮,添加一个监听端口。
如上图所示,添加一个8000端口用以监听8080。确定后,我们要单击start启动TCP/IP Mointor。
引用:https://zhuanlan.zhihu.com/p/126507013
标签:Web,调用,WebService,简介,SelectNodes,item,节点 From: https://www.cnblogs.com/JiahaoZeng/p/16964890.html