加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

Webservice,基于Axis的最佳实践。

发布时间:2020-12-17 02:37:44 所属栏目:安全 来源:网络整理
导读:? Web Service 实战 1. ???? 基本原理: 从宏观看,是基于协议( SOAP 协议)的 web 服务,从微观层面看,就是一个应用程序,暴露给外界,外界的程序可以通过 web 的方式来调用其 API ,我们以前写一个 dao 或者一个 mgr ,你要是想调用他的方法,用 java 语
?

Web Service实战

1.???? 基本原理:
从宏观看,是基于协议(SOAP协议)的web 服务,从微观层面看,就是一个应用程序,暴露给外界,外界的程序可以通过web的方式来调用其API,我们以前写一个dao或者一个mgr,你要是想调用他的方法,用java语言来描述,通常是要通过或者类的实例,然后调用类的方法。比如说:
Class UserMgr{
???? public void checkUser();

},
你要是想调用的话,可以通过这样,在你的Action里(假设通过Struts作为客户端程序)

UserMgr um = new UserMgr();
um.checkUser();//
注意,这里产生了调用。
那么我们现在只要把这个UserMgr这个类暴露给外界(web Service),让其客户端程序(调用/访问 -可以是任何程序,只要是它能支持WebService就可以),比如说,在c#的程序里要调用一个java应用程序的API(方法),这里是一个Add方法。

?

?

package?com.zhuweisky.xfireDemo;
public?class
?MathService?
{
????
public?int?Add(int?a?,int
?b)
????{
????????
return
?a+b?;
????}
}




2.????
----------------------------------------------------------

? //C#
????????????????string
?url?=?"http://localhost:8080/XFireZhuweiTest/services/MathService"?;
????????????????
object
[]?args?={1,2}?;
????????????????
object
?result?=?ESFramework.WebService.WebServiceHelper.InvokeWebService(url?,"Add"?,args)?;
????????????????MessageBox.Show(result.ToString());

3.????
????????


爱思考的人肯定会问了,这中跨平台之间的调用(WebService)肯定需要一个协议,这里的协议就是与平台无关的RPC-----远程过程调用协议-----它可以真正实现互操作。RPC由三部分组成的。
?1.1 XML
XSD
?????
聪明的人一定会想到XML(可扩展的标记语言),它是真正的跨平台的数据格式----平台无关和厂商无关,XML是解决了数据表示问题,但是还缺少了一套标准的数据类型,更没有说怎么样去扩展这套数据类型,例如,整形数到底表示什么?16位,32位,64位,这些对于跨平台来说也是非常重要的,W3C制定的XML SchemeXSD)就是专门解决这个问题的提出一套标准,它定义了一套标准的数据类型---这个可是任何厂商都要支持的哦,WebService就是使用XSD作为数据类型系统的,当你使用某种类型的语言(.Net or Java)来构建某个WebService,为了符合WebService标准,你所有的数据类型都必须转换位XSD类型。一般来说你用的工具会帮你完整这个标准转换的工作。当然你也可以自己定义。
?1.2 SOAP
???
你建好了一个WebService以后,客户端程序需要去调用,简单对象访问协议(SOAP)提供了标准的RPC方法来调用你的WebService。实际上,SOAP在这里有点用词不当,不一定是对象,你完全可以用C写一个函数作为一个WebService,任然可以通过SOAP进行调用,SOAP规范定义了SOAP消息的格式,以及怎样通过Http协议来使用SOAPSOAP也是基于XMLXSD的,XMLSOAP的数据编码格式。我猜想一下SOAP的底层的实现原理,以java为例,启动一个Servlet程序,这个Servlet接受网络(Http协议)上的SOAP对象------------假设不是WebServiceServlet可能接受的就是普通HttpSerletRequest对象,这个SOAP对象是包含着标准的基于XML的数据。然后这个Servlet最先需要做的事情就是解析这个对象,获得足够多的信息然后调用对应的方法。
?1.3 WSDL ???
???
你会怎么样向别人介绍你的web Service都有那些功能呢?以及每个函数调用时候的参数呢?你可能写一个文档或者口头告诉需要调用你的WebService的人,这些非正式的方法有一个严重的问题就是,他们的工具(比如Eclipse或者Visio Studio)不能提供任何的帮助,因为你的工具根本不了解你的WebService,一个解决的办法是用一个机器能认识的文档,WebService的一个描述语言(WSDL)就是这样一个基于XML的语言,用WebService以及其函数和函数的参数,返回值,因为这是基于xml的,所以WSDL是能够被机器阅读的,人也可以阅读,

4.???? 用途:
系统集成,系统间的数据交换,分布计算,不同平台的互操作。说白了,就是你可以在.Net上用C#程序调用Java的程序(要求是你的程序是基于WebService的)

5.???? 实战部分
java为例,首先特别申明,目前支持WebService的框架有很多(这些框架做了一些基础的工作,使得你编写一个WebService非常地方便,和使用HibernateJDBC的区别一样),我们这里以集成在MyEclipsexFire框架为例,目前这个框架的发展势头很,对Spring的支持也很充分,类似的支持WebService的框架还有很多,比如说axis
先用MyEclipse建立一个WebService的工程,然后编写接口和实现类,

public interface IService {

??? public String testMethod(String testStr);

?

}

实现类:

public class ECIWebservice implements IService {

?

??? public void putMessage(MessageInfo message,String authInfo)

?????????? throws UniediException {

?????? // TODO Auto-generated method stub

?

??? }

?

??? public void putMessages(MessageInfo[] messages,String authInfo)

?????????? throws UniediException {

?????? // TODO Auto-generated method stub

?

??? }

?

??? public MessageInfo getMessage(String appId,String orgCode,String authInfo)

?????????? throws UniediException {

?????? // TODO Auto-generated method stub

?????? return null;

??? }

?

??? public MessageInfo[] getMessages(String appId,

?????????? String authInfo,int count) throws UniediException {

?????? // TODO Auto-generated method stub

?????? return null;

??? }

?

??? public String testMethod(String testStr) {

?????? System.out.println("&&&&&&&&&&&&&&&&&Hello: "+testStr+"******************");

?????? return "The para is "+testStr;

??????

??? }

?

}

建立一个WebService的工程,其实没有什么什么特别,仅仅是比普通的Tomcat工程多WebService.xml文件---这个时候的此文件啥内容都没有。

然后再建立一个WebService,这个时候会提示

默认会把当前所有的webService工程都列出来。选择其中一个,进入一下步:选择你的发布名字,以及要把那个API开放出去(接口和实现类,默认会把所有public的方法都开放出去)。

?



?

点击完成。其实做这一步骤仅仅是为了修改webservice.xml文件。

请看修改后的文件内容:

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://xfire.codehaus.org/config/1.0">

???

??? <service>

?????? <name>testwebservice</name>

?????? <serviceClass>com.webservice.test.IService</serviceClass>

?????? <implementationClass>

?????????? com.webservice.test.ECIWebservice

?????? </implementationClass>

?????? <style>wrapped</style>

?????? <use>literal</use>

?????? <scope>application</scope>

??? </service></beans>

?

?

至此,一个WebService已经建立完成,发布到web容器上(Tomcatjboss都是可以的)你可以有三种方式来测试。

第一种方式是:

利用MyEclipse自带的Web service explorer

点击go以后。

点击bindingslink以后,就能看到binding了的所有方法,这些方法都是可以在这里调用的。

我们以一个简单的方法testMethod()作为测试使用。

看看执行后得效果:

第二种方法就是通过,使用浏览器的:

直接在浏览器的地址栏里输入:

http://localhost:8080/mywebservice/services/testwebservice?wsdl

应该可以看到一个XML文件(此文件就是描述文件WSDL)的内容,不过这里只摘写部分内容:

<xsd:element name="testMethod">

- <xsd:complexType>

- <xsd:sequence>

? <xsd:element maxOccurs="1" minOccurs="1" name="in0" nillable="true" type="xsd:string" />

? </xsd:sequence>

? </xsd:complexType>

? </xsd:element>

- <xsd:element name="testMethodResponse">

- <xsd:complexType>

- <xsd:sequence>

? <xsd:element maxOccurs="1" minOccurs="1" name="out" nillable="true" type="xsd:string" />

? </xsd:sequence>

? </xsd:complexType>

? </xsd:element>

。。。。。

<wsdl:message name="testMethodResponse">

? <wsdl:part name="parameters" element="tns:testMethodResponse" />

? </wsdl:message>

。。。。。

<wsdl:operation name="testMethod">

? <wsdl:input name="testMethodRequest" message="tns:testMethodRequest" />

? <wsdl:output name="testMethodResponse" message="tns:testMethodResponse" />

? </wsdl:operation>

。。。。

<wsdl:service name="testwebservice">

- <wsdl:port name="testwebserviceHttpPort" binding="tns:testwebserviceHttpBinding">

? <wsdlsoap:address location="http://localhost:8080/mywebservice/services/testwebservice" />

? </wsdl:port>

? </wsdl:service>

能看到这部分内容也是说明你的WebService已经好了。

?

第三种方法就是编写一个客户端程序去测试,特别说明的是,这个客户端可以人适合程序,aspVB.net,C#,

我们是使用了一个javaApplication

public static void main(String[] args){

?????? IService is =null;

?????? org.codehaus.xfire.service.Service srvcModel = new? ObjectServiceFactory().create(IService.class);?

?????? XFireProxyFactory factory = new XFireProxyFactory(XFireFactory.newInstance().getXFire());

?????? ?? String helloWorldURL = "http://localhost:8080/mywebservice/services/testwebservice";

?????? ?? try {????????

?????????? ?? is = (IService)factory.create(srvcModel,helloWorldURL);

?????????? ?? is.testMethod("zhangsan");

?????? ?? }catch(Exception ex){

?????????? ??

?????? ?? }

?

??? }

程序顺利执行,其结果就在tomcat的控制台打印出来了我们想看到的内容了。这里需要特别说明的是,假如不用XFire框架,可是可以编写你自己的WebService的客户端程序的。或者使用了其他的框架(这里以Axis为例):

String endpoint = " http://localhost:8080/mywebservice/services/testwebservice";

?????????? ?? Service service = new Service();

?????????? ?? Call call = (Call)service.createCall();

?????????? ?? call.setTargetEndpointAddress(endpoint);

call.setOperationName(new QName("urn: testwebservice ","testMethod"));

?????????? ?? String resultStr = ((String)call.invoke(new Object[]{theIntArray}));

?????????? ?? System.out.println("result_int: " + resultStr);

?

---------------------------------------------------------------------------------

Axis原理探讨与实战演练

Axis是支持Webservicejava平台的框架,和Xfire是一样的。不过使用起来好像比Xfire要麻烦很多。

它有三种方式支持Webservice

1. ?Dynamic Invocation Interface ( DII) ?

2.? Dynamic Proxy,

3.? Stubs,

?

三种方式的介绍:

?

<!--[if !supportLists]-->1.? <!--[endif]-->?DII是最简单的方式,编写一个java文件比如说MyService,记住不需要编译成class文件,因为Axis会帮您编译,你需要做的是拷贝这个java文件到一个目录下,我们是拷贝MyServic.javaaxis_example/jws目录下,更改文件名为MyService.jws,然后编写一个Client程序,直接访问之,

import org.apache.axis.client.Call; ?

import org.apache.axis.client.Service; ?

import javax.xml.namespace.QName; ?

import javax.xml.rpc.ServiceFactory; ?

import java.net.URL; ?

public class Client { ?

??? public static void main(String [] args) throws Exception { ?

??????? // 指出service所在URL ?

??????? String endpoint = "http://localhost:8080/axis_example/jws/MyService.jws"; ?

??????? // 创建一个服务(service)调用(call) ?

??????? Service service = new Service(); ?

??????? Call call = (Call) service.createCall();// 通过service创建call对象

??????? // 设置service所在URL ?

??????? call.setTargetEndpointAddress(new java.net.URL(endpoint)); ?

??????? // 方法名(processService)MyService.java方法名保持一致 ?

??????? call.setOperationName("processService"); ?

??????? // Object 数组封装了参数,参数为"This is Test!",调用processService(String arg) ?

??????? String ret = (String) call.invoke(new Object[]{"This is Test!"}); ?

??????? System.out.println(ret); ?

??? } ?

} ?

?

axis_example 工程放入tomcat/webapps启动tomcat ?

编译Client.java,运行其中的main方法进行测试,可以看到屏幕打印出:"This is Test!",可以看到axis_example/WEB-INF目录下生jwsClasses/jws/MyService.class文件——axis会根据你访问时的endpoint,自动编译其中的*.jws文件,并置于生成的jwsClasses相应目录下。

?

1 在上面的 new Object[]{"This is Test!"} 语句中,只传递了一个参数。如果MyServic.java ?

processService(String arg) 改写为 ?

processService(String arg,String arg2) ?

你可以通过new Object[]{"test","test2"}传递多个参数。 ?

2 启动tomcat 后控制台出现下面警告: ?

- Unable to find required classes (javax.activation.DataHandler and javax.mail.i ?nternet.MimeMultipart). Attachment support is disabled. ?

这是因为缺少activation.jarmail.jar(本文中的实例可以忽略此警告)。 ?

activation.jar (目前版本为1.1)下载地址 ?

http://java.sun.com/products/javabeans/jaf/downloads/index.html ?

mail.jar (目前版本为1.4)下载地址 ?

http://java.sun.com/products/javamail/downloads/ ?

?

<!--[if !supportLists]-->2.? <!--[endif]-->Dynamic Proxy)动态代理

? axis_example /src 新建一MyServiceInterface.java文件,内容为: ?

import java.rmi.Remote; ?

import java.rmi.RemoteException; ?

public interface MyServiceInterface extends Remote { ?

??? public String processService(String arg) throws RemoteException; ?

}
修改axis_example /src MyServic.java文件,把类声明 ?

public class MyService ?

改为 ?

public class MyService implements MyServiceInterface ?

无需编译,拷贝MyServic.javaaxis_example/jws目录下,更改文件名为MyService.jws



客户端的开发, 更改axis_example/src/Client.java中的main方法,内容为: ?

??? public static void main(String [] args) throws Exception { ?

??????? String wsdlUrl = "http://localhost:8080/axis_example/jws/MyService.jws?wsdl"; ?

??????? String nameSpaceUri = "http://localhost:8080/axis_example/jws/MyService.jws"; ?

??????? String serviceName = "MyServiceService"; ?

??????? ServiceFactory serviceFactory = ServiceFactory.newInstance(); ?

??????? javax.xml.rpc.Service service = serviceFactory.createService(new URL(wsdlUrl),new QName(nameSpaceUri,serviceName)); ?

??????? MyServiceInterface proxy = (MyServiceInterface) ?

??????????????? service.getPort(new QName(nameSpaceUri,portName),MyServiceInterface.class); ?

??????? System.out.println("This is " + proxy.processService("Dynamic Proxy test!")); ?

}
<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

axis_example/src工程下的放入tomcat/webapps下面,启动tomcat

编译Client,运行其中的main方法,你会看到程序执行的结果。

?

Stub方式(推荐的方式)。

?

axis_example/src下新建一MyServic.java文件,内容为: ?

public class MyService { ?

??? public String processService(String arg){ ?

??????? return arg; ?

??? } ?

} ?

?

编译 MyServic.java

在新建一deploy.wsdd(可参考 axis-bin-1_4.zip /axis-1_4/samples 中的deploy.wsdd----只要保证在classpath下就可以了)文件,内容为: ?

<deployment xmlns="http://xml.apache.org/axis/wsdd/" ?

??????????? xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"> ?

?<service name=" MyService" provider="java:RPC"> ?

? <parameter name="className" value=" com.cjl.test.MyService"/> ?

? <parameter name="allowedMethods" value="processService"/> ?

?</service> ?

</deployment> ?

?

启动tomcat

采用这种方式,先要保证axis所需要的jar在你的环境的classpath下。我是采用把所有的jarclasspath = D:/eCustoms/j2sdk1.4.2_07/lib;D:/Alex/workspace/mywebservice/WebRoot/WEB-INF/lib/activation.jar;D:/Alex/workspace/mywebservice/WebRoot/WEB-INF/lib/axis.jar;axis-ant.jar;D:/Alex/workspace/mywebservice/WebRoot/WEB-INF/lib/commons-discovery-0.2.jar;D:/Alex/workspace/mywebservice/WebRoot/WEB-INF/lib/jaxrpc.jar;D:/Alex/workspace/mywebservice/WebRoot/WEB-INF/lib/saaj.jar;D:/Alex/workspace/mywebservice/WebRoot/WEB-INF/lib/tools.jar;D:/Alex/workspace/mywebservice/WebRoot/WEB-INF/lib/wsdl4j-1.5.1.jar;D:/Alex/workspace/mywebservice/WebRoot/WEB-INF/lib/commons-logging-1.0.4.jar

axis_example/WEB-INF目录下执行:

java -Djava.ext.dirs=lib org.apache.axis.client.AdminClient -lhttp://localhost:8080/axis_example/servlet/AxisServlet deploy.wsdd

执行后可看到在axis_example/WEB-INF目录下生成server-config.wsdd文件。

?

从文件名称上就能看到大概的意思,是一个配置文件,这个文件就是一个Webservice工程的核心。

?

启动tomcatAxis框架会自动加载这个server-config.wsdd文件(相当于struts-config.xml,假如你使用struts框架),然后你就可以通过在浏览器的地址栏输入:

http://localhost:8080/axis_example/services/MyService?wsdl,

?

假如能看到xml文件了,表示这个Webservice的服务器已经部署完成,可以接受它的客户端的访问咯。

你可以编写客户端程序来访问这个Webservice了。

String endpoint = "http://localhost:8080/mywebservice/services/MyService";?

??????? // 创建一个服务(service)调用(call)?

??????? Service service = new Service();?

??????? Call call = (Call) service.createCall();通过service创建call对象?

??????? 设置所在URL?

??????? call.setTargetEndpointAddress(new java.net.URL(endpoint));?

??????? 方法名(processService)MyService.java方法名保持一致?

??????

?

??????? call.setOperationName("processService");?

??????? // Object 数组封装了参数,参数为"This is Test!",processService(String arg)?

??????? String ret = (String) call.invoke(new Object[]{"This is Test!"});?

??????? System.out.println(ret);?

假如你的service传递的方法是用户自定义的对象类型的话,需要增加一个映射配置

1.客户端程序里。

QName qn = new QName(endpoint,"MessageInfo");

?????? call.registerTypeMapping(MessageInfo.class,qn,

?????????? new BeanSerializerFactory(MessageInfo.class,qn),

?????????? new BeanDeserializerFactory(MessageInfo.class,qn));

?

2 服务器端:

修改Service-config.wsdd文件:

<service name="MyService" provider="java:RPC">

? <parameter name="allowedMethods" value="processService"/>

? <parameter name="className" value="com.eci.ciq.webservice.test.MyService"/>

? <typeMapping deserializer="org.apache.axis.encoding.ser.BeanDeserializerFactory" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" qname="ns1:MessageInfo" serializer="org.apache.axis.encoding.ser.BeanSerializerFactory" type="java:com.eci.ciq.webservice.test.MessageInfo" xmlns:ns1="urn:MyService"/>

?</service>

表色加粗的部分就是添加项。

那样就可以。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读