关于webService,个人觉得这篇文章:http://www.cnblogs.com/zernyree/archive/2009/05/27/1491179.html,讲得比较易懂,简单看看可以帮助理解=》推荐;
在前面我曾经写过使用.net编写webService的文章,简单的介绍.net的webservice编程和使用jquery调用的示例;由于从毕业到现在使用过最多的技术就是java、js;前段时间也使用过java来编程webService的调用端;我一直以来都认为一个技术,只有当你能够跟别很清晰的说出来并且能够熟练的去运用才能叫掌握了,下面就java编写webService的写篇文章,作为自己学习java的webService的一个笔记;
无论学习什么框架还是技术,个人始终首先要知道它是怎么用然后在去学习其原理,例如:我们学习骑自行车,首要的目地就是要学懂怎么骑,然后才追问原理~~~;学习webService的也是一样;
就目前我所知道的而言,主要的java webservice框架有axis2、cxf和xfire;至于他们各自的优劣,我目前也还不是很了解;
好,现在使用我最熟悉的xfire来编写下我们的demo:
第一:我们使用的ide为MyEclipse,在MyEclipse下建立一个Web Project,并且建立名为:com.test.service的jar包,如图:
建立名称为:CalculatorService的接口java文件;
CalculatorService接口:
package com.test.service; public interface CalculatorService { public int add(int a,int b); public int subtract(int a,int b); public int multiply(int a,int b); public int divide(int a,int b); }
第二步:
建立com.test.service.impl包,并且在这个包下面建立一个名为:CalculatorServiceImpl的实现类:
package com.test.service.impl; import com.test.service.CalculatorService; public class CalculatorServiceImpl implements CalculatorService{ public int add(int a, int b) { return a + b; } public int divide(int a, int b) { return a - b; } public int multiply(int a, int b) { return a * b; } public int subtract(int a, int b) { return a / b; } }
第三步:通过配置文件,将上面的代码纳入xfire的管辖范围内,
web.xml:
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <servlet> <servlet-name>XFireServlet</servlet-name> <servlet-class> org.codehaus.xfire.transport.http.XFireConfigurableServlet </servlet-class> </servlet> <servlet-mapping> <servlet-name>XFireServlet</servlet-name> <url-pattern>/servlet/XFireServlet/*</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>XFireServlet</servlet-name> <url-pattern>/services/*</url-pattern> </servlet-mapping> </web-app>
这里值得提到的一点就是,这些配置是可以再xfire的example里面是可以找到的,我们没有必要去记忆。
第四步:在src目录下建立如下的文件结构:
services.xml:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://xfire.codehaus.org/config/1.0"> <service> <name>CalculatorService</name> <serviceClass>com.test.service.CalculatorService</serviceClass> <implementationClass>com.test.service.impl.CalculatorServiceImpl</implementationClass> </service> </beans>
第五步:把xfire相关的jar放到lib目录下面(PS:可以直接抄example里面的过来)
第六步:把应用部署到tomcat下,访问:
http://localhost:8080/myxfire/services
到此,webservice创建成功;
现在我们在java里面编写客户端去调用,这里要使用到xfire的api,
调用端代码:
package com.test.client; import java.net.MalformedURLException; import org.codehaus.xfire.XFireFactory; import org.codehaus.xfire.client.XFireProxyFactory; import org.codehaus.xfire.service.Service; import org.codehaus.xfire.service.binding.ObjectServiceFactory; import com.test.service.CalculatorService; public class Client { public static void main(String[] args){ Service service = new ObjectServiceFactory().create(CalculatorService.class); XFireProxyFactory factory = new XFireProxyFactory(XFireFactory.newInstance().getXFire()); String url = "http://192.168.1.101:8080/myxfire/services/CalculatorService"; try { CalculatorService cs = (CalculatorService) factory.create(service,url); int addResult = cs.add(1, 2); int subtractResult = cs.subtract(1, 2); int multiplyResult = cs.multiply(1, 2); int divideResult = cs.divide(1, 2); System.out.println(addResult); System.out.println(subtractResult); System.out.println(multiplyResult); System.out.println(divideResult); } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
调用效果:
--------------------------------------------------------------------------------------------------------------------------------
使用.net调用,-----》
第一步:新建一个控制台应用名为wsclient:
第二步,增加服务引用:
=》添加Web引用
然后添加web应用=>这样在.net调用端就自动生成桩,
看这是生成的本地桩如图:
编写调用Program.cs,代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using wsclient.CalculatorService; namespace wsclient { class Program { static void Main(string[] args) { CalculatorService.CalculatorService service = new CalculatorService.CalculatorService(); int addResult = service.add(1,3); Console.WriteLine(addResult); Console.ReadKey(); } } }
然后debug,好结果出来了,如图:
----------------------------------------------------------------------------------------------------------------------------------
上面这个调用端是与服务端代码放到同一个工程下面的,而实际的使用中我们不可能这样,所以我们下面要做的就是将服务器端和调用端相互分离开来,
在另外一个java工程里面调用,-----》
第一步:新建一个java项目,命名为xfire_client,
java里面也是要生成相应的桩,不过我们可以使用一些自动化构建工具来帮助我们来完成,这个例子中我们使用Ant;
第二步:新建build.xml文件:
<?xml version="1.0" encoding="UTF-8"?> <project name="WebService" basedir="." default="gen-webservice"> <property file="build.properties"> </property> <path id="project-classpath"> <fileset dir="${lib.dir}"> <include name="**/*.jar" /> </fileset> </path> <target name="gen-webservice"> <taskdef name="wsgen" classname="org.codehaus.xfire.gen.WsGenTask" classpathref="project-classpath" /> <wsgen outputDirectory="${src.dir}" wsdl="${wsdl.dir}" package="org.langsin.ws.client" overwrite="true"/> </target> </project>
第三步:建立build.properties
然后Ant运行build.xml:
src.dir=${basedir}/src lib.dir=C:/xfire-1.2.6/lib wsdl.dir=http://localhost:8080/myxfire/services/CalculatorService?wsdl
就会生成远程服务器端的方法在客户端的桩:
如图:
在生成的包org.langsin.ws.client下面建一个测试类来试验下:
package org.langsin.ws.client; public class Test { public static void main(String[] args){ CalculatorServiceClient client = new CalculatorServiceClient(); CalculatorServicePortType PortType = (CalculatorServicePortType) client.getCalculatorServiceHttpPort(); int addResult = PortType.add(1,2); System.out.println(addResult); } }
运行效果如下:
//输出:3
使用tcpmon来截取
原理其实很简单:就是用tcpmon来做中间键然后将请求转发出去
-------------------------------------------------------------------------------------------------------------------------------------------------
使用js去调用(ps:还没找到使用参数调用的方式,先用个HelloWorld函数演示下)
因为WebService是遵守SOAP协议的,网上例子都是JSON格式的参数传递,而net WebService兼容JSON格式,而Java的是标准WebService,不兼容JSON。
所以要用js去调用java的webService就要对wsdl相关的知识要有一定的了解;
下面还是以原来的程序为例子,不过就要添加一个方法了,相关的修改如下:
修改后的CalculatorServiceImpl的实现类:
package com.test.service.impl; import com.test.service.CalculatorService; public class CalculatorServiceImpl implements CalculatorService{ public String sayHelloWorld() { return "hello "; } public String sayHelloWorld(String name) { return "hello "; } public int add(int a, int b) { return a + b; } public int divide(int a, int b) { return a - b; } public int multiply(int a, int b) { return a * b; } public int subtract(int a, int b) { return a / b; } }
修改后的CalculatorService接口:
package com.test.service; public interface CalculatorService { public String sayHelloWorld(); public String sayHelloWorld(String name); public int add(int a,int b); public int subtract(int a,int b); public int multiply(int a,int b); public int divide(int a,int b); }
添加index.jsp文件:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>My JSP 'index.jsp' starting page</title> </head> <body> <input type="text" id="txtName" /><br/> <input type="button" id="btnWs" value="WebService"> <div id="result"></div> </body> <script type="text/javascript" src="js/jquery-1.2.6.min.js"></script> <script type="text/javascript" src="js/myjs.js"></script> </html>
js/myjs.js文件:
$(function () { $("#btnWs").click(btnAjaxPost); }); function btnAjaxPost(event) { $.ajax({ type: "POST", contentType:"text/xml", //url:"/WebServiceTest/services/HelloWorldService", url:"http://localhost:8080/myxfire/services/CalculatorService", data:getPostData(),//这里不该用JSON格式 dataType:'xml',//这里设成XML或者不设。设成JSON格式会让返回值变成NULL success: function(xml) { //对结果做XML解析。 //浏览器判断 (IE和非IE完全不同) if($.browser.msie){ $("#result").append(xml.getElementsByTagName("ns1:out")[0].childNodes[0].nodeValue+"<br/>"); } else{ $(xml).find("out").each(function(){ $("#result").append($(this).text()+"<br/>"); }) } }, error: function(x, e) { alert('error:'+x.responseText); }, complete: function(x) { //alert('complete:'+x.responseText); } }); } //定义满足SOAP协议的参数。 function getPostData() { //根据WSDL分析sayHelloWorld是方法名,parameters是传入参数名 var postdata="<?xml version=\"1.0\" encoding=\"utf-8\"?>"; postdata+="<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"; postdata+="<soap:Body><sayHelloWorld xmlns=\"http://tempuri.org/\">"; //postdata+="<parameters>"+$("#txtName").val()+"</parameters>"; //postdata+="<name>"+$("#txtName").val()+"</name>"; postdata+="</sayHelloWorld></soap:Body>"; postdata+="</soap:Envelope>"; return postdata; }
-------------------------------------------------------------------------------------------------------
需要参数的js调用方式目前还没找到,尚待研究。--------super-d2
--------------------------------------------------------------------------------------
经历了一番努力js使用参数去调用webService的方法了
js/myjs.js文件修改:
$(function () { $("#btnWs").click(btnAjaxPost); }); function btnAjaxPost(event) { $.ajax({ type: "POST", contentType:"text/xml", //url:"/WebServiceTest/services/HelloWorldService", url:"http://localhost:8080/myxfire/services/CalculatorService", data:getPostData(),//这里不该用JSON格式 dataType:'xml',//这里设成XML或者不设。设成JSON格式会让返回值变成NULL success: function(xml) { //对结果做XML解析。 //浏览器判断 (IE和非IE完全不同) if($.browser.msie){ $("#result").append(xml.getElementsByTagName("ns1:out")[0].childNodes[0].nodeValue+"<br/>"); } else{ $(xml).find("out").each(function(){ $("#result").append($(this).text()+"<br/>"); }) } }, error: function(x, e) { alert('error:'+x.responseText); }, complete: function(x) { //alert('complete:'+x.responseText); } }); } //定义满足SOAP协议的参数。 function getPostData() { //根据WSDL分析sayHelloWorld是方法名,parameters是传入参数名 var postdata = "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"><soap:Body><ns1:add xmlns:ns1=\"http://service.test.com\"><ns1:in0>1</ns1:in0><ns1:in1>2</ns1:in1></ns1:add></soap:Body></soap:Envelope>" return postdata; }
可能有些人会奇怪这些xml的数据格式,其实我就是用tcpmon来截取的,不过真正开发是怎么处理这种问题,抱歉暂时还没研究得出来。
跑起来的结果:
//3
//3
//3
----------------------------------------------------------------------------------------
关于压力测试,因为webService毕竟不像jsp那样,它的效率相对来说要差一些,因为它本身有一个请求:xml=》java代码;响应:java=》xml的转化过程。
相关的压力测试工具其实有很多,如Jmeter(分布式压力测试工具)就是其中的一个。原理其实也是很简单,就是模仿多个用户然后发出多个请求。