一、什么是WebService(来源百度百科)

  Web service是一个平台独立的,低耦合的,自包含的、基于可编程的web的应用程序,可使用开放的XML(标准通用标记语言下的一个子集)标准来描述、发布、发现、协调和配置这些应用程序,用于开发分布式的互操作的应用程序。

  Web Service技术, 能使得运行在不同机器上的不同应用无须借助附加的、专门的第三方软件或硬件, 就可相互交换数据或集成。依据Web Service规范实施的应用之间, 无论它们所使用的语言、 平台或内部协议是什么, 都可以相互交换数据。Web Service是自描述、 自包含的可用网络模块, 可以执行具体的业务功能。Web Service也很容易部署, 因为它们基于一些常规的产业标准以及已有的一些技术,诸如标准通用标记语言下的子集XML、HTTP。Web Service减少了应用接口的花费。Web Service为整个企业甚至多个组织之间的业务流程的集成提供了一个通用机制。

二、发布

  Web service 就是一个应用程序,它向外界暴露出一个能够通过Web进行调用的API。这就是说,你能够用编程的方法通过Web来调用这个应用程序。

  我们将调用这个Web service 的应用程序称作客户端,运行这个Web service 的应用程序称作服务端。

  在我之前创建的Web service项目其实就是一个服务端,这个HelloWorld类能实现的功能就是当客户端提交一个字符串的时候,返回一个"Hello, world, from " + 字符串;

public class HelloWorld {
public String sayHelloWorldFrom(String from) {
String result = "Hello, world, from " + from;
System.out.println(result);
return result;
}
}

  那么我们就需要将这个类发布在Web上,在Web service项目的客户端中是在server-config.wsdd中编写XML进行发布

    <service name="HelloWorld" provider="java:RPC" style="document" use="literal">
<parameter name="className" value="example.HelloWorld"/>
<parameter name="allowedMethods" value="*"/>
<parameter name="scope" value="Application"/>
<namespace>http://example</namespace>
</service>

  这里每个标签的具体含义以及填写内容:

  • name="HelloWorld"就是这个WebService的名字,可任意填写
  • provider="java:RPC"指的是服务类型,可填写四种类型RPC、Document、Wrapped、Message
  • <parameter name="className" value="example.HelloWorld"/>这个节点指出具体的类,value处填写类的路径
  • <parameter name="allowedMethods" value="*"/>这个节点表示可以调用所有的public方法,也可以自己指定
  • <parameter name="scope" value="Application"/>这个节点配置了service object,这里可以填写request、session、application
    • requst :这个选项会让AXIS为每一个SOAP的请求产生一个服务对象,可以想像如果这个webservice的对象足够复杂,而且SOAP的请求过多,这个选项是非常耗费服务器性能的。
    • session:表示对同一个客户代理对象所发送的请求使用同一个服务对象,并把服务信息放在同一个上下文当中。

    • application: 类似于使用单体模式,表示所示的请求均使用同一个服务对象

  然后点击运行。。。

  再然后就是客户端的代码,新建一个ClientWSDD类

public class ClientWSDD {
public static void main(String[] args){
try {
String url =
"http://localhost:8080/test/services/HelloWorld?wsdl";
//生成服务对象Service
Service service = new Service();
Call call = (Call) service.createCall();
//设置Endpoint地址
call.setTargetEndpointAddress(new java.net.URL(url));
//绑定请求方法名称
call.setOperationName(new QName(url, "sayHelloWorldFrom"));
//通过call.invoke 调用服务,获取返回值
String result = (String) call.invoke(new Object[]{"xw"});
System.out.println("result = " + result);
}catch (ServiceException e){
System.out.println("ServiceException");
e.printStackTrace();
}catch (RemoteException e){
System.out.println("RemoteException");
e.printStackTrace();
} catch (MalformedURLException e) {
System.out.println("MalformedURLException");
e.printStackTrace();
}
}
}

  具体使用流程注释里写得很清楚,要注意的就是方法名,传入参数的个数,最后运行这个ClientWSDD类,可以看到输出:

  

  输入的参数是xw,最终返回的结果是Hello, world, from xw。

三、高级特性Handler

  Handler在功能上类似与Filter过滤器可以在WebService服务被调用前调用,也能在调用后调用。

  这样我们可以实现WebService权限验证、记录调用次数,这次这里就实现记录某个WebService被调用次数的Handler

  首先创建一个继承BasicHandler的类,BasicHandler是一个Axis的抽象类,然后实现其中的invoke()方法:

public class HelloWorldHandler extends BasicHandler {
private static final long UID = 2333333L; private static long COUNT = 0L; private int requestCount = 0; @Override
public void invoke(MessageContext messageContext) throws AxisFault {
requestCount++;
COUNT++;
String status = (String) this.getOption("status");
System.out.println("HelloWorldHandler status " + status +
", COUNT " + COUNT +
", requestCount " + requestCount);
}
}

  messageContext是一个Axis的上下文,里面存储了一些Axis和WebService的基本信息。这个类中有一个静态变量COUNT用于记录Handler的被调用次数,每次Handler被调用的时候都将加一

  再然后我们还需要发布这个Handler,在server-config.wsdd中编写XML:

  <handler name="HelloWorldHandler" type="java:example.HelloWorldHandler">
<parameter name="status" value="success"/>
</handler>
<service name="HelloWorldWSDDHandler" provider="java:RPC">
<requestFlow>
<handler type="HelloWorldHandler"/>
</requestFlow>
<parameter name="className" value="example.HelloWorld"/>
<parameter name="allowedMethods" value="*"/>
<parameter name="scope" value="request"/>
<responseFlow>
<handler type="HelloWorldHandler"/>
</responseFlow>
</service>
  • <handler></handler>中先是创建了一个名为HelloWorldHandler,类的路径是example.HelloWorldHandler的Handler,还创建了一个值为success的status参数
  • 然后创建了一个service服务,名为HelloWorldWSDDHandler,服务类型为RPC,这个服务使用的类是example.HelloWorld
  • <requestFlow><handler type="HelloWorldHandler"/></requestFlow>表示在调用这个服务前将先调用这个HelloWorldHandler

  • <responseFlow><handler type="HelloWorldHandler"/></responseFlow>表示调用这个服务后将先调用这个HelloWorldHandler

  服务端点击运行之后可以在http://localhost:8080/test/services页面中看到多了一个HelloWorldWSDDHandler服务:

  

  客户端的调用和之前类似,只是需要修改URL,因为具体调用的功能和刚才一样,但是调用的服务不一样了

public class ClientWSDD {
public static void main(String[] args){
try {
String url =
"http://localhost:8080/test/services/HelloWorldWSDDHandler?wsdl";
//生成服务对象Service
Service service = new Service();
Call call = (Call) service.createCall();
//设置Endpoint地址
call.setTargetEndpointAddress(new java.net.URL(url));
//绑定请求方法名称
call.setOperationName(new QName(url, "sayHelloWorldFrom"));
//通过call.invoke 调用服务,获取返回值
String result = (String) call.invoke(new Object[]{"xw"}); System.out.println("result = " + result);
}catch (ServiceException e){
System.out.println("ServiceException");
e.printStackTrace();
}catch (RemoteException e){
System.out.println("RemoteException");
e.printStackTrace();
} catch (MalformedURLException e) {
System.out.println("MalformedURLException");
e.printStackTrace();
}
}
}

  在点击运行,在客户端的输出和刚才一样,但是在服务端可以看到输出:

  

  这个HelloWorldHandler在服务被调用前后被调用,如果只在服务调用前或者之后调用那么就能实现记录被调用次数的功能。

  同一个Handler类可以当作两个不一样的Handler调用,这只需要在发布的时候再发布一个Handler就行:

  <handler name="HelloWorldHandler" type="java:example.HelloWorldHandler">
<parameter name="status" value="success"/>
</handler>
<handler name="HelloWorldHandler2" type="java:example.HelloWorldHandler">
<parameter name="status" value="success"/>
</handler>
<service name="HelloWorldWSDDHandler" provider="java:RPC">
<requestFlow>
<handler type="HelloWorldHandler"/>
</requestFlow>
<parameter name="className" value="example.HelloWorld"/>
<parameter name="allowedMethods" value="*"/>
<parameter name="scope" value="request"/>
<responseFlow>
<handler type="HelloWorldHandler2"/>
</responseFlow>
</service>

  这里我又发布了一个名为HelloWorldHandler2的Handler,然后HelloWorldWSDDHandler之前将调用HelloWorldHandler,之后将调用HelloWorldHandler2。然后在运行两次客户端代码,最后的输出是:

  

因为COUNT是静态变量所以调用了两次就被加一两次,而request则没有,所以可以看出这里创建了两个HelloWorldHandler对象。这里的requset完成了记录WebService被调用次数的功能

四、高级特性Chain

  Chain用于实现一连串的Handler功能,因为是一连串的所以。。需要先再创建一个Handler类,这里修改了UID和输出:

public class HelloWorldHandler2 extends BasicHandler {
private static final long UID = 3222222L; private static long COUNT = 0L; private int requestCount = 0; @Override
public void invoke(MessageContext messageContext) throws AxisFault {
requestCount++;
COUNT++;
String status = (String) this.getOption("status");
System.out.println("HelloWorldHandler2 status " + status +
", COUNT " + COUNT +
", requestCount " + requestCount);
}
}

  然后是创建Chain类,在Chain的构造函数中,需要创建想要调用的Handler类对象实例,然后使用addHandler方法将两个Handler加载进行,

public class HelloWorldChain extends SimpleChain {
private static final long UID = 2222333L; public HelloWorldChain(){
HelloWorldHandler handler1 = new HelloWorldHandler();
HelloWorldHandler2 handler2 = new HelloWorldHandler2(); this.addHandler(handler1);
this.addHandler(handler2);
}
}

  然后是发布的xml:

  <handler name="HelloWorldChain" type="java:example.HelloWorldChain">
</handler>
<service name="HelloWorldWSDDChain" provider="java:RPC">
<requestFlow>
<handler type="HelloWorldChain"/>
</requestFlow>
<parameter name="className" value="example.HelloWorld"/>
<parameter name="allowedMethods" value="*"/>
<parameter name="scope" value="request"/>
<responseFlow>
<handler type="HelloWorldChain"/>
</responseFlow>
</service>

  和之前发布Handler类似的使用方法,我看资料用的标签是<chain></chain>但是不知道为什么我这里会报错,所以我直接修改成了Handler也能成功运行,所以其实chain也是Handler。

  运行之后同样先在浏览器中的http://localhost:8080/test/services页面查看服务是否正常发布,

  

  然后修改客户端的代码中的URL,

public class ClientWSDD {
public static void main(String[] args){
try {
String url =
"http://localhost:8080/test/services/HelloWorldWSDDChain?wsdl";
//生成服务对象Service
Service service = new Service();
Call call = (Call) service.createCall();
//设置Endpoint地址
call.setTargetEndpointAddress(new java.net.URL(url));
//绑定请求方法名称
call.setOperationName(new QName(url, "sayHelloWorldFrom"));
//通过call.invoke 调用服务,获取返回值
String result = (String) call.invoke(new Object[]{"xw"}); System.out.println("result = " + result);
}catch (ServiceException e){
System.out.println("ServiceException");
e.printStackTrace();
}catch (RemoteException e){
System.out.println("RemoteException");
e.printStackTrace();
} catch (MalformedURLException e) {
System.out.println("MalformedURLException");
e.printStackTrace();
}
}
}

  然后是服务端的输出:

  

  可以看到HelloWorldHandler2将在HelloWorldHandler之后被调用。

  

WebService1的更多相关文章

  1. flex 调用WebService1(基于.net)

    以.net平台下C#语言开发的WebService为web服务,使用flex  actionscript语句访问webservice接口 Flex:  Temp.mxml部分代码 //调用WebSer ...

  2. C#winForm调用WebService的远程接口

    Web Service 的创建简单编码.发布和部署 上一篇详细概述了WebService的创建,编码,发布和部署,那么作为客户端的程序如何访问远程端的WebService 接下来看一下具体步骤:   ...

  3. Web Service 的创建简单编码、发布和部署

    最近,老大准备将已有的C/S架构项目中的通信部分做成通用,需要将其支持WebService为以后项目向着B/S架构升级做好铺垫,为此身为屌丝的我去各种百度WebService是个什么卵玩意,然后逐渐搭 ...

  4. webserver[实时查询当天的天气情况]

    1.webserver是什么? 日常生活中经常会使用到webserver,注册时,会收到验证码,购买东西时,会收到短信,假如,A公司网站和B公司合作,那么A公司注册对的用户可以直接推送给B网站,那怎么 ...

  5. WebService返回DataTable

    http://blog.csdn.net/wxnjob/article/details/8638420 webservice返回datatable时报序列化错误 以下三种方案的实质应该都是序列化的,有 ...

  6. 指定的架构无效。错误: CLR 类型到 EDM 类型的映射不明确

    在使用WebService开发时,同时使用了EF和linq,查询数据时,使用linq(查询订单)可以正常拉出数据, 但是使用EF(查询用户)却会报以下错误: {"指定的架构无效.错误: \r ...

  7. Webservice服务创建、调用笔记

    引言 以前使用windows服务,于是学习并记录下来:windows服务的创建.安装.调试全过程及引发的后续学习.现如今需要用到webservice,对此感觉到很困惑.经过几天的学习.查阅资料,终于大 ...

  8. 将webservice封装成dll

    生成dll文件的步骤如下:1.发布完成后,在浏览器中打开WebService文件,如:http://localhost/WebSer/WebService1.asmx,可以看到WebService1. ...

  9. webservice服务的简单应用

    本人目前刚接触到webservice服务,知道它是一个为外部提供接口的服务,下面大概讲一下webservice是如何应用的. 在此我只针对ASP.NET 讲一个是如何应用的: 1. 打开VS ,在WE ...

随机推荐

  1. java接口自动化(一) - 接口自动化测试整体认知 - 开山篇(超详解)

    简介 了解什么是接口和为什么要做接口测试.并且知道接口自动化测试应该学习哪些技术以及接口自动化测试的落地过程.其实这些基本上在python接口自动化的文章中已经详细的介绍过了,不清楚的可以过去看看.了 ...

  2. Object.keys使用整理

    一.语法 Object.keys(obj) 参数:要返回其枚举自身属性的对象 返回值:一个表示给定对象的所有可枚举属性的字符串数组 二.处理对象,返回可枚举的属性数组 let person = { n ...

  3. Skyline WEB端开发2——添加一个定位点、文本标签

    Skyline 添加定位点 sgworld.Creator.CreatePosition CreatePosition( X, //兴趣点的东西方向坐标,即经度 Y, //兴趣点的南北方向坐标,即纬度 ...

  4. 【译】.NET Core 3.0 发布自包含单体可执行程序

    .NET Core 提供的发布应用程序选项 self-contained 是共享应用程序的好方法,因为应用程序的发布目录包含所有组件.运行时和框架.您只需要告诉使用者应用程序的入口 exe 文件,就可 ...

  5. WinForm控件之【ListView】

    基本介绍 项列表控件,拥有五种不同视图的样式供展示项集合. 常设置属性 Columns:‘详细信息’视图中用来显示的列: Groups:ListView列表中的组,将列表各项分组区域展示: Horiz ...

  6. 个人永久性免费-Excel催化剂功能第43波-文本处理类函数增强

    Excel的函数有400多个,真正常用的50多个,而常有的文本处理类函数也不多,不是因为文本类处理简单,而是Excel真的有点挤牙膏式的每个版本更新那么几个小函数,普通用户等得急切,但实际上这些小函数 ...

  7. 为什么选择 Spring 作为 Java 框架

    1. 概述 在本文中,我们将讨论 Spring 作为最流行的 Java 框架之一的主要价值体现. 最重要的是,我们将尝试理解 Spring 成为我们选择框架的原因.Spring 的详细信息及其组成部分 ...

  8. AMD CPU环境下使用android studio,eclipse的Genymotion插件

    1.下载安装VirtualBox Genymotion的运行需要此环境(链接) 2.下载安装android模拟器Genymotion 由于官网的下载速度过慢,建议直接百度下载Genymotion(链接 ...

  9. Go语言圣经习题练习_1.4. GIF动画

    练习 1.5: 修改前面的Lissajous程序里的调色板,由黑色改为绿色.我们可以用color.RGBA{0xRR, 0xGG, 0xBB, 0xff}来得到#RRGGBB这个色值,三个十六进制的字 ...

  10. Floyd—Warshall算法

    我们用DP来求解任意两点间的最短路问题 首先定义状态:d[k][i][k]表示使用顶点1~k,i,j的情况下,i到j的最短路径 (d[0][i][j]表示只使用i和j,因此d[0][i][j] = c ...