一、什么是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. 深入学习Spring框架(二)- 注解配置

    1.为什么要学习Spring的注解配置? 基于注解配置的方式也已经逐渐代替xml.所以我们必须要掌握使用注解的方式配置Spring. 关于实际的开发中到底使用xml还是注解,每家公司有着不同的使用习惯 ...

  2. Modbus RTU 通信应用案例

    如何打开项目归档文件 例程中的TIA博途项目文件与STEP 7项目文件均为归档文件,需要按如下方式打开: TIA博途项目文件 1. 打开TIA博途软件,通过软件左下方“项目视图”按钮切换至项目视图: ...

  3. 【风哥干货】快速解决Oracle数据库故障必备的20个脚本与命令

    1.操作系统性能(通常故障出现时最先检查的内容)top.topas.vmstat.iostat.free.nmon 2.万能重启方法 如应急情况,需要重启数据库:tail -100f <对应路径 ...

  4. 利用iisnode模块,让你的Node.js应用跑在Windows系统IIS中

    最近比较喜欢用Node.js做一些简单的应用,一直想要部署到生产环境中,但是手上只有一台windows server 2008服务器,并且已经开启了IIS服务,运行了很多.Net开发的网站,80端口已 ...

  5. 一秒完成springboot与logback配置

    1. 一秒配置与效果 1.1 一秒配置 ​ spring boot中无须添加任何依赖,直接在resources文件夹下面新建logback.xml文件,将以下代码复制过去,配置完成,可以使用了. &l ...

  6. Bzoj 3874: [Ahoi2014&Jsoi2014]宅男计划 三分+贪心

    3874: [Ahoi2014&Jsoi2014]宅男计划 Time Limit: 1 Sec  Memory Limit: 256 MBSubmit: 861  Solved: 336[Su ...

  7. Java 内存映射文件

    import java.io.*; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; import jav ...

  8. nginx连接资源管理

    本文介绍在nginx中连接资源(即ngx_connection_t)的管理与使用. 连接池的初始化 在ngx_cycle_t结构体中维护了几个和连接相关的数据,具体如下 struct ngx_cycl ...

  9. 个人永久性免费-Excel催化剂功能第101波-批量替换功能(增加正则及高性能替换能力)

    数据处理无小事,正如没有人活在真空理想环境一下,在数据分析过程中,也没有那么真空理想化的数据源可以使用,数据处理占据数据分析的80%的时间,每一个小小的改善,获益都良多.Excel查找替换,有其局限性 ...

  10. 个人永久性免费-Excel催化剂功能第57波-一键生成完全组合的笛卡尔积结果表

    在数据库的多表查询中,通常会有各种连接关系,同样地在Excel环境中,也有很大的场景需要用到类似数据库的多表查询,如经典的VLOOKUP就是其中一种类似LEFT JOIN查询的查询效果.在很多时候需要 ...