admin管理员组

文章数量:1533861

2024年3月4日发(作者:)

GeoServer汉化与定制开发方法介绍

一、GeoServer简介

GeoServer 是 OpenGIS Web 服务器规范的 J2EE 实现,利用 GeoServer 可以方便的发布地图数据,允许用户对特征数据进行更新、删除、插入操作,通过 GeoServer 可以比较容易的在用户之间迅速共享空间地理信息。

GeoServer 主要特性包括:兼容 WMS 和 WFS 特性;支持 PostGIS 、 Shapefile 、

ArcSDE 、 Oracle 、 VPF 、 MySQL 、 MapInfo ;支持上百种投影;能够将网络地图输出为 jpeg 、 gif 、 png 、 SVG 、 KML 等格式;能够运行在任何基于 J2EE/Servlet 容器之上;嵌入 MapBuilder 支持 AJAX 的地图客户端;除此之外还包括许多其他的特性。

GeoServer 最新的版本增加了 GeoTools 2.x , GeoTools 是一款基于 Java 的开源 GIS

工具集,允许用户对地理数据进行基本操作。通过 GeoTools 的各种接口和 helper 类,可以写入新的数据格式,通过 GeoTools 为 GeoServer 提供的插件,在不进行重新编译的情况下,可以让 GeoServer 支持更多的数据格式,甚至只需要通过 GUI 的 option 设置即可。

GeoServer能够发布的数据类型:

地图或影象——应用WMS,

实时数据——应用WFS,

用户更新、删除和编辑的数据——应用WFS-T。

相关概念的:

WMS: Web Map Service(Web地图服务 )

l 利用具有地理空间位置信息的数据制作地图。其中将地图定义为地理数据可视的表现。这个规范定义了三个操作:

GetCapabitities 返回服务级元数据,它是对服务信息内容和要求参数的一种描述;

GetMap 返回一个地图影像,其地理空间参考和大小参数是明确定义了的;

GetFeatureInfo(可选)返回显示在地图上的某些特殊要素的信息

WFS: Web Feature Service(Web要素服务)

Web 地图服务返回的是图层级的地图影像, Web要素服务(WFS)返回的是要素级的GML编码,并提供对要素的增加、修改、删除等事务操作,是对Web地图服务的进一步深入。OGC Web要素服务允许客户端从多个Web要素服务中取得使用地理标记语言(GML)编码的地理空间数据,定义了五个操作:

GetCapabilites 返回Web要素服务性能描述文档(用XML描述);

DescribeFeatureType 返回描述可以提供服务的任何要素 结构的XML文档;

GetFeature 一个获取要素实例的请求提供服务;

Transaction 为事务请求提供服务;

LockFeature 处理在一个事务期间对一个或多个要素类型实例上锁的请求。

WFS-T: Web Map Service-Transactional. 允许用户以可传输的块编辑地理数据。

WCS:Web Coverage Service(Web覆盖服务)

Web 覆盖服务(WCS)面向空间影像数据,它将包含地理位置值的地理空间数据作为“覆盖(Coverage)”在网上相互交换。

网络覆盖服务由三种操作组成:GetCapabilities,GetCoverage和DescribeCoverageType:

GetCapabilities 操作返回描述服务 和数据集的XML文档。

GetCoverage操作是在GetCapabilities确定什么样的查询可以执行、什么样的数据能够获取之后执行的,它使用通用的覆盖格式返回地理位置的值或属性。

DescribeCoverageType 操作允许客户端请求由具体的WCS服务器提供的任一覆盖层的完全描述。

GML: Geography Markup Language. 一种用于描述地理数据的XML。

OGC——Open Geospatial Consortium——开放地理信息联盟

总之 , GeoServer 是您需要显示地图在网页的那些工具的当中一个,用户可以缩放并且移动。可以与一些客户端联合使用,比如: MapBuilder (for web pages), UDig, GVSig,等等。 对标准的使用允许信息从GeoServer 到其它地理信息可以很容易地被结合

二、GeoServer的汉化

GeoServer的汉化实际上是软件国际化与本地化的一个具体实例。

GeoServer提供了J2EE架构下标准的国际化方法支持,即采用“地区_语言”资源方式实现对全球各个地区和语言语种的支持,当然,汉语也被包含其中。

要实现GeoServer的汉化,有如下几个途径:

1、局部汉化

编制一组中国大陆地区和简体中文资源文件,增加到GeoServer的发布包*.jar中去;

这种汉化方式能汉化绝大部分内容,但由于开源软件存在的固有问题,并不是所有需要国际化的资源都被资源化了,因此,还有一小部分内容不能通过这种方式国际化;如果对汉化要求不高,可以采用这种方式。

2、彻底汉化

下载GeoServer的源代码,自己构建工程并编译成果,在第一部的基础上,对未能国际化的部分,将相应的字符串资源化,并将新资源化的字符串添加到编制的那组中国大陆地区和简体中文资源文件中。有兴趣或疑问的朋友可以一起讨论

注意,要彻底汉化,必须的代码包括三大部分:

(1)GeoServer工程自身的代码;

(2)GeoServer的GIS内核及扩展GeoTools的代码;

(3)GeoServer的WEB框架(Apache Wicket)的代码;

三、GeoServer定制开发入门

如果希望对GeoServer进行定制开发,首先需要获取GeoServer的代码。

代码可以在 /geoserver 下载。

另外,你还需要Apache的build工具maven,这里特别需要注意的是geoserver与maven版本的对应性。在GeoServer Developer Manual文档中有特定说明。

最后就是需要一个支持j2ee开发的集成开发环境,这里推荐eclipse。

使用eclipse加载geoserver全部工程代码后,可以看到其工程结构如下图所示,先赞一下,架构还是非常不错的。

如果需要定制开发,我们主要是要扩展和定制ows、web-core两个工程即可。当然,根据个人喜好,也可以把某些内容的修改提炼到main中去。

至于如何在eclipse中对ows、web-core进行扩展和定制,有兴趣的朋友也可以一起讨论。

四、GeoServer定制开发的深入——完整的WMS访问过程

如果希望深入的进行定制开发,必须首先理解Geoserver自身的概念体系和框架结构,下面我们就慢慢来介绍。

一、HTTP GET请求

WMS的请求一般使用HTTP Get的形式直接从地址栏输入或者通过JS代码发送到服务器端。请求的格式如下所示:

localhost:8080/geoserver

/wms?bbox=-74.61,40.73,-74.95,40.752&styles=&Format=application/openlayers&request=GetMap&version=1.1.1&layers=tiger:poi&width=457&height=550&srs=EPSG:4326,该请求中wms是要请求的服务,version=1.1.1是请求的wms版本,GetMap是请求的服务方法,tiger:poi是要访问的地理数据。

二、HTTP 派发

GeoServer的MVC架构是建立在Spring的Web MVC的基础之上的。Spring Web MVC的核心控制类是cherServlet。HTTP请求一般都先发送给这个Servlet,做一些HTTP请求的通用处理(比如文件上载)后,通过合适的派发机制转发给不同的Spring容器中的Bean,也就是不同业务逻辑、服务处理的控制器(Logic Control),由这些控制器结合不同模型(Model),如空间数据模型、属性数据模型、地图样式模型等,进行处理,形成结果模型,并经 DispatcherServlet返回客户端。

cherServlet相关配置位于GeoServer的Web工程的配置文件中。

1、Servlet声明

dispatcher

cherServlet

2、URL Mapping

dispatcher

/wms/*

dispatcher

/wcs/*

dispatcher

/wfs/*

dispatcher

/ows/*

这说明,对于/wms/*、/wcs/*、/wfs/*、/ows/*等地址的请求,都会调用cherServlet对象来响应。

三、cherServlet派发流程

在Spring框架下,cherServlet基于每个工程的的配置,将请求转发给专门的对象处理。其中,根据wms工程的配置,wms除putstyles路径下的请求,都由dispatcher处理。

class="UrlHandlerMapping">

dispatcher

putStylesWrapper

dispatcher

关于dispatcher对象的配置在main工程的,处理对象的类是cher。

cher继承自spring框架的AbstractController类。它对于HTTP请求的处理是在handleRequestInternal(HttpServletRequest httpRequest, HttpServletResponse

httpResponse)中处理。此函数再调用本身的execute(Request req, Operation opDescriptor),先分析出请求的服务(Service)、版本(Version)、操作(Operation),然后根据配置信息与GeoServerExtensions匹配找到服务处理的Bean,wms的配置信息如下所示。

此配置信息说明对于服务ID为wms的操作,由tWebMapService来使用与操作同名的函数来处理。

这样,对于下面的请求:

localhost:8080/geoserver

/wms?bbox=-74.61,40.73,-74.95,40.752&styles=&Format=application/openlayers&request=GetMap&version=1.1.1&layers=tiger:poi&width=457&height=550&srs=EPSG:4326

将由tWebMapService的getMap函数来处理。

四、tWebMapService的getMap函数处理过程

此函数先根据配置信息得到。

class=""

parent="wmsService">

对象,所属类是然后执行此对象的getResponse()方法。然后创建一个GetMapResponse对象。

五、写输出

写输出是通过执行cher的void response(Object result, Request req,

Operation opDescriptor)函数。此函数先循环搜索和排序响应类集合responses(List responses

= ions();),确定响应类response (Response response

= (Response) (0);),再根据输出策略outputStrategy(ServiceStrategy

outputStrategy = findOutputStrategy(sponse);)进行输出。

具体执行在set the mime type时(tentType(eType(result, opDescriptor));)调用ResponseAdapter的getMimeType(Object value, Operation operation)函数,此函数再调用e(request)来执行(delegate即第四步创建的GetMapResponse对象)。最终的执行在GetMapResponse对象的execute(Request req)函数。

四、GeoServer定制开发的深入——感性的应用实例

由于GeoServer只支持发布ArcGIS格式的地图数据,既.shp格式的地图数据。如果是别的厂商提供的地图数据则需要进行一次地图数据格式转化。本篇主要介绍如何查看、编辑地图数据的应用。

一、地图数据转为shp数据格式

由于GeoServer只支持发布ArcGIS格式的地图数据,既.shp格式的地图数据。在使用GeoServer部署地图数据之前则需要针对不同地图厂商提供的地图数据进行数据格式转化。比如说将MapInfo地图数据转为ArcGIS的shp格式地图数据,需要使用MapInfo提供的工具进行装换。操作非常简单,这里不做详细介绍。

二、使用uDig编辑SHP格式数据

首先使用uDig打开shp格式地图文件,支持同时打开多个shp格式地图数据文件。打开单个地图数据文件则以地图数据文件的地图风格呈现出来,如果是打开多个地图数据文件则是以按照地理坐标确定图层位置的图层重叠呈现。

在打开的shp格式地图数据文件后,通过uDig的图层面板就可以查看当所选择的shp地图数据文件中所包含的地图图层信息,当选中某个图层后就可以通过Table面板查看到该图层所对应的一些详细数据信息。如下图所示:

通过uDig工具可以对地图数据进行查看,编辑,是地图数据部署中对地图数据进行纠错处理不可缺少的一个工具,很给力的一个工具。

三、从uDig导出SHP格式数据样式

uDig提供了非常强大的地图数据编辑功能,实际上应用最多的就是使用uDig编辑shp格式的地图数据,从中提起样式文件。目的其实很简单就是为了修改编码,通常默认的文字编码发布出的WMS服务呈现出来的地图标签中午是乱码。通过图层的“Change Style”功能选项就可以进入图层的样式编辑器。

通过可视化编辑器将修改后的样式导出为样式文件(.sld),在发布地图数据的时候就可以使用编辑后的样式到对应的地图图层,从而解决中文标签乱码问题。

本篇文章正式介绍基于GeoServer的地图数据部署实现,前提条件为成功搭建有GeoServer环境。实际上基于GeoServer部署shp格式的地图数据非常简单,对于GeoServer对于的磁盘物理层主要就是一个地图数据目录的概念,对于GeoServer应用系统来说则有三大重要知识点,分别为:工作空间(workspace)、存储器(store)和地图图层(layer),这些概念的详细都将在本文中逐一的介绍。

一、GeoServer地图数据目录(Data Directory)

所谓地图数据目录既地图数据的存放目录,在《GeoServer地图数据部署解决方案(一):环境搭建篇》中介绍环境搭建的时候就提到过地图数据目录这个概念,安装GeoServer的时候就已经指定了地图数据目录的位置。

部署地图数据非常简单,首先需要将地图数据文件(shp地图数据文件)复制到GeoServer的数据目录(安装GeoServer的时候所指定的地图数据目录)下面,因为只有将地图数据放到此目录下,GeoServer后台才能发现shp的地图数据文件(建议使用英文命名地图数据文件)。

需要部署的地图数据必须放置在上面GeoServer提供的地图数据目录之下,如下图示就是将待部署发布的shp格式地图数据放在在GeoServer地图数据目录下名为“t_shapes”的目录中的。这里的“t_shapes”需要特别注意,在使用GeoServer进行地图数据部署发布的时候(创建存储器)需要使用到此名字(t_shapes)。

最新版(版本号:2.0.2)的GeoServer全面改善了shp格式地图数据的发布,并增加了OpenLayers方式的地图数据发布预览功能,以及将地图数据导出KML或GML等格式数据。下面将详细介绍这些功能点。

二、工作空间(workspace)

最新版的GeoServer里面修改了老版本的“目录”为“工作空间”,工作空间存放着多个数据存储器。成功登陆GeoServer管理系统后就可以从左边的功能导航处看到“工作空间”选项。工作空间管理平台详细如下图所示:

要发布地图数据为WMS服务,首先得建立工作空间(也可以使用现有的工作空间),然后建立数据存储器,最后在存储器里面发布地图数据。要想创建工作空间可以直接通过管理平台界面的“Add new workspace”进入工作空间创建界面,如下图所示:

编辑工作空间和创建工作空间一样,非常的简单,可以直接从工作空间管理列表界面进入工作空间编辑界面。

三、存储器(store)

基于工作空间只上的存储器,维护着和地图数据目录的映射关系。可以直接通过GeoServer左边的功能导航进入存储器管理界面,如下图所示:

如上图所示,在存储器管理界面中点击“Add new Store”就可以导航到创建存储器界面,可以完成存储器到地图数据目录的映射,为后面发布地图图层做准备。如下图所示:

通常我们使用的是“Directory of Spatial files”,也就是以目录为单位进行shp格式地图数据的部署。下图为添加存储器的界面:

按照GeoServer的约定一个数据存储器可以部署一个独立的shp格式地图数据文件,也可以部署一个目录的shp格式地图数据格式。

需要特别注意就是“URL”,这里指向的就是存放需要部署的地图数据的目录,此地址的格式为:“file:” + “GeoServer的地图数据目录”,比如说地图数据放在C:Program

FilesGeoServer 2.0.2data_dirdatat_shapes 下,那么在建立存储器的时候的URL应该为file:data/t_shapes 。最终的配置如下图所示:

四、地图图层(layer)

地图图层主要就是管理部署在GeoServer里面的地图数据中的图层元素,通过地图图层管理列表可以非常清楚的看到地图图层的类型、所属工作空间、所属存储器、图层名称以及采用的SRS标准等相关信息。

通过图层管理界面的“Add a new resource”可以进入图层类型(工作空间:存储器)选择界面,详细如下图:

地图数据存储器管理维护着与地图数据目录对应的地图图层数据,选择了对应的图层存储器类型,就会列表处该图层类型下面的所有图层元素,如下列表所示:

使用图层列表管理维护着地图数据图层的发布,图上图所示成功发布地图数据图层为地图服务的前面有“V”标记,如果要修改已发布的地图图层可以使用再次发布功能完成。

基于工作空间的数据存储器管理的地图图层,还提到可在图层列表中发布地图图层为WMS服务,对于已经发布过的地图数据还可以进行修改发布。

从上图上可以看到每个图层有“Published”属性,表示当前图层是否发布,其后还有操作连接“Publish again”或“Publish”,表示对以及发布的图层进行再次发布,或者对没有发布的图层进行发布。

要发布地图图层可以在图层列表中点击“Publish”进入图层发布界面,这里需要注意的就是在进行图层发布的时候有几个必填的参数,分别为Declared SRS、Bounding Boxes等。Declared SRS表示当前发布的地图图层将采用何种地理空间引用标准,这里通常都是使用的EPSG:4326标准;Bounding Boxes表示当前图层的经度、纬度范围,这两项值可以直接通过GeoServer提供的工具自动获取到。详细如下图所示:

二、发布地图样式

之所以要应用样式,主要是解决中文编码的问题以及某些地图数据需要做特别的处理,通常可以修改样式文件实现,这里大多数的图层使用默认的样式基本不会有问题,某些图层使用默认的样式却不能正确的发布为WMS服务,就需要使用前面所介绍的通过uDig对地图数据的样式进行编辑并导出样式文件(.sld),然后再GeoServer中发布新的样式,并在图层发布或者是编辑图层的时候就使用自己发布的样式。

通过样式列表界面的“Add a new style”就可进入下面的样式发布界面。如下图所示:

三、应用地图样式

应用地图样式非常简单,在添加地图图层或者编辑地图图层的时候,通过“Default

style”功能选项进行地图图层的样式设置。详细如下图所示:

四、预览地图图层

通过GeoServer管理台左边功能导航“Layer Preview”可进入图层阅览列表,在此列表中部分类型地图图层还提供导出为KML和GML格式的地图数据。

从上图所示中点击图层所对应的“OpenLayers”就可以打开所对应地图图层的预览界面,上图图层列表的地图图层是为了测试而部署的,比如需要查看重庆大区界地图图层,那么可以直接预览大区边界地图图层就可以了,也就是上图中的名为“cq:dqjx_polyline”的图层。

如上面预览地图图层,实际上就是加载了单个地图图层,其对应的URL地址如下表格所示:

WMS服务的单个地图图层加载分析表

localhost:8080/geoserver/wms?service=WMS&version=1.1.0&request=GetMap&layers=cq:dqjx_polyline&styles=&bbox=105.286,28.163,110.194,32.203

&width=512&height=421&srs=EPSG:4326&format=application/openlayers

参数名

service

Version

request

layers

Styles

bbox

width

height

srs

format

参数值

WMS

1.0.1

GetMap

cq:dqjx_polyline

105.286,28.163,110.194,32.203

512

512

EPSG:4326

application/openlayers

参数说明

表示该服务为WMS服务

WMS服务版本

WMS服务请求接口类型,GetMap表示请求地图数据

WMS所请求的地图图层

图层样式

请求的地图图层范围

宽度

高度

地理空间引用标准

地图响应格式(openlayers)

五、多图层叠加呈现

在访问WMS服务的时候通常都是将多个地图图层进行叠加组合,才能完成一个相对完整的地图界面呈现。在访问WMS服务的时候图层叠加非常简单,就是在WMS请求地址的layers参数后面用逗号(“,”)将多个图层进行分割就可以了。下面的WMS服务请求地址就叠加了3个地图图层:

localhost:8080/geoserver/wms?service=WMS&version=1.1.0&request=GetMap&layers=cq:dqjx_polyline,cq:cszgddx_polyline,cq:cszgd_polyline

&styles=&bbox=105.286,28.163,110.194,32.203&width=512&height=421&srs=EPSG:4326&format=application/openlayers

layers=cq:dqjx_polyline,cq:cszgddx_polyline,cq:cszgd_polyline,表示此WMS服务请求是由三个地图图层叠加组合而成的。最终的预览效果如下图:

基于Web地图服务(Web Map Service,简称:WMS)的Silverlight地图客户端实现。

一、DeepZoom简介

DeepZoom技术以MultiScaleImage控件为核心,其内部有一个MultiScaleTileSource类型的源属性,主要用于设置MultiScaleImage控件所要呈现的数据源。基于Silverlight的Web GIS客户端实现也是通MultiScaleImage控件来实现,核心就在于通过MultiScaleTileSource属性针对不同的Web GIS地图瓦片数据(Image Tiles)提供商为MultiScaleImage控件实现一个数据源。因此本篇所需要做的工作就是针对WMS服务为

MultiScaleImage控件实现一套加载数据源的算法。

二、WMS服务加载实现

实现WMS服务加载的算法其实非常简单,只需要了解WMS发布的方式、WMS地址的参数组成结构以及地图瓦片的投影原理就可以了,首先需要定义一个盒子对象作为访问WMS的边界参数对象。

public class BBox

{

public int X { get; set; }

public int Y { get; set; }

public int Width { get; set; }

public int Height { get; set; }

public BBox(int x, int y, int w, int h)

{

this.X = x;

this.Y = y;

= w;

= h;

}

}

关于WMS服务加载的详细算法需要一些GIS理论基础才能够知道具体的实现原理,这里我就不逐一介绍,直接贴代码:

public class WMSTileSource : MultiScaleTileSource

{

public WMSTileSource()

: base(ue, ue, 0x100, 0x100, 0)

{ }

public const int TILE_SIZE = 256;

///

/// 地球半径

///

public const double EARTH_RADIUS = 6378137;

///

/// 地球周长

///

public const double EARTH_CIRCUMFERENCE = EARTH_RADIUS * 2 * ;

public const double HALF_EARTH_CIRCUMFERENCE = EARTH_CIRCUMFERENCE / 2;

///

/// WMS服务地址

///

private const string TilePath = @"localhost:8080/geoserver/wms?service=WMS&version=1.1.0&request=GetMap&layers=cq:CQ_County_region,cq:CQ_County_region_level&styles=&bbox={0},{1},{2},{3}&width=512&height=421&srs=EPSG:4326&&Format=image/png";

public string GetQuadKey(string url)

{

var regex = new Regex(".*tiles/(.+)[.].*");

Match match = (url);

return [1].ToString();

}

public BBox QuadKeyToBBox(string quadKey, int x, int y, int zoomLevel)

{

char c = quadKey[0];

int tileSize = 2 << (18 - zoomLevel - 1);

if (c == '0')

{

y = y - tileSize;

}

else if (c == '1')

{

y = y - tileSize;

x = x + tileSize;

}

else if (c == '3')

{

x = x + tileSize;

}

if ( > 1)

{

return QuadKeyToBBox(ing(1), x, y, zoomLevel + 1);

}

return new BBox(x, y, tileSize, tileSize);

}

public BBox QuadKeyToBBox(string quadKey)

{

const int x = 0;

const int y = 262144;

return QuadKeyToBBox(quadKey, x, y, 1);

}

public double XToLongitudeAtZoom(int x, int zoom)

{

double arc = EARTH_CIRCUMFERENCE / ((1 << zoom) * TILE_SIZE);

double metersX = (x * arc) - HALF_EARTH_CIRCUMFERENCE;

double result = RadToDeg(metersX / EARTH_RADIUS);

return result;

}

public double YToLatitudeAtZoom(int y, int zoom)

{

double arc = EARTH_CIRCUMFERENCE / ((1 << zoom) * TILE_SIZE);

double metersY = HALF_EARTH_CIRCUMFERENCE - (y * arc);

double a = (metersY * 2 / EARTH_RADIUS);

double result = RadToDeg(((a - 1) / (a + 1)));

return result;

}

public double RadToDeg(double d)

{

return d / * 180.0;

}

private static string TileXYToQuadKey(int tileX, int tileY, int levelOfDetail)

{

var quadKey = new StringBuilder();

for (int i = levelOfDetail; i > 0; i--)

{

char digit = '0';

int mask = 1 << (i - 1);

if ((tileX & mask) != 0)

{

digit++;

}

if ((tileY & mask) != 0)

{

digit++;

digit++;

}

(digit);

}

return ng();

}

protected override void GetTileLayers(int tileLevel, int tilePositionX, int tilePositionY, tileImageLayerSources)

{

int zoom = tileLevel - 8;

if (zoom > 0)

{

string quadKey = TileXYToQuadKey(tilePositionX, tilePositionY, zoom);

BBox boundingBox = QuadKeyToBBox(quadKey);

double lon = XToLongitudeAtZoom(boundingBox.X * TILE_SIZE, 18);

double lat = YToLatitudeAtZoom(boundingBox.Y * TILE_SIZE, 18);

double lon2 = XToLongitudeAtZoom((boundingBox.X + ) * TILE_SIZE, 18);

double lat2 = YToLatitudeAtZoom((boundingBox.Y - ) * TILE_SIZE, 18);

string wmsUrl = (TilePath, lon, lat, lon2, lat2, TILE_SIZE);

var veUri = new Uri(wmsUrl);

(veUri);

}

}

}

前端通过一个按钮事件驱动触发加载WMS服务,按钮的XAML代码如下: