一、写在前面

  之前做项目用到了基于Axis的WebService,为了更进一步的理解和记忆,在这里通过代码实践和源码分析来完整的做一遍Axis的WebService以及对应的客户端调用实践,并和其它的方式的接口做一些对比。

二、基于Axis的WebService和HTTP接口的优劣

  本质上而言,Axis的WebService在数据传输时用的就是基于HTTP协议的POST请求,调用WebService接口实际上就是在HTTP header里添加SOAPAction头,然后请求体里发送的是XML格式的数据,即SOAP报文,内部包括请求方法、请求参数等信息。

  客户端可以通过服务端提供的服务类的wsdl文件在本地生成一个服务类代理,使得客户端调用服务端的接口可以通过new一个本地代理类对象并调用实例方法来实现;比如服务代理类叫ATestProxy,那么调用WebService接口可以直接是

ATestProxy proxy = new ATestProxy();
Object result = proxy.servicePart(3);
/**
这里的servicePart就是服务端的服务类提供的接口,它的原理是
proxy.servicePart方法内部最终会通过HTTP POST请求发送数据,
此请求会被服务器中间件转发给Axis的Servlet,然后Servlet解析
请求的请求体,通过请求体提供的服务类、服务类方法、参数等
数据定位到服务类的具体方法,从而在Servlet里创建该服务类对象并
调用对应方法,然后返回值通过HTTP Response返回给客户端,
客户端又将Response里的响应体解析为变量或类对象
*/

WebService相比自写的HTTP请求好处有:

  1.容易定位使用位置,右键代理类方法查找引用即可;2.使用方便,不需要自己再构造HttpURLConnection对象;

WebService相比自写的HTTP请求劣处有:

  1.性能损耗,分析自动生成的服务代理类可以发现一个简单的HTTP请求被分成了很多步骤(光是产生的客户端类就有五个),从数据包装到真正发送数据经过了多个类的协调工作,这显然是比直接通过HTTP请求发送SOAP报文要慢的。2.不够灵活,勉强算是一个不是劣处的劣处吧。

  经过对比,个人认为,如果一个接口是可能频繁被调用的,那么一定不要用WebService;如果是内部系统的接口则用WebService是不错的选择。

三、创建WebService服务端

1.先创建一个简单的webapp项目,创建完毕后src及web.xml如图:

2.接下来在这个基础上创建一个WebService的服务类及供外部调用的public访问权限的方法,创建好后src和代码如图:

3.为此webapp创建基于Axis的WebService:
3.1.右键SerialCodeGenerator->New->Web Service->{在此步的Service Implementation填上silentdoer.web.services.SerialCodeGenerator,然后更改Configuration中的Server Runtime等配置,点击next;
3.2.勾选要发布的Methods,然后next,点击Start Server;
3.3.此webapp会添加进之前配置的tomcat Server里并启动tomcat,在WEB-INF目录下会生成server-config.wsdd文件(还有其它文件但是都不很重要),以及web.xml里会自动配置<servlet-name>AxisServlet</servlet-name>等配套的配置。
在server-config.wsdd里有如下配置:
<ns1:service name="SerialCodeGenerator" provider="java:RPC" style="wrapped" use="literal">
<!--这段配置可以注释-->
<!--<ns2:operation name="getNewStudentCode" qname="ns1:getNewStudentCode" returnQName="ns1:getNewStudentCodeReturn" returnType="xsd:long" soapAction="" xmlns:ns1="http://services.web.silentdoer" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns2="http://xml.apache.org/axis/wsdd/"/>-->
<!--可以将getNewStudentCode改为*则表示开放SerialCodeGenerator中所有的public的方法-->
<ns1:parameter name="allowedMethods" value="getNewStudentCode"/>
<ns1:parameter name="typeMappingVersion" value="1.2"/>
<ns1:parameter name="wsdlPortType" value="SerialCodeGenerator"/>
<ns1:parameter name="className" value="silentdoer.web.services.SerialCodeGenerator"/>
<ns1:parameter name="wsdlServicePort" value="SerialCodeGenerator"/>
<ns1:parameter name="schemaQualified" value="http://services.web.silentdoer"/>
<ns1:parameter name="wsdlTargetNamespace" value="http://services.web.silentdoer"/>
<ns1:parameter name="wsdlServiceElement" value="SerialCodeGeneratorService"/>
</ns1:service>
3.4.启动webapp所在的tomcat server后,在浏览器中输入:http://localhost:8080/Demo_WebServiceInWebapp/services/SerialCodeGenerator?wsdl即可获得此port对应的wsdl配置文件;这个配置文件的生成是通过调用wsdl引擎生成的,后面客户端通过wsdl文件生成Java代码也是通过这个引擎实现的;它的原理就是Axis的Servlet收到请求后会判断路径URI和查询参数,发现是SerialCodeGenerator?wsdl则匹配wsdd文件中的配置,匹配成功获得对于发布类的一系列信息[类名、public方法名、参数信息等等](可通过反射实现),然后在将这些信息作为参数调用wsdl引擎的映射方法,wsdl引擎返回wsdl配置信息,这个过程其实就是参数映射或说数据转换,只要理解好映射规则咱们自己也能写个wsdl引擎,比如假设传入字符串参数SerialCodeGenerator,返回<wsdl:portType name="SerialCodeGenerator">..</wsdl:portType>;
3.5.Java Axis框架本质上也是一个基于Servlet的处理服务,服务器中间件通过url-pattern将符合path/services/*的请求交给Axis的org.apache.axis.transport.http.AxisServlet处理,而客户端调用WebService时最终还是一个HTTP请求,pathinfo里以services开头,请求体里是soap报文,
在Header里有个SOAPAction用于区分普通的HTTP请求;对于服务器中间件而言这就是个普通的HTTP请求并将它转发给AxisServlet处理,AxisServlet内部会解析soap报文,提取出port、part、parameters等关键信息然后匹配后台的代码,匹配到则调用对应的方法并将返回值也封装成soap报文写在响应体里从而完成对客户端的服务。
3.6.客户端会生成一个和服务端开放接口具有相同方法签名的接口以及其实现类的stub,客户端通过stub对象调用本地方法就能够自动请求服务端调用对应的方法,然后返回结果给客户端的stub的对应方法,比如客户端调用stub.getCode()方法,在getCode()方法里会间接的构造soap报文,报文中的method就是getCode,其它参数也传递进来,然后通过HTTP请求发送此soap报文,然后服务端处理后返回数据,在getCode()里继续处理返回的数据并反序列化成对象然后返回给stub.getCode()的调用者。
3.7.在webapp里创建axis的webservice可以自己添加jar包和配置web.xml和server-config.wsdd也能实现在webapp里添加基于Axis框架的WebService服务。
3.8.接口方法的参数或返回值是一个JavaBean

四、创建WebService的测试客户端

1.同样的先创建一个项目,名字比如叫WebServiceTest;
2.右键src-new-WebService Client,然后在service definition里填写http://localhost:8080/Demo_WebServiceInWebapp/services/SerialCodeGenerator?wsdl;
3.点击finish,然后wsdl引擎会根据service definition中获得的wsdl描述信息生成相应的Java代码,如图:

4.这5个.Java文件的对应关系是SerialCodeGenerator是接口,里面的方法签名和服务端的一致,SerialCodeGeneratorProxy和SerialCodeGeneratorSoapBindingStub均继承自该接口,而Proxy是stub的代理;而SerialCodeGeneratorServiceLocator继承自SerialCodeGeneratorService,SerialCodeGeneratorService又继承自Service,这个Service对象可以用来创建Call对象,Call对象是WebServiceClient里真正调用请求服务端的比较底层的组成部分,后面会演示直接用Call对象来调用WebService服务(Call下面还可以继续深挖出HTTP请求-TCP请求等),SerialCodeGeneratorServiceLocator同时还存储了webservice请求的url,在本例中是:http://localhost:8080/Demo_WebServiceInWebapp/services/SerialCodeGenerator;(用UML)
5.main方法里调用,待添加;(客户端其实只需要知道请求的url、soap报文中的必要数据,如ser参数,方法名、参数等信息再加上SOAPAction的Header就可以用HTTP请求来实现调用webservice服务了);

6.如果服务端和客户端的JDK版本不一致则还可以直接通过HTTP请求发送soap报文。

7.客户端直接用Call类来完成webservice的调用

String endpoint="http://localhost:8080/SecondSpringMvcProj/services/HelloWebService";

        Call call = new Call(endpoint);

        // 对于复杂对象需要设置返回类型
call.setReturnClass(Student.class);
call.setOperationName("getStudent");
Student student = (Student)call.invoke(new Object[] {"uuuu"});
System.out.println(student.getName());

五、添加复杂类型

如果参数或返回值是自定义类型,则需要在server-config.wsdd的对应service内添加

<beanMapping qname="myNSD:Student" xmlns:myNSD="urn:Student"
languageSpecificType="java:silentdoer.web.pojo.Student"/>,否则复杂类型将无法正确被传输。

六、总结

如果是系统内部直接的接口用webservice还是不错的,毕竟用起来很方便,而且很多代码不用自己写;但是如果接口是与外部系统对接,且要求效率较高,灵活性较好则应该用HTTP请求;

浅析基于AXIS框架的WebService的更多相关文章

  1. WebService(基于AXIS的WebService编程)

    一.服务端代码 1.创建Maven工程 注意pom.xml文件的配置,需要引入axis的相关包 <project xmlns="http://maven.apache.org/POM/ ...

  2. Axis1.4框架 实现webservice服务器和客户端

    一:软件环境 win7旗舰版, Eclipse,JDK1.6,tomcat6.0,Axis1.4的包. 至于Axis1.4包网上可以下载,如果是在找不到可以留言给我. 二:摘要 将解压后的 axis- ...

  3. 基于dubbo框架下的RPC通讯协议性能测试

    一.前言 Dubbo RPC服务框架支持丰富的传输协议.序列化方式等通讯相关的配置和扩展.dubbo执行一次RPC请求的过程大致如下:消费者(Consumer)向注册中心(Registry)执行RPC ...

  4. 如何快速搭建一个基于ServiceStack框架的web服务

    ServiceStack是一个高性能的.NET Web Service 平台,能够简化开发高性能的REST (支持JSON,XML,JSV,HTML,MsgPack,ProtoBuf,CSV等消息格式 ...

  5. 【前端框架系列】浅谈当前基于bootstrap框架的几种主流前端框架

    一  概述 当新开发一个项目或产品时,技术选型是一个不可缺少的环节,在软件架构中有着举足轻重的作用,可以这么说,技术选型的好坏直接影响项目或产品的成败优劣,因此,在进行软件架构时,一定要想好技术选型. ...

  6. 基于Axis1.4的webservice接口开发(接口调用)

    基于Axis1.4的webservice接口开发(接口调用) 一.webservice接口代码参考上一篇博客: http://www.cnblogs.com/zhukunqiang/p/7125668 ...

  7. 基于Axis1.4的webservice接口开发(代码开发)

    基于Axis1.4的webservice接口开发(代码开发) 一.开发环境: 我的开发环境是MyEclipse 2015+Apache-Tomcat-8.0.21. 二.代码开发: 1.新建一个Web ...

  8. 基于Axis1.4的webservice接口开发(环境搭建)

    基于Axis1.4的webservice接口开发(环境搭建) 一.环境搭建: 1.搜索关键字“Axis1.4”下载Axis1.4相关的jar包. 下载地址:http://download.csdn.n ...

  9. 开发基于CXF的 RESTful WebService web 项目 webservice发布

    配置步骤 开发基于CXF的 RESTful WebService 1.创建Web项目并导入CXF的jar 2.在Web.xml中配置 CXFServlet <servlet> <se ...

随机推荐

  1. 2基本类型数组和枚举类型——重拾Java

    2.1 标识符和关键字 2.1.1标识符 标识符:用来标志类名.变量名.方法名.类型名.数组名.文件名的有效字符序列称为标识符.简单地说,标识符就是一个名字. Java关于标识符的语法规则 标识符由字 ...

  2. lnmp上传文件

    LAMP环境: Linux Mint 16 32bits xfce apache 2.4.6 Ubuntu php 5.5.3 默认www是/var/www,我用符号连接到了/home/tony/ww ...

  3. Ansible 从远程主机添加或删除MySQL数据库

    mysql_db - 从远程主机添加或删除MySQL数据库. 概要 要求(在执行模块的主机上) 选项 例子 笔记 状态 支持 概要 从远程主机添加或删除MySQL数据库. 要求(在执行模块的主机上) ...

  4. for循环计算阶乘的和,for循环计算阶乘倒数的和

    计算阶乘的和 //阶乘的和,5!+4!+3!+2! int a = 5; for(int b = 4; b > 0; b--) { a = a * b; } //先定义好最大数的阶乘是多少 in ...

  5. c++ stl常用

    #include<iostream>#include<string>#include<vector>#include<list>#include< ...

  6. Oracle 数据库的绑定变量特性及应用

    Oracle 数据库的绑定变量特性及应用[-----]转载自https://www.cnblogs.com/rootq/(原地址) 关键词: 绑定变量(binding variable),共享池(sh ...

  7. Java计算图的匹配率

    2016-07-02 大概意思就是这样了,代码里我貌似没有计算最后一步,但是原理都是一样的.....R1有5个点P1有四个点,他们共同的点是4个,那就是共同点4*4/(R1的5个点*P1的四个点就是0 ...

  8. python 网络客户端编程端口,模块

    协议 功能 端口 模块 HTTP 网页 80 httplib,urllib,xmlrpclib NNTP Usenet 新闻组 119 nntplib FTP 文件传输 20(21控制和命令端口) f ...

  9. 分割回文串 II · Palindrome Partitioning II

    [抄题]: 给定一个字符串s,将s分割成一些子串,使每个子串都是回文. 返回s符合要求的的最少分割次数. [思维问题]: 不知道要用预处理字符串降低复杂度 [一句话思路]: 先把预处理获得s中回文串的 ...

  10. ios 进入后台 一段时间在进入前台 动画消失

    http://www.cnblogs.com/YouXianMing/p/3670846.html