WebService1
一、什么是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的更多相关文章
- flex 调用WebService1(基于.net)
以.net平台下C#语言开发的WebService为web服务,使用flex actionscript语句访问webservice接口 Flex: Temp.mxml部分代码 //调用WebSer ...
- C#winForm调用WebService的远程接口
Web Service 的创建简单编码.发布和部署 上一篇详细概述了WebService的创建,编码,发布和部署,那么作为客户端的程序如何访问远程端的WebService 接下来看一下具体步骤: ...
- Web Service 的创建简单编码、发布和部署
最近,老大准备将已有的C/S架构项目中的通信部分做成通用,需要将其支持WebService为以后项目向着B/S架构升级做好铺垫,为此身为屌丝的我去各种百度WebService是个什么卵玩意,然后逐渐搭 ...
- webserver[实时查询当天的天气情况]
1.webserver是什么? 日常生活中经常会使用到webserver,注册时,会收到验证码,购买东西时,会收到短信,假如,A公司网站和B公司合作,那么A公司注册对的用户可以直接推送给B网站,那怎么 ...
- WebService返回DataTable
http://blog.csdn.net/wxnjob/article/details/8638420 webservice返回datatable时报序列化错误 以下三种方案的实质应该都是序列化的,有 ...
- 指定的架构无效。错误: CLR 类型到 EDM 类型的映射不明确
在使用WebService开发时,同时使用了EF和linq,查询数据时,使用linq(查询订单)可以正常拉出数据, 但是使用EF(查询用户)却会报以下错误: {"指定的架构无效.错误: \r ...
- Webservice服务创建、调用笔记
引言 以前使用windows服务,于是学习并记录下来:windows服务的创建.安装.调试全过程及引发的后续学习.现如今需要用到webservice,对此感觉到很困惑.经过几天的学习.查阅资料,终于大 ...
- 将webservice封装成dll
生成dll文件的步骤如下:1.发布完成后,在浏览器中打开WebService文件,如:http://localhost/WebSer/WebService1.asmx,可以看到WebService1. ...
- webservice服务的简单应用
本人目前刚接触到webservice服务,知道它是一个为外部提供接口的服务,下面大概讲一下webservice是如何应用的. 在此我只针对ASP.NET 讲一个是如何应用的: 1. 打开VS ,在WE ...
随机推荐
- os.path.join用法
os.path.join()函数:连接两个或更多的路径名组件 1.如果各组件名首字母不包含’/’,则函数会自动加上 2.如果有一个组件是一个绝对路径,则在它之前的所有组件均会被舍弃 3.如果最后一个组 ...
- 你懂什么叫js继承吗
说到继承呢?肯定有很多做java的朋友都觉得是一个比较简单的东西了.毕竟面向对象的三大特征就是:封装.继承和多态嘛.但是真正对于一个javascript开发人员来说,很多时候其实你使用了继承,但其实你 ...
- springboot与springcloud的关系
1 . 问题描述 随着springboot.springcloud的不断迭代升级,开发效率不断提升,越来越多的开发团队加入到spring的大军中,今天用通俗的语言,介绍下什么是springboot,s ...
- Spring IoC控制反转创建实例
Spring IoC控制反转创建实例写一个配置文件beans.xml,配置文件的约束可以访问:完整链接:https://repo.spring.io/libs-release-local/org/sp ...
- cogs.12运输问题2题解
乍一看貌似和运输问题1没有任何区别,但本题有一个有意思的东西叫做下限,我个人称之为非强制下限,因为本题中要求的实际是我走这条边这条边才至少走下限的流,虽然出题人没说,但从样例来看确实是这样的,而强制下 ...
- 彻底搞清楚c#中的委托和事件
一.什么是委托呢? 听着名字挺抽象,确实不好理解.面试官最喜欢考察这个,而且更喜欢问:“委托和事件有何异同?”.如果对一些知识点没有想明白,那么很容易被绕进去.研究任何事物,我们不妨从它的定义开始,委 ...
- 不调用free会内存泄露吗?
内存泄露的概念大家可以自行百度下,本文不做阐述.本文要讲的是在程序中分配了内存,但是最后没有使用free()函数来释放这块内存,会导致内存泄露吗?比如有如下代码: #include <stdio ...
- EnjoyingSoft之Mule ESB开发教程第二篇:Mule ESB基本概念
目录 1. 使用Anypoint Studio开发 2. Mule ESB Application Structure - Mule ESB应用程序结构 3. Mule ESB Application ...
- 软件测试必须掌握的linux命令大全
测试工程师的四大基础技能:数据库.linux.网络协议.测试工具,不管是刚入门还是已经工作多年,这几个方向都是要掌握的.今天我们再讲一下测试工程师必须要掌握的linux命令. 测试工程师需要掌握lin ...
- springboot启动不设置端口
非web工程 在服务架构中,有些springboot工程只是简单的作为服务,并不提供web服务 这个时候不需要依赖 <dependency> <groupId>org.spri ...