分享

OpenLayer+PostGIS+GeoServer--无额外后台实现地理分析与查询框架

 Jcstone 2020-01-31

1.1 传统流程

在一般情况下,人们使用PostGIS存储空间数据,以Geoserver发布数据服务,以OpenLayer客户端展示地图。客户端操作与地理查询,如果查询等比较复杂,一般会使用ajax将ol的请求参数传给后台,由后台完成操作后返回前端。流程如下:

1.2 框架问题说明

1 GeoServer只是简单发布了地理数据,单个图层,只能接受简单的wms显示,wfs查询,wps分析。产生的问题是,面对多个图层的叠加分析与查询,几乎做不到,所以很多图层的分析只能交由后台服务器完成。

2 使用后台服务器处理地理数据,产生的问题是,对数据库的访问比较频繁,分析的结果,由于是空间数据,对数据的解析存储有要求,工作量增大。

3 作为GIS专业开发人员的苦恼是我曾加入一个j2ee项目组,作为Java的门外汉,我做一个哪怕最简单的查询,都要写好多个java类文件与数据结构类文件,为了满足j2ee框架需求。这令我感到很苦恼,在我看来,作为业务开发人员,他们需要这个框架,但作为地图开发人员,我的精力都在研究各个地图技术和框架上而不是语言本身,既不必要也无精力。能不能有个gis开发框架,使我专注于地理数据的查询与分析而脱离业务框架本身的束缚,这让我感到很有必要。

二 独立于业务的地理数据操作框架

结构说明:1 复杂的多图层的分析,全是在数据库中以function脚本编写。

2 geoserver发布要显示地图表。发布function作为视图参数。 对geoserver来说,table,view,function本质都是数据源,是一样的,所以都可以发布。

3 使用时,普通的表用来显示地图,function用来分析地图。

优势:无论加入哪个项目组,我根本不用关心他们的框架与数据结构,集成时,自己负责地图,业务负责业务,各司其职。

原来后台服务全被改写到数据库中,这样,在运算速度上也比驱动的快且少了一个额外的后台。

三 框架使用示例

以最最简单的需求作为说明示例:

需求: 我要根据道路名称,查询道路某个距离的缓冲区内的兴趣点。

3.1 实现具体分析功能的数据库function脚本

[sql] view plain copy print?

  1. CREATE OR REPLACE FUNCTION queryplottingbyroad(  

  2.                 IN roadname text,  

  3.                 in distance double precision,  

  4.                 OUT gid int,  

  5.                 OUT shapearea double precision,  

  6.                 out swglm text,  

  7.                 out idcode text,  

  8.                 out gljg_dm text,  

  9.                 out editdate timestamp without time zone,  

  10.                 out geom geometry  

  11.         )  

  12.          returns SETOF record AS  

  13. $BODY$  

  14. DECLARE  

  15.         queryGeom geometry;  

  16.         rec record;  

  17.         sql text;  

  18. BEGIN  

  19.     --依据道路名称查询道路图形  

  20.     sql:='select geom from road where name='''||roadname||'''';  

  21.     raise notice 'sql:%',sql;  

  22.     EXECUTE sql into rec;  

  23.     --对查询的道路进行缓冲  

  24.     queryGeom:=ST_Buffer(rec.geom,distance);  

  25.     --查询落在缓冲区内或与缓冲区相交的指定图层数据  

  26.     sql:='select * from plottingwithqx t where ST_Within(t.geom,ST_GeomFromText('''||st_astext(queryGeom)||''',3857)) or ST_Intersects(t.geom,ST_GeomFromText('''||st_astext(queryGeom)||''',3857))';  

  27.     raise notice 'sql:%',sql;  

  28.     --查询数据搜集返回调用者  

  29.     for rec in execute sql loop  

  30.         gid:= rec.gid;  

  31.         shapearea:= rec.shapearea;  

  32.         swglm:= rec.swglm;  

  33.         idcode:= rec.idcode;  

  34.         gljg_dm:= rec.gljg_dm;    

  35.         editdate:= rec.editdate;          

  36.         geom:= rec.geom;  

  37.         return next;  

  38.     end loop;  

  39.     return;  

  40. END;  

  41. $BODY$  

  42. LANGUAGE 'plpgsql' VOLATILE STRICT;  

  1. CREATE OR REPLACE FUNCTION queryplottingbyroad(

  2. IN roadname text,

  3. in distance double precision,

  4. OUT gid int,

  5. OUT shapearea double precision,

  6. out swglm text,

  7. out idcode text,

  8. out gljg_dm text,

  9. out editdate timestamp without time zone,

  10. out geom geometry

  11. )

  12. returns SETOF record AS

  13. $BODY$

  14. DECLARE

  15. queryGeom geometry;

  16. rec record;

  17. sql text;

  18. BEGIN

  19. --依据道路名称查询道路图形

  20. sql:='select geom from road where name='''||roadname||'''';

  21. raise notice 'sql:%',sql;

  22. EXECUTE sql into rec;

  23. --对查询的道路进行缓冲

  24. queryGeom:=ST_Buffer(rec.geom,distance);

  25. --查询落在缓冲区内或与缓冲区相交的指定图层数据

  26. sql:='select * from plottingwithqx t where ST_Within(t.geom,ST_GeomFromText('''||st_astext(queryGeom)||''',3857)) or ST_Intersects(t.geom,ST_GeomFromText('''||st_astext(queryGeom)||''',3857))';

  27. raise notice 'sql:%',sql;

  28. --查询数据搜集返回调用者

  29. for rec in execute sql loop

  30. gid:= rec.gid;

  31. shapearea:= rec.shapearea;

  32. swglm:= rec.swglm;

  33. idcode:= rec.idcode;

  34. gljg_dm:= rec.gljg_dm;

  35. editdate:= rec.editdate;

  36. geom:= rec.geom;

  37. return next;

  38. end loop;

  39. return;

  40. END;

  41. $BODY$

  42. LANGUAGE 'plpgsql' VOLATILE STRICT;

3.2 Geoserer发布function

在  图层》发布视图服务中发布一个视图服务,具体参照geoserver官网。

3 客户端调用

以wms查询为例:

[plain] view plain copy print?

  1. http://localhost:8090/geoserver/nkstarTax/wms?LAYERS=nkstarTax:queryPlottingbyroad&TRANSPARENT=TRUE&VIEWPARAMS=name:'东方红路';distance:100&BBOX=1.3304724687752E7,3812889.1757509,1.3323585520889E7,3829641.4938807&WIDTH=512&HEIGHT=434&SRS=EPSG:900913&format=image/png&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&STYLES=  

http://localhost:8090/geoserver/nkstarTax/wms?LAYERS=nkstarTax:queryPlottingbyroad&TRANSPARENT=TRUE&VIEWPARAMS=name:'东方红路';distance:100&BBOX=1.3304724687752E7,3812889.1757509,1.3323585520889E7,3829641.4938807&WIDTH=512&HEIGHT=434&SRS=EPSG:900913&format=image/png&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&STYLES=

viewparams是客户端把参数放这个里面,传给geoserver,然后服务器解析参数,查询数据库并返回结果。上方的url请求返回 道路名称为'东方红路'的100米范围内的查询图层的符合要求数据。

查询 200米范围内的指定图层符号要求数据

[plain] view plain copy print?

  1. http://localhost:8090/geoserver/nkstarTax/wms?LAYERS=nkstarTax:queryPlottingbyroad&TRANSPARENT=TRUE&VIEWPARAMS=name:'东方红路';distance:200&BBOX=1.3304724687752E7,3812889.1757509,1.3323585520889E7,3829641.4938807&WIDTH=512&HEIGHT=434&SRS=EPSG:900913&format=image/png&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&STYLES=  

http://localhost:8090/geoserver/nkstarTax/wms?LAYERS=nkstarTax:queryPlottingbyroad&TRANSPARENT=TRUE&VIEWPARAMS=name:'东方红路';distance:200&BBOX=1.3304724687752E7,3812889.1757509,1.3323585520889E7,3829641.4938807&WIDTH=512&HEIGHT=434&SRS=EPSG:900913&format=image/png&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&STYLES=

效果如下,范围扩大之后,多了一条记录。

使用wfs查询也是一样的,使用viewparams将参数传给服务器,服务器查询数据库。

总的来说,将传统流程的复杂分析,摒弃了后台,直接放在数据库中的function中完成,由geoserver作为后台,响应客户端请求,无论wms,wfs都可以,并根据参数返回图片或数据。

后续小编的主要精力放到GIS理论开发知识的大众化的道路了,通过浅显易懂的语言,结合多年行业应用开发,通过微信订阅号传播(每周更新三篇文章及相关GIS编码知识),为GIS的发展尽微博之力。终极目标是让GIS不再专业,让GIS更加大众,使得GIS深入各行业应用,让每位GISER都有一股自豪感!以下是我的微信订阅号二维码,感兴趣的可以交流沟通!

文章来源:http://blog.csdn.net/freeland1/article/details/42171949

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多