一、什么是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. iOS 国际化 (国际化文字内容不改变,app名字国际化,一键切换语言)

    首先我们要分三个步骤讲解怎么一步步实现app名字国际化.内容国际化.一键切换国际化的: 一.app设置内容或者可以说是app名字或者可以说Info.Plist中的东西国际化  app名字国际化  1. ...

  2. fiddler无法抓取chrome浏览器请求的解决方案之关闭代理软件

    最近安装fiddler后,按照通用设置后依然无法抓取到chrome的请求,经检查,我本地的chrome安装了代理管理的插件Switchy,无论选择直接连接还是选择使用代理连接,插件都会屏蔽fiddle ...

  3. 图片去水印工具:Inpaint 7.2中文专业破解版下载及使用方法

    下载地址: 点我 Inpaint 是一款可以从图片上去除不必要的物体,让您轻松摆脱照片上的水印.划痕.污渍.标志等瑕疵的实用型软件:简单说来,Inpaint 就是一款强大实用的图片去水印软件,您的图片 ...

  4. 网络设置管理 NetSetMan Pro v4.7.1 Lite 绿色便携版

    下载地址:点我 基本介绍 Netsetman是一个小巧好用的工具,你可以设置六组不同的网络参数值,针对不同的网络环境,而调用不同的参数,当你在家中.学校.工作单位等不同环境切换网络配置文件时,只需要通 ...

  5. 《Graph Attention Network》阅读笔记

    基本信息 论文题目:GRAPH ATTENTION NETWORKS 时间:2018 期刊:ICLR 主要动机 探讨图谱(Graph)作为输入的情况下如何用深度学习完成分类.预测等问题:通过堆叠这种层 ...

  6. CDQZ集训DAY6 日记

    又炸了. 早上起来其他竞赛生也走了,食堂做饭做的挺潦草,但为什么四川烧麦的馅是米啊??!! 起来看题总觉得都似曾相识.第一题打完40分暴力后想拿莫队搞到70分,但发现能想到的莫队维护都是nsqrt(n ...

  7. Python重试模块retrying

    Python重试模块retrying 工作中经常碰到的问题就是,某个方法出现了异常,重试几次.循环重复一个方法是很常见的.比如爬虫中的获取代理,对获取失败的情况进行重试. 刚开始搜的几个博客讲的有点问 ...

  8. VBox on 14.04: Kernel driver not installed (rc=-1908) [duplicate]

    这几天刚刚装上Ubuntu的系统开始写Android代码,真心是流畅了很多,但是也出现了很多的问题. 还好 有大神护佑,童鞋博客首页,点击查看吧. 刚刚又遇到了一个新的问题,那就是我想用genymot ...

  9. Java秒杀系统实战系列~构建SpringBoot多模块项目

    摘要:本篇博文是“Java秒杀系统实战系列文章”的第二篇,主要分享介绍如何采用IDEA,基于SpringBoot+SpringMVC+Mybatis+分布式中间件构建一个多模块的项目,即“秒杀系统”! ...

  10. Java_异常介绍

    今日内容介绍: 掌握异常概述 理解异常的基础操作以及最简单的捕获处理 理解多异常捕获处理 理解声明抛出异常 掌握自定义异常 掌握异常处理注意事项 异常 什么是异常?Java代码在运行时期发生的问题就是 ...