`
Virgo_S
  • 浏览: 1153926 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Server Java开发--Born for SOA系列 整理中。。。

阅读更多
Server Java开发--Born for SOA系列 前言
      在这一章里面,我们将用大量的篇幅,阐述ArcGIS Server对SOA的支持,我们在这里所指的SOA,是基于Web Serivces的SOA,其他架构的SOA不在我们这个系列的讨论之列。本章内容包括Web Service基础;如何在J2EE下环境下构建和部署Web Service;如何使用ArcGIS Server 构建 Web Service;如何在SOA系统中利用这些Web Service等。最后会以一个实际的例子为例,如何在利用ArcGIS Server编写Web Service,并且部署到SOA环境中,解决实际中的问题。本章所有的例子都是基于JDK 1.5,AXIS2,ArcGIS Server 9.2 JAVA ADF开发。本章也是CJ编写的ESRI内部教材Server Java开发教程的第十五章。

Server Java开发--Born for SOA系列 Web Service基础
Web Service是描述一些操作(利用标准化的 XML 消息传递机制可以通过网络访问这些操作)的接口。Web 服务是用标准的、规范的XML 概念描述的,称为 Web 服务的服务描述。这一描述囊括了与服务交互需要的全部细节,包括消息格式(详细描述操作)、传输协议和位置。该接口隐藏了实现服务的细节,允许独立于实现服务基于的硬件或软件平台和编写服务所用的编程语言使用服务。这允许并支持基于 Web 服务的应用程序成为松散耦合、面向组件和跨技术实现。Web 服务执行一项特定的任务或一组任务。Web 服务可以单独或同其它 Web服务一起用于实现复杂的功能或商业交易。

听起来很复杂,但是我们用一个简单的例子加以说明。这个例子跟GIS无关,但是可以帮助大家了解在J2EE环境中,整个Web Service的编写,部署过程。并且如何在.Net环境和Java环境中调用这个Web Service。

以下的需求来自于一个我原来导师的项目,这虽然不是一个典型的WebService充满前景的一个例子,但是确实用web service来解决问题的一个好的开始。项目的背景是要帮用户部署多个网站,为了节约成本,两个网站都是使用租用的空间,结果有一个租用的Linux操作系统的空间没有安装XWindows,导致一个使用JAVA写的图像缩放程序无法执行,当然,没有Xwindows,基本上需要访问AWT包的程序都会无法执行。怎么解决呢,刚好另外一台服务器上有Xwindows,可以使用这个功能,所以我们可以在另外一台服务器上编写一个WebService,发送一个图像Resize请求,请求参数是被需要被Resize的图片的URL,以及Resize的比例,而返回的结果是Resize后的图像。压缩图像的代码如下所示:
package edu.zju;

import java.awt.image.BufferedImage;

import java.io.FileOutputStream;

import java.io.InputStream;

import java.net.URL;

import javax.imageio.ImageIO;

import com.sun.image.codec.jpeg.JPEGCodec;

import com.sun.image.codec.jpeg.JPEGImageEncoder;

/**

* 

* @author CJ

*

*/

public class CompressLocal {

publicCompressLocal() {

super();

}

/**

* 

* @param filename 要被缩放的文件名,如果是URL,请设置isURL为true

* @param newname 缩放后的新的文件名

* @param std_img_w 目标文件的宽度

* @param std_img_h 目标文件的高度

* @param stretch 是否拉伸,如果1,则按照参数比例,如果是2,则按照宽度的比例;如果3,则取小的那个比例尺

* @param isURL 是否是URL

*/

public void doScaleOnImage(String filename,String newname,int std_img_w,intstd_img_h,int stretch,boolean isURL) 

{

BufferedImageoldimage=null;

try{

intnew_w=-1;int new_h=-1;

if(isURL){

InputStreamin=(new URL(filename)).openStream();

oldimage= ImageIO.read(in);

in.close();

}else{

oldimage = javax.imageio.ImageIO.read(newjava.io.File(filename));

}

intold_w = oldimage.getWidth(null); //原图像的宽度

intold_h = oldimage.getHeight(null);//原图像的高度

if(stretch==1){

new_w=std_img_w;

new_h=std_img_h;

}elseif(stretch==2){

if((old_w > std_img_w) || (old_h > std_img_h)) {

doubletagSize = (double)old_w / std_img_w; // 按宽度比例确定缩放比例

new_w= (int)(old_w / tagSize); //得到一个新的比例

new_h= (int)(old_h / tagSize);

}

}

else if(stretch==3){

new_w= old_w;

new_h = old_h;

if((old_w > std_img_w) || (old_h > std_img_h)) { //如果原图像高度和宽度都大于目标高度和宽度

floattmpdouble = std_img_w;

floattagSize = old_w / tmpdouble; // 按宽度比例确定缩放比例

tmpdouble= std_img_h;

if(tagSize < (old_h / tmpdouble)) //按高度确定缩放比例

tagSize= old_h / tmpdouble;

new_w= Math.round(old_w / tagSize); //得到一个新的比例

new_h= Math.round(old_h / tagSize);

}

}

BufferedImagetag = new BufferedImage(new_w,new_h,BufferedImage.TYPE_INT_RGB); 

tag.getGraphics().drawImage(oldimage,0,0,new_w,new_h,null);

oldimage.flush();

FileOutputStreamnewfile = new FileOutputStream(newname); 

JPEGImageEncoderencoder = JPEGCodec.createJPEGEncoder(newfile); 

encoder.encode(tag);

tag.flush();

newfile.close();

}catch (Exception e) {

e.printStackTrace();

}

}

/**

* @param args

*/

public static void main(String[] args) {

CompressLocalcl = new CompressLocal();

cl.doScaleOnImage("D:\\temp\\photo\\0016.jpg","c:\\temp\\cj.jpg", 535, 312,2,false);

}

}

缩放图片的代码已经完成,下面来写一个方法,如何调用图片缩放代码: package edu.zju;

/**

* 作为一个application scope的web service,供大家使用

* 

* @author CJ

*

*/

public class CompressWebService {

publicCompressWebService() {

super();

}

/**

* 

* @param url 源jpg文件的URL

* @param width 目标jpg文件的宽度

* @param length 目标jpg文件的高度

* @return 返回目标jpg文件的url

*/

publicString doCompress(String url,int width,int height){

StringrltURL="c:/temp/aa.jpg"; //例子程序使用,正式代码根据url生成文件名

CompressLocalcomp=new CompressLocal();

comp.doScaleOnImage(url,rltURL,width,height,1,true);

returnrltURL;

}

/**

* @param args

*/

public static void main(String[] args) {


}



}


代码编写完毕后,可以直接部署了,由于有了AXIS,部署变得非常的简单,我们使用下面的service.xml进行部署,具体的部署方法可以参考AXIS的部署文档:
<service name="CompressService"scope="application">

<description>

ScaleJPEG Service

</description>

<messageReceivers>

<messageReceiver 

mep="http://www.w3.org/2004/08/wsdl/in-only"

class="org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver"/>

<messageReceiver

mep="http://www.w3.org/2004/08/wsdl/in-out"

class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/>

</messageReceivers>

<parameter name="ServiceClass">

edu.zju.CompressWebService

</parameter>

</service>


部署完成后,可以使用下面的URL对WebService进行访问。

http://chunjie:8088/axis2/services/CompressService/doCompress?url=http://chunjie:8088/jpg/10/deans/0037.JPG&width=55&height=55

返回结果为
<ns:doCompressResponse xmlns:ns="http://zju.edu/xsd">

<ns:return>c:/temp/aa.jpg</ns:return> 

</ns:doCompressResponse>


如果访问http://chunjie:8088/axis2/services/CompressService?wsdl,可以得到描述当前WebService的wsdl文件。第一个WebService就部署完成了,是不是简单的不可思议?当然,得益于axis的伟大工作,隐藏了大量的细节,从而使工作变得如此简单。

刚才我们直接通过URL已经可以访问webservice了。但是我们一般在javacode里面访问,访问后还需要做一些其他的操作,比如马上把图片文件保存到服务器上的某个目录中。如果需要在Javacode中访问该web service,我们需要根据wsdl文件生成一个本地的Java代理类,通过这个代理类用来访问WebService的方法。Axis提供了wsdl2java的工具可以根据wsdl的描述生成java代理类,可以使用命令行的工具,或者使用Axis为Eclipse提供的工具生成代理类。生成代理后,就可以用下面的方法调用该WebService:
try {

DoCompress dc = newDoCompress();

dc.setUrl("http://chunjie:8088/jspsamples/jpg/thanks.jpg");

dc.setHeight(100);

dc.setWidth(100);

CompressWebServiceCompressWebServiceSOAP11PortStubstub = new CompressWebServiceCompressWebServiceSOAP11PortStub(

null,"http://chunjie:8088/axis2/services/CompressService");

DoCompressResponsedcr=stub.doCompress(dc);

System.out.println(dcr.get_return());

} catch (AxisFault e) {

e.printStackTrace();

} catch (RemoteException e) {

e.printStackTrace();

}



当然,我们也可以用.Net来调用这个WebService,这正是Web Service的妙处所在,在VisualStudio里面新建一个项目,然后添加Web引用,在引用地址里面填入service的URL,入下图所示:

[attach]4122[/attach]


添加引用后,就可以用下面的代码来进行访问:
consumeWS.chunjie.doCompressdc = new consumeWS.chunjie.doCompress();

dc.url = "http://chunjie:8088/jspsamples/jpg/thanks.jpg";

dc.height = 160;

dc.width = 120;

consumeWS.chunjie.CompressServicecs = new consumeWS.chunjie.CompressService();

consumeWS.chunjie.doCompressResponsedr= cs.doCompress(dc);



现在我们已经知道如何编写,部署,在JAVA和.NET中调用WebService。在下一节中,我们来看看可以通过怎样的方式对ArcGIS Server提供的WebService的进行访问。

Server Java开发--Born for SOA系列-- ADF中访问Web Services的类
事实上细心的您肯定已经发现了,在ADF的类库中,很多类在两个Package中都会有,比如我们曾经在前面的例子中提到的类:
MapDescription

在9.2以前的服务中,此类都是老老实实的呆在com.esri.arcgis.carto.MapDescription包中,但是在9.2以后,有了一个新的package,此package就是大名鼎鼎的com.esri.arcgisws。这两个类是不同之处在于:com.esri.arcgis.carto.MapDescription类是指向com的一个代理,你在创建这个类的时候,必须创建在ServerContext里面;而com.esri.arcgisws. MapDescription则是一个标准的Java类,你可以用创建普通类的方法创建一个com.esri.arcgisws.MapDescription实例。
在上面一节中已经知道,MapDescription是通过AXIS的WSDL2JAVA工具转换而来的,事实上,这个包里面所有的类都是这么来的。注意com.esri.arcgisws.MapDescription的父类是Object,创建com.esri.arcgisws. MapDescription类的时候,它在本地的JVM中运行(比如Tomcat的JVM中),所以不消耗ArcGIS Server那一端的资源,而且很容易进行调试。另外,com.esri.arcgisws. MapDescription被称为Value Object,它在向服务器发送请求前,被实例化并且设置一些值,作为参数发送到服务器端;从服务器端返回结果后,该类的属性又被设置成相应的值,从而得到服务器端返回的结果。如果想要看MapDescription的源代码,可以用AXIS根据WSDL生成一个JAVA类来查看。
跟Server进行交互的是8个特别的接口,这些接口的命名都很特殊:…port,比如com.esri.arcgisws.MapServerPort,这个接口唯一的实现类是MapServerBindingStub ,这个接口可以通过com.esri.adf.web.ags.data.AGSMapResource类得到,而AGSMapResource是adf中的类,这样也就把我们所需要的一些功能跟adf连接起来了。如果您使用的是AGSGPResource,那么对应的port就是GPServerPort。而network Analysist比较奇怪,似乎现在ESRI更愿意让我们通过Functionality来使用它,看看它将来的情况吧。所以,所有的参数的创建,设置都在本地JVM中,从服务器端返回的结果也在JVM中,只有在使用MapServerPort进行查询或者其它操作时才跟Server进行交互。所以大大减少了和Server交互的次数和时间,大大提高了性能,同样的情况下,9.2比9.1可以服务更多的用户。这也可以让我们回想起在学习分布式系统编程的时候的一个规则:一次性传输1000 bytes的数据,比传输1000次的1 byte数据又快又好。
所以,adf访问ArcGISServer的时候,推荐使用SOAP协议对Server进行访问,也就是我们提到的com.esri.arcgisws包中的类,这里arcgisws包中ws的含义就是web services。这样效率会更高,速度也会更快。可以查看下面的图,了解协议请求的关系。事实上我们ArcIMS一开始就是使用ArcXML进行数据的交互;Server现在也开始吸取ArcIMS的长处,在本地构建类后,通过SOAP协议,把XML请求发送到服务器端,如图16.3所示:


看看例子里面一个CountFeature的功能吧,在9.1下我们如果要计算某个层中选中的要素,方法是在ServerContext里面建一个,SpatialFilter,设置它的过滤要素和关系。然后对层进行query,然后再得到返回记录集的数目,完成一个空间查询并得到选中要素的过程。在9.2环境下,我们不需要在ServerContext里面建SpatialFilter,而可以使用arcgisws包里面的SpatialFitler,在本地创建空间过滤器,如下面的代码所示:
EnvelopeN env =new EnvelopeN(extent.getMinX(), extent.getMinY(), extent.getMaxX(),

extent.getMaxY(), null, null, null, null, null);

//新建一个空间过滤器

SpatialFilter spatialFilter = new SpatialFilter();

//设置空间相交关系

spatialFilter.setSpatialRel(EsriSpatialRelEnum.esriSpatialRelIntersects);

spatialFilter.setWhereClause("");

spatialFilter.setSearchOrder(EsriSearchOrder.esriSearchOrderSpatial);

spatialFilter.setSpatialRelDescription("");

spatialFilter.setGeometryFieldName("");

//设置和层相交的要素

spatialFilter.setFilterGeometry(env);

int layerId = 1;

this.countedFeatures =

mapServer.queryFeatureCount(mapServer.getDefaultMapName(), layerId,spatialFilter);  

在本地创建SpatialFitler,设置好参数,调用mapServerPort的queryFeatureCount方法,在调用这个方法的时候,SpatialFitler,layerId等参数都作为XML封装在SOAP中,发送到服务器端,查询完成后再以XML返回结果。

上面我们说到的一直是ADF这一端的对象,那么如果我们有的时候确实需要使用AO对象,怎么办呢?ESRI的JAVA开发人员事实上早就想到了这些,比如用如下的方法实现对AO对象和ADF中ws包对象中的转换:

ADF对象转向AO对象:
IGeometry igeom =(IGeometry)AGSUtil.createArcObjectFromStub(geom, serverContext);

AO对象转向ADF对象:
com.esri.arcgisws.Polygon wPoly =(com.esri.arcgisws.Polygon)AGSUtil.createStubFromArcObject(bufferedGeom,com.esri.arcgisws.Polygon.class,serverContext);


这就是我们ArcGIS Server中无处不在的Web Services,ArcGIS Server有.net版本和Java版本,事实上你完全可以用Java版本的ADF去访问.net版本Server。如果你要构建大型的SOA,也完全可以用我们server的API,去通过SOAP协议访问我们的Server。




  • 大小: 108.6 KB
分享到:
评论

相关推荐

    ArcGIS+Server+Java讲座

    1、前言------为什么我们选择JSF,而不是其它framework 1 2、ArcGIS Server Java开发 JSF基础 2 3、ArcGIS Server Java ADF开发...29、Server Java开发--Born for SOA系列 通过代理类访问ArcGIS Server Web Service 84

    arcgis server java讲座

    最后,【Born for SOA(Service-Oriented Architecture)系列】强调了ArcGIS Server对SOA的支持,讲解了如何通过WebService接口进行远程调用,以及如何利用代理类访问ArcGIS Server Web Services,这使得ArcGIS ...

    非交换Sitter-Einstein-Born-Infeld时空的热力学性质

    我们根据非交换尺度重力理论构造了一个变形的反d​​e Sitter-Einstein-Born-Infeld黑洞,并确定了非交换参数上直到二阶的度量系数。 我们分析了由于非交换作用对黑洞热力学性质的影响,并且表明非交换作用直接导致...

    相对论中的Born-Infeld电动力学

    在这项工作中,我们将在非常狭义相对论(VSR)的框架内讨论修改的Born-Infeld电动力学的性质。 该建议使我们能够在非线性电动力学的规范不变背景下研究VSR质量效应。 详细分析了两种情况下的静电解决方案,以及发现...

    用于膨胀的Born-Infeld黑洞的热机

    在带有负宇宙学常数和Born-Infeld场的Dilaton耦合... 将效率作为dilaton和Born-Infeld耦合的函数进行分析,并将结果与​​Brans-Dicke-Born-Infeld理论中相关保形解的类似计算以及anti-de Sitter时空中的黑洞相比较。

    Die-to-Born:Die to Born是一款用于JS13KB compo的桌面浏览器游戏

    在压缩包子文件"Die-to-Born-master"中,我们可以推测包含以下几个部分: 1. `index.html`:游戏的主页面,包含游戏的HTML结构和JavaScript入口点。 2. `main.js`:核心游戏逻辑,包括游戏循环、对象管理、事件处理...

    关于多场Born和Born-Infeld理论及其非阿贝尔概括

    从最近提出的关于辅助场的线性公式开始,我们研究Born和Born-Infeld理论的n场推广。 在此描述中,拉格朗日向量场强度是二次方的,并且相应的非线性理论的对称性(包括特征自对偶性)表现为壳对偶对称性,并取决于...

    相对论性离子碰撞中e + e-对生成的总Born截面从微分方程式

    在本研究中,微分方程方法被应用于计算粒子碰撞过程中e+e-对生成的总Born截面,这表明研究者需要解决一个涉及复杂动力学的问题。 5. 原子核相对速度:在相对论性离子碰撞中,碰撞前后的原子核速度是非常重要的物理...

    Java高级教程课件 java数据库教程 JDBC教程 5-java-thread(1)线程(共18页).pptx

    课程资源中包含了关于Oracle的基础知识和SQL函数,这些都是开发Java数据库应用时需要掌握的关键点。 总的来说,Java高级教程涵盖了数据库交互、多线程和网络编程等核心概念,这些知识对于成为一名全面的Java开发者...

    具有动量耗散的Born-Infeld电动力学的全息传输

    我们从Born-Infeld电动力学研究了爱因斯坦-轴距AdS黑洞。 分析计算了双边界理论的各种直流输运系数。 直流电导率取决于温度,与RN-AdS黑洞相比,这是一种新颖的特性。 分析了Born-Infeld参数对输运系数的影响。 此外...

    born-gosu-gaming:Born Gosu的事件子域支持和不一致的bot处理程序

    发展第一次&gt; ./scripts/provision.sh&gt; source /tmp/born-gosu-gaming/asdf/asdf.sh&gt; mix deps.get本地运行&gt; source /tmp/born-gosu-gaming/asdf/asdf.sh&gt; iex -S mix本地测试&gt; source /tmp/born-gosu-gaming/asdf/...

    Hero-Born-AA

    综上所述,"Hero-Born-AA"项目展示了C#在游戏或应用程序开发中的广泛用途,涵盖了从基本语法到高级特性的多个方面。通过对这些知识点的深入理解和实践,开发者可以创建出功能丰富、性能优秀的软件产品。

    超对称Dirac-Born-Infeld轴离子膨胀和非高斯性

    基于超对称狄拉克-博恩-因费尔德(DBI)作用在两性离子环境中的通货膨胀进行了分析。 我们讨论的DBI模型涉及具有一个U(1)移位对称性的手性超场,该对称性由超势中的瞬时型非扰动项打破。 移位对称性的破坏导致一个...

    Born-Infeld黑洞的全息复杂性

    在本文中,根据CA对偶性,我们研究了Born-Infeld(BI)黑洞的复杂度增长。 作为比较,我们从一开始就研究了爱因斯坦-麦克斯韦引力中重音黑洞的作用增长。 我们研究了dRGT大重力中的电BI黑洞的动作增长,发现大重力中...

    非局部观测资料探测的Born-Infeld-Anti-de Sitter黑洞的相结构

    利用两点相关函数和全息纠缠熵等非局部可观测性,我们研究了Born-Infeld-anti-de Sitter黑洞的相位结构。 对于bQ&gt; 0.5的情况,其中b是Born-Infeld参数,Q是黑洞的电荷,发现其相结构类似于Van der Waals相变,即黑洞...

    具有超重力的Dirac-Born-Infeld和新的Fayet-Iliopoulos项的大规模矢量多重峰

    我们提出了一个基于单个重矢量多重态的基于N = 1超维的Starobinsky型膨胀模型,其作用包括Dirac-Born-Infeld型动力学项和广义(新)Fayet-Iliopoulos型 项,而不衡量R对称性。 计算出玻色子作用和标量势。 充气子是...

    腔中Born-Infeld-de Sitter黑洞的临界现象

    我们发现,Born-Infeld理论的非线性导致规范集合中折返相变的存在,而折返相变的存在和性质取决于该理论的最大电场强度。 我们还检查了大正则合奏中的相结构,并演示了从辐射到中间尺寸黑洞再回到辐射的新的折返...

Global site tag (gtag.js) - Google Analytics