认识 WebService
什么是服务?
1)现在的应用程序变得越来越复杂,甚至只靠单一的应用程序无法完成全部的工作。更别说只使用一种语言了。
2)大家在写应用程序查询数据库时,并没有考虑过为什么可以将查询结果返回给上层的应用程序,甚至认为,这就是数据库应该做的,其实不然,这是数据库通过 TCP/IP 协议与另一个应用程序进行交流的结果,而上层是什么样的应用程序,是用什么语言,数据库本身并不知道,它只知道接收到了一份协议,这就是SQL92查询标准协议。
3)既然数据库可以依据某些标准对外部其他应用程序提供服务、而且不关心对方使用什么语言,那我们为什么就不能实现跨平台、跨语言的服务呢?只要我们用Java写的代码,可以被任意的语言所调用,我们就实现了跨平台,跨语言的服务!
复杂的网络应用:
WebService 定义:顾名思义就是基于Web的服务。它使用Web(HTTP)方式,接收和响应外部系统的某种请求,从而实现远程调用。
Webservice 理解:我们可以调用互联网上查询天气信息Web服务,然后将它嵌入到我们的程序(C/S或B/S程序)当中来,当用户从我们的网点看到天气信息时,他会认为我们为他提供了很多的信息服务,但其实我们什么也没有做,只是简单了调用了一下服务器上的一段代码而已。WebService 可以将你的服务(一段代码)发布到互联网上让别人去调用,也可以调用别人机器上发布的 WebService,就像使用自己的代码一样。
既然 WebService 是一种远程调用技术,那么最直接的问题就是:1、我怎么去调用别人的程序。2、我的程序怎么才能被别人调用
作为一种通用技术,那么是否有通用的使用说明书呢?答案是肯定的:WSDL 就是 WebService 的说明书(网上有更详细的教程,这里不特别介绍)
WSDL:WebService Description Language——Web服务描述语言。 通过XML形式说明服务在什么地方——地址。通过XML形式说明服务提供什么样的方法——如何调用。
分享一个 Webservice 服务网站:http://www.webxml.com.cn
WSDL文档从下往上读,它包含几个值得注意的关键节点
Types:数据类型定义的容器,它使用某种类型系统(一般地使用XML Schema中的类型系统)。(入参和出参的数据类型)
Message:通信消息的数据结构的抽象类型化定义。使用Types所定义的类型来定义整个消息的数据结构(入参和出参)。
Operation:对服务中所支持的操作的抽象描述,一般单个Operation描述了一个访问入口的请求/响应消息对(方法)。
PortType:对于某个访问入口点类型所支持的操作的抽象集合,这些操作可以由一个或多个服务访问点来支持(服务类)。
Binding:特定服务访问点与具体服务类的绑定(不看内容,看关系)。
Port:定义为webservice单个服务访问点。
Service:相关服务访问点的集合。
下面演示 jdk 怎样通过 WSDL 生成客户端代码,通过客户端代码完成调用。
1. wsimport 是 jdk 自带的,可以根据 wsdl 文档生成客户端调用代码的工具。
2. 无论服务器端的 WebService 是用什么语言写的,都将在客户端生成Java代码。服务器端用什么写的并不重要。
3. wsimport.exe位于 JAVA_HOME\bin 目录下。
常用参数为:
1)-d<目录> - 将生成.class文件。默认参数。
2)-s<目录> - 将生成.java文件和class文件。
3)-p<生成的新包名> -将生成的类,放于指定的包下。
(wsdlurl) - http://server:port/service?wsdl,必须的参数。
注意:-s不能分开,-s后面有个小点,用于指定源代码生成的目录。点即当前目录。如果使用了-s参数则会在目录下生成两份代码,一份为.class代码。一份为.java代码。.class代码,可以经过打包以后使用。.java代码可以直接Copy到我们的项目中运行。
我们在F盘下新建一个文件夹,将生成的代码保存在此文件夹中。现在文件夹里是空的
打开命令行,输入java命令。参照上面的命令解释,下面命令的意思是:生成 java 文件和 class 文件,创建子文件夹来放这些文件
最后生成的结果如下
上面是通过直接访问WSDL的URL这种方式来生成的,我们也可以把 WSDL下载下来,比如,放在f:/wsCode/EnglishChinese.wsdl
用下面的命令
生成效果是一样的
注意:如果用第一种方式生成报错,那么就把WSDL下载下来,删除报错提示的那几行,然后用第二种方式重新生成。
原因:wsimport 只适用于 SOAP1.1 协议,如果 WebService 是用 SOAP1.2 协议发布的,则使用 wsimport 导出代码会报错,生成的文件也不全。
生成的class文件是不需要的,只需要 java 文件,接下来就是使用这些java文件。
第一步:将jdk生成的java文件复制到项目中
写测试方法进行调用测试。这其实就是调用普通的Java方法,但是需要读懂 WSDL 明白创建哪些对象,调用哪些方法,这是关键!
调用WebService步骤
1)打开WSDL文档
2)从下往上读WSDL文档,先找到Services(服务访问点集合),根据Services里面binding属性找到binding元素,再根据binding元素的type属性找到绑定的portType(服务类)
3)根据WSDL的地址生成客户端代码 wsimport -s . -p com.jwen.trans d:/wsCode/EnglishChinese.wsdl
4)把客户端代码拷贝到项目中
5)创建服务访问点集合对象
6)根据服务访问点获得服务类
7)调用服务类的方法
下面演示 jdk 发布 WebService 服务
注意:用 jdk1.6.0_21 以后的版本发布一个 WebService 服务。在JDK1.6中JAX-WS规范定义了如何发布一个WebService服务。 JAX-WS是指Java Api for XML – WebService。
与Web服务相关的类,都位于javax.xml.ws.*包中。主要类有:
a)@WebService:它是一个注解,用在类上指定将此类发布成一个webservice服务.
b)Endpoint:此类为端点服务类,它的方法publish用于将一个已经添加了@WebService 注解对象绑定到一个地址的端口上。Endpoint 是 jdk 提供的一个专门用于发布服务的类,它的publish方法接收两个参数,一个是本地的服务地址,二是提供服务的类。它位于 javax.xml.ws.* 包中。
public static Endpoint.publish(String address, Object implementor) 在给定地址处针对指定的实现者对象创建并发布端点。stop方法用于停止服务。
其他注意事项:
1)给类添加上@WebService注解后,类中所有的非静态方法都将会对外公布。不支持静态方法,final方法。
2) 如果希望某个方法(非static,非final)不对外公开,可以在方法上添加@WebMethod(exclude=true),阻止对外公开。
3) 如果一个类上,被添加了@WebService注解,则必须此类至少有一个可以公开的方法,否则将会启动失败。
4) 服务类中不能没有方法
5) @WebMethod(exclude=true)屏蔽方法
项目结构如下图所示
HelloServer.java 的代码如下:
@WebService
public class HelloServer {
/**
* 1.需要方法权限是public
* 2.不能是final类型
* 3.方法不能是静态的
* 4.服务类至少有一个方法
* @param name
* @return
*/
public String sayHello(String name){
return name + " hello!";
} @WebMethod(exclude=true)
public String sayBye(String name){
return name + " bye!";
} }
ServerPublish.java 的代码如下:
public class ServerPublish { public static void main(String[] args) {
//jdk发布webservice服务, 第一个参数服务地址,第二个参数具体服务类
Endpoint.publish("http://127.0.0.1:8080/hello", new HelloServer());
} }
运行 main 方法后,在浏览器地址栏中输入 http://127.0.0.1:8080/hello?wsdl 查看 WSDL,可见,WebService成功发布。可以用前面介绍的方式进行调用。
调用WebService的方式是不是只有调用客户端代码这一种呢?显然不是,还是有其他方式的。
下面演示 ajax 调用WebService,注意运行前设置IE可信任站点和自定义级别
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script type="text/javascript">
var xhr; function invoke(){
//创建ajax对象
xhr = new ActiveXObject("Microsoft.XMLHTTP");
//指定要访问的地址,就是我们WSDL地址,说明书
var url = "http://127.0.0.1:8080/hello?wsdl";
//打开连接,参数1.请求方式, 2,url地址. 3.是否同步,true异步,false同步
xhr.open("POST", url, true);
//指定发送的数据类型
xhr.setRequestHeader("Content-Type", "text/xml;charset=UTF-8");
//设置回调函数
xhr.onreadystatechange = _back;
var mytext = document.getElementById("mytext").value;
//定义消息体
var data ='<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:q0="hello.ren.liang" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">'
+'<soapenv:Body>'
+'<q0:sayHello>'
+' <arg0>'+mytext+'</arg0>'
+'</q0:sayHello>'
+'</soapenv:Body>'
+'</soapenv:Envelope>'; //发送消息体
xhr.send(data);
}
//回调函数
function _back(){
//判断成功状态
if(xhr.readyState == 4 && xhr.status == 200){
//以文本形式
var result = xhr.responseText;
//以xml文档对象
var obj = xhr.responseXML;
//解析文档
var returns = obj.getElementsByTagName("return");
alert(returns[0].text);
}
}
</script>
</head>
<body>
<input type="text" id="mytext">
<input type="button" value="click" onclick="invoke();">
</body>
</html>
Java 也可以通过 WSDL 直接调用 WebService
package com.rl.client; import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.StringReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.List; import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader; public class TestHttpURLConnClient { public static void main(String[] args) throws Exception {
//定义webservice的URL
URL url = new URL("http://127.0.0.1:8080/hello?wsdl");
//打开连接获得URLConnection
URLConnection uc = url.openConnection();
//强转成HttpURLConnection
HttpURLConnection httpuc = (HttpURLConnection)uc;
//打开输入输出的开关
httpuc.setDoInput(true);
httpuc.setDoOutput(true);
//设置请求方式
httpuc.setRequestMethod("POST");
//设置content-type text/xml;charset=UTF-8
httpuc.setRequestProperty("Content-Type", "text/xml;charset=UTF-8");
//组装消息体
String data = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:q0=\"http://server.rl.com/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">"
+"<soapenv:Body>"
+" <q0:sayBye>"
+" <arg0>wangwu</arg0>"
+" </q0:sayBye>"
+" </soapenv:Body>"
+"</soapenv:Envelope>";
//根据HttpURLConnection获得输出流
OutputStream out = httpuc.getOutputStream();
//用输出流把消息发送到服务端
out.write(data.getBytes());
//如果请求成功
if(httpuc.getResponseCode() == 200){
//获得输入流
InputStream in = httpuc.getInputStream();
//使用输入缓冲区
BufferedReader br = new BufferedReader(new InputStreamReader(in));
//读取响应的消息
StringBuffer sb = new StringBuffer();
String line = null;
while((line = br.readLine()) != null){
sb.append(line);
}
//解析消息,定义SAXReader对象
SAXReader reader = new SAXReader();
//获得文档对象
Document doc = reader.read(new StringReader(sb.toString()));
//使用XPath的方式获得到return这个元素的集合
List<Element> eList = doc.selectNodes("//return");
//遍历元素集合
for(Element ele : eList){
System.out.println(ele.getText());
}
} } }
上面的两种方式共同点都是需要知道消息体的组织方式,与客户端调用相比较,上面的两种方式不需要导出代码,但需要组织消息体,而客户端调用对参数的处理则方便的多,因为对象都是现成的。
关于怎样查看消息体,参考https://www.cnblogs.com/jwen1994/p/10589150.html
自动生成的 WSDL 文档的名字有时不规范,可以手动进行修改。
修改前的普通代码
@WebService
public class HelloServer { @WebMethod(exclude=false)
public String sayHello(String name){
return name + " hello!";
} @WebMethod(exclude=false)
public String sayBye(String name){
return name + " bye!";
}
}
修改后的代码
@WebService(
serviceName="MyHelloServerService",
portName="MyHelloServer",
name="MyHelloServer",
targetNamespace="hello.jwen.com"
)
public class HelloServer {
/**
* 1.需要方法权限是public
* 2.不能是final类型
* 3.方法不能是静态的
* 4.服务类至少有一个方法
* @param name
* @return
*/
@WebMethod(exclude=false)
public String sayHello(String name){
return name + " hello!";
} @WebMethod(exclude=false)
public @WebResult(name="byeResult") String sayBye(@WebParam(name="personName") String name){
return name + " bye!";
}
}
参数说明:
@WebService(
portName="myHelloService",修改端口名字
serviceName="HelloServices",修改服务访问点集合名字
name="HelloService",修改服务类的名字
targetNamespace="hello.rl.com" 修改命名空间名字
)
@WebResult(name="sirHello")修改返回值的元素的父标签名字
@WebParam(name="sir")修改传入参数的元素的父标签名字
本文还没有解决的两个问题:
1、难道只能用 jdk 自带方法 EndPoint.publish 这种方式发布 WebService 吗?
2、使用 SOAP1.2 协议发布的 WebService 该用什么方式导出客户端代码呢?
请看这篇文章:https://www.cnblogs.com/jwen1994/p/10630417.html
认识 WebService的更多相关文章
- webService
什么是webService WebService,顾名思义就是基于Web的服务.它使用Web(HTTP)方式,接收和响应外部系统的某种请求.从而实现远程调用. 1:从WebService的工作模式上 ...
- 开始webservice了
一.WebService到底是什么 一言以蔽之:WebService是一种跨编程语言和跨操作系统平台的远程调用技术. 所谓跨编程语言和跨操作平台,就是说服务端程序采用java编写,客户端程序则可以采用 ...
- Spring WebService入门
Web service是一个平台独立的,低耦合的,自包含的.基于可编程的web的应用程序,可使用开放的XML(标准通用标记语言下的一个子集)标准来描述.发布.发现.协调和配置这些应用程序,用于开发分布 ...
- 浅谈跨域以及WebService对跨域的支持
跨域问题来源于JavaScript的同源策略,即只有 协议+主机名+端口号 (如存在)相同,则允许相互访问.也就是说JavaScript只能访问和操作自己域下的资源,不能访问和操作其他域下的资源. 在 ...
- 浅谈WebService的版本兼容性设计
在现在大型的项目或者软件开发中,一般都会有很多种终端, PC端比如Winform.WebForm,移动端,比如各种Native客户端(iOS, Android, WP),Html5等,我们要满足以上所 ...
- Atitit webservice发现机制 WS-Discovery标准的规范attilax总结
Atitit webservice发现机制 WS-Discovery标准的规范attilax总结 1.1. WS-Discovery标准1 1.2. 一.WS-Discovery1 1.2.1. ...
- java调用CXF WebService接口的两种方式
通过http://localhost:7002/card/services/HelloWorld?wsdl访问到xml如下,说明接口写对了. 2.静态调用 // 创建WebService客户端代理工厂 ...
- VS2010编写WebService与在IIS的发布<之简单讲解>
工具VS2010,window环境win7 一:Webservice的创建与方法查看调用 1.新建空web应用程序项目 2.新建web服务 3.自动生成 4.直接跑起来,可以看到有2个方法 5.点击H ...
- webService学习之路(三):springMVC集成CXF后调用已知的wsdl接口
webService学习之路一:讲解了通过传统方式怎么发布及调用webservice webService学习之路二:讲解了SpringMVC和CXF的集成及快速发布webservice 本篇文章将讲 ...
- webService学习之路(二):springMVC集成CXF快速发布webService
继上一篇webService入门之后,http://www.cnblogs.com/xiaochangwei/p/4969448.html ,现在我将我周六在家研究的结果公布出来 本次集成是基于之前已 ...
随机推荐
- Chrome - JavaScript调试技巧总结(浏览器调试JS)
Chrome 是 Google 出品的一款非常优秀的浏览器,其内置了开发者工具(Windows 系统中按下 F12 即可开启),可以让我们方便地对 JavaScript 代码进行调试. 为方便大家学习 ...
- JAVA WEB快速入门之从编写一个基于SpringMVC框架的网站了解Maven、SpringMVC、SpringJDBC
接上篇<JAVA WEB快速入门之通过一个简单的Spring项目了解Spring的核心(AOP.IOC)>,了解了Spring的核心(AOP.IOC)后,我们再来学习与实践Maven.Sp ...
- Raptor井字棋游戏
作为大学第一个小作品,记录一下,也给那些想接触到Raptor游戏的人一个小小的参考QAQ至于Raptor的语法和使用,可以参考一下他的帮助手册,看不懂英文的话可以复制放到翻译上看. 以上是主函数 以下 ...
- MySQL InnoDB 存储引擎探秘
在MySQL中InnoDB属于存储引擎层,并以插件的形式集成在数据库中.从MySQL5.5.8开始,InnoDB成为其默认的存储引擎.InnoDB存储引擎支持事务.其设计目标主要是面向OLTP的应用, ...
- arcgis api 3.x for js 入门开发系列二十一气泡窗口信息动态配置模板
前言 关于本篇功能实现用到的 api 涉及类看不懂的,请参照 esri 官网的 arcgis api 3.x for js:esri 官网 api,里面详细的介绍 arcgis api 3.x 各个类 ...
- C#零基础入门-3-第一个控制台程序
打开VS2017 文件 新建 项目 模板选择Visual C# Windows 控制台应用程序 快速写入Console.WriteLine 输入cw,然后快速按tab键两次即可.
- django mongodb配置
#settings.py import os from mongoengine import * BASE_DIR = os.path.dirname(os.path.dirname(os.path. ...
- WebApi 身份认证解决方案:Basic基础认证
前言:最近,讨论到数据库安全的问题,于是就引出了WebApi服务没有加任何验证的问题.也就是说,任何人只要知道了接口的url,都能够模拟http请求去访问我们的服务接口,从而去增删改查数据库,这后果想 ...
- mssql2008 r2 修改默认端口
1.点击“开始”-“所有程序”-“Microsoft SQL Server 2008R2”-“配置工具”-“SQL Server配置管理器” 2.在打开的“SQL Server配置管理器”窗口中,在左 ...
- RC4
RC4(Rivest Cipher 4)是一种流加密算法,密钥长度可变.并且因为加解密时使用的密钥相同,所以也为对称加密.加密过程和解密过程仅明密文的区别. 主要分为初始化 s 盒和伪随机密码生成组成 ...