一、什么是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. Vue技术点整理-安装引入

    Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架 所谓渐进式是指: 1,如果你有一个现成的web应用,你可以将vue作为该应用的一部分嵌入其中,带来更丰富的交互体验 ...

  2. ajax 的简单请求,get的加法运算,post加法运算,用户登录认证

    视图函数部分 from django.shortcuts import render, HttpResponse import time from app01.models import User i ...

  3. 业以太网:西门子PROFINET诊断功能SFC12-OB86-SFB20概览

    [OB86配合SFC12在PROFINET诊断中的应用] OB86是机架故障组织块,操作系统在检测到下列PN系统故障时将调用OB86: 1.检测到PROFINET IO设备故障,故障产生和消失时分别调 ...

  4. echo-nginx-module的安装、配置、使用

    一.下载压缩包 [root@www nginx-1.16.0]# wget https://github.com/openresty/echo-nginx-module/archive/v0.61.t ...

  5. [HNOI2015]菜肴制作 题解(自带口胡证明)

    [HNOI2015]菜肴制作 时间限制: 1 Sec  内存限制: 512 MB 题目描述 知名美食家小 A被邀请至ATM 大酒店,为其品评菜肴. ATM 酒店为小 A 准备了 N 道菜肴,酒店按照为 ...

  6. ROS中URDF的学习以及与Xacro的比较

    1.urdf与Xacro简单比较 "URDF" 是最初也是比较简单的机器人描述文件,它的结构简单明了,容易理解.但是这也导致当机器人模型变得复杂时,urdf的结构描述就变得冗长,无 ...

  7. WinForm控件之【LinkLabel】

    基本介绍 超链接标签控件,随处可见应用极为广泛,一般用作触发指定链接跳转指定页面等操作. 常设置属性.事件 ActiveLinkColor:用户单击超链接时超链接显示的颜色: LinkColor:超链 ...

  8. 【dfs基础讲解及例题】

    定义 DFS(Depth-First-Search)深度优先搜索算法,是搜索算法的一种. 接下来因为懒得去找大段大段深奥的材料 所以就是一些个人的理解. 所谓深搜,是相对于广搜(只是第一篇)来说的.深 ...

  9. sql server 2382端口问题

    前两天在微软下载了官方示例数据库AdventureWorksDW2008R2及它的OLAP项目:AdventureWorks 2008R2 Analysis Services Project < ...

  10. weblogic安装时检查监视器: 必须配置为至少显示 256 种颜色,实际空间未知→失败

    1.首先如果你出现的结果是[未通过],则设置DISPLAY环境变量. 按网上方法:export DISPLAY=:0.0 然后继续安装你的东西……若成功则恭喜你~ 若[失败],按网上方法让你去看日志 ...