GeoServer之SqlView

GeoServer+PostgreSQL+OpenLayers应用技巧
本文介绍如何利用GeoServer、PostgreSQL及OpenLayers进行高效的地图数据管理和发布。针对大量地图图层发布的问题,提出了使用SQLView简化流程的方法,并详细讲解了SQLView的创建与使用。

原文:http://www.cnblogs.com/hanhuibing/articles/5642703.html

Geoserver+postgresql+openlayers是目前主流的gis开发工具。Postgresql用于存储地 图数据,geoserver用于发布地图数据,openlayers或者leaflet用于访问发布地图。正常情况下当shapefile格式的数据导入 postgresql数据库中 之后,我们需要通过geoserver把所有的数据发布出去,这样才能访问。常规情况下这种操作方式是没有问题的,因为地图作为基础服务,一旦发布出去是 不会变化的。但是对于室内地图来说就不行了,假如一个商场有5层,每一楼层又层有5个地图图层,对于这样一个商场需要把这25个地图图层在 geoserver中全部发布出来才能访问该商场的全部地图。假如发布这一个商场的25个图层你还能忍受的话,那发布成千上万个商场的地图你还能忍受吗? 既然忍受不了那就要想办法解决。由于发布地图是机械的重复的工作,我们是否能想一些办法来帮我们完成这些工作呢。这时候就是我们的sqlView出场了。

首先介绍一下sql View,通过SQLViews可以做如下事情:

(1)数据库view可以在geoserver中当作表完全一样的发布,而geoserver的SQLViews不仅能实现简单的查询发布,还能输入参数作为查询视图的条件。

(2)SQLViews可以发布数据库的存储过程或者function,执行更加复杂的逻辑操作与查询。

(3)SQL Views查询可以通过字符串替换的方式进行参数化,参数值可以在wms和wfs请求总使用,输入值可以通过设置的正则表达式进行验证从而消除SQL 注入攻击的风险。

(4)SQLViews是对数据库操作与查询的一个结果,不能使用wfs_t去操作它,但是wfs,wms都可以正常请求或者查询。

创建简单的SQL Views

这里写图片描述 
这里写图片描述 
这里创建了一个视图,从road表中只返回gid小于100的记录。 
这里写图片描述 
一般可以将数据库中主键比如gid设置为标识符,返回的图形要手动选择类型和srid。其他发布操作和其他的一模一样。

创建带查询条件的SQL Views

定义参数化Views

这里写图片描述 
这里使用%%定义了两个参数,一个是下限low,一个是上限high。该视图用于传入这两个参数,查询结果。 
这里写图片描述 
点击 ‘从sql中猜想参数’,自动弹出以上内容。可以在默认值中赋值,后面正则表达式用于验证参数格式,防止sql注入,具体细节请学习正则表达式。任何不符 合表达式规定的参数,验证都不会通过。(新手练习可以删除正则表达式内容,为空即可。避免因为正则不通过,导致视图使用不了)。发布的其他操作见上文。

使用参数化Views

在正常的wms的getMap请求中或者wfs的getFeature请求的url中加入viewparams参数,用来向视图传递参数值。上文中我们定义了两个参数,即low和high,下面看如何在请求中将参数传递给服务器。 
正常getMap语句:

http://localhost:8090/geoserver/network/wms?service=WMS&version=1.1.0&request=GetMap&layers=network:road&styles=&bbox=1.31808014222456E7,3663612.77697468,1.32722445176114E7,3844254.1268673&width=259&height=512&srs=EPSG:3857&format='image.png'

可传递参数的getMap

http://localhost:8090/geoserver/network/wms?service=WMS&version=1.1.0&request=GetMap&layers=network:road&styles=&bbox=1.31808014222456E7,3663612.77697468,1.32722445176114E7,3844254.1268673&width=259 
&format=’image.png’ 
&viewparams=low:200;high:400

`正常wfs的请求url后加上viewparmas即可。 
viewparams格式一般是viewparams=p1:v1;p2:v2;…可以加若干个参数。不同参数之间以;隔开,单个参数是键值对,即p1是参数名称,v1是参数值。 
很明显如’,’,’ ;’都是特殊符号,用来区分参数的,可是有人要问,要是我的参数值是字符串,并且就有特殊符号怎么办?当然有办法–转义!转义符号是’\’。 
比如,v1值比如是’adsf;sdfjsdf’,那么viewparams就要这么写viewparams=p1:’adsf\;sdfjsdf’,注意’,’,’:’都是特殊符号。

创建数据库的Function视图

在postgis中定义Function

CREATE OR REPLACE FUNCTION zj_showjgnsr( IN p_idcode text, OUT swglm text, OUT geom geometry) RETURNS SETOF record AS $BODY$ DECLARE sql text; rec record; the_geom geometry; BEGIN execute 'select geom from grid where idcode=$1' using p_idcode into the_geom; for rec in execute 'select * from jgnsr where ST_Within(geom,$1)' using the_geom loop swglm:=rec.swglm; geom:=rec.geom; return next; end loop; return; END; $BODY$ LANGUAGE 'plpgsql' VOLATILE STRICT;

这个function接受一个参数,根据该参数从grid表中查询出图形,然后以该图形为查询条件,查询这个jgnsr 表中与其相交的所有记录,并返回出去。function一般处理比较复杂的逻辑和过程。

发布Function

这里写图片描述 
这里写图片描述

使用:发布成功之后,该视图图层和普通表在查询时几乎都是一模一样的操作,不同的是,表发布的图层可以通过wfs_t修改,而视图图层不可以。此外,视图图层有参数的,在正常请求的wfs,wms的url中要加上viewparams参数。

内容概要:本文主要介绍了基于PostGIS环境在GeoServer平台之上建立自定义SQL视图的具体方法。首先对如何利用PostGIS数据库创建存储函数进行了说明,详细讲解了包括参数传递机制(如字符型和整型),到函数体内部查询操作编写的所有细节。紧接着针对创建好的PostGIS函数阐述了在GeoServer平台配置过程中关于图层新增时选择相应工作区、定制化SQL视图界面以及设定SQL查询命令和参数设置等一系列关键环节。此外还强调了参数格式的验证对于预防SQL注入攻击的重要性。 适用人群:地理信息系统管理员,地图开发者,WebGIS应用集成人员,从事空间数据分析工作者。 使用场景及目标:旨在使开发者能够独立地将复杂的后端PostGIS查询结果呈现给前端GIS系统,提高地理信息服务的数据灵活性和服务响应速度的同时,加强了数据安全管理措施。例如,在线绘制特定条件筛选的空间要素图形,为用户提供定制化的空间查询服务等功能。 其他说明:通过本教程,不仅可以加深对PostGIS扩展的强大支持的理解,更能掌握使用GeoServer作为开源地理信息服务平台搭建的基础技能。这使得读者可以更高效地管理和展示地理位置相关的大规模矢量数据集。文中所涉及的内容涵盖了从理论介绍到具体实操指引两方面,对于想深入研究PostGIS同GeoServer协作机制的学习者非常有帮助。
<think>我们正在处理用户关于使用QGIS连接PostgreSQL数据库,并在GeoServer中设置定时更新和发布图层的查询。步骤分解:1.使用QGIS连接到PostgreSQL数据库(包含PostGIS扩展)2.在GeoServer中发布PostgreSQL中的图层3.配置定时更新(可能涉及数据库视图、外部程序定时触发或GeoServer的定时刷新策略)注意:GeoServer本身不直接提供定时更新发布图层的功能,但可以通过以下方式实现:-使用数据库视图并设置定时任务更新视图的数据源(例如通过cron作业或pgAgent执行SQL脚本更新表)-使用GeoServer的SQL视图并设置缓存过期时间(这样当数据变化时,GeoServer会在缓存过期后重新查询数据库)-或者,更常见的是,通过外部脚本(如Python)定时更新数据库表,然后通过GeoServerRESTAPI重新加载图层(或清除缓存)根据用户需求,我们将分步说明。步骤1:QGIS连接PostgreSQL-打开QGIS,在“图层”菜单中选择“添加图层”->“添加PostGIS图层”-点击“新建”创建一个新连接,填写以下信息:名称:自定义(如my_pg_connection)主机:数据库服务器IP或域名端口:5432(默认)数据库:数据库名用户名和密码:数据库的登录凭据-点击“测试连接”确认成功,然后点击“确定”-在连接列表中选择该连接,点击“连接”,然后选择要添加的表或视图步骤2:在GeoServer中发布图层-登录GeoServer管理界面(默认http://localhost:8080/geoserver)-创建新的工作区(Workspace)或使用现有工作区-创建数据存储(DataStore):选择“PostGIS”在数据存储配置页面,填写连接参数(与QGIS连接类似),包括:工作区:选择工作区数据源名称:自定义数据库:PostGIS主机:数据库服务器IP端口:5432数据库:数据库名用户名和密码Schema:public(或指定其他schema)-点击“保存”-发布图层:在数据存储创建成功后,点击“发布”链接选择要发布的表或视图配置图层信息(如坐标参考系统、边框等)在“发布”标签页中设置样式等,然后点击“保存”步骤3:定时更新-方案1:使用数据库视图并定时刷新数据在PostgreSQL中创建视图,然后通过定时任务(如cron)执行SQL脚本更新基表(视图的数据源)。但注意,视图是实时的,如果基表数据更新,视图查询就会更新。因此,定时更新基表即可。例如:使用cron定时执行一个SQL脚本(或psql命令)来更新基表数据。-方案2:使用GeoServer的SQL视图在GeoServer中创建数据存储时,可以选择“配置新的SQL视图”:在“新建数据存储”页面,选择“PostGIS”后,在“工作区”下方有一个“配置新的SQL视图”链接。输入视图名称和SQL语句(例如:SELECT*FROMmy_tableWHEREupdate_time>current_date-interval'1day')可以设置缓存时间(如60秒),这样GeoServer会每隔60秒重新执行SQL查询。但注意:这种方式适用于小数据量,且SQL视图不支持写操作。-方案3:通过外部脚本更新数据库并重新加载GeoServer图层步骤:a.编写脚本(如Python)定时从数据源获取新数据并更新PostgreSQL表(使用psycopg2等库)。b.在更新数据库后,使用GeoServerRESTAPI重新加载图层或清除图层的缓存。GeoServerRESTAPI示例(重新加载整个GeoServer):POST/geoserver/rest/reload(需要管理员认证)c.设置定时任务(如cron)运行该脚本。具体选择哪种方案取决于具体需求(数据量、更新频率等)。由于用户要求配置教程,我们将重点放在方案3,因为它更通用且可控。方案3详细步骤:1.编写Python脚本更新数据库并调用GeoServerRESTAPI:-使用psycopg2更新PostgreSQL数据库-使用requests库调用GeoServerRESTAPI示例脚本(假设每天凌晨1点更新):```pythonimportpsycopg2importrequestsfromdatetimeimportdatetime#更新数据库defupdate_db():conn=psycopg2.connect(host="your_db_host",dbname="your_db",user="user",password="password")cur=conn.cursor()#执行更新操作,例如从另一个数据源导入新数据到目标表#这里假设有一个临时表staging_table,每天将新数据插入到主表main_tablecur.execute("""INSERTINTOmain_table(geom,attr1,update_time)SELECTgeom,attr1,update_timeFROMstaging_tableWHEREupdate_time>(SELECTMAX(update_time)FROMmain_table);""")conn.commit()cur.close()conn.close()#重新加载GeoServer(整个GeoServer重新加载)defreload_geoserver():url='http://localhost:8080/geoserver/rest/reload'#使用管理员账号认证auth=('admin','geoserver')#默认密码,如果修改过请使用修改后的response=requests.post(url,auth=auth)ifresponse.status_code==200:print("GeoServerreloadedsuccessfully.")else:print("FailedtoreloadGeoServer.Statuscode:",response.status_code)if__name__=='__main__':print("Startingupdateat",datetime.now())update_db()reload_geoserver()```2.设置定时任务(以Linux为例):-将上述脚本保存为`update_geoserver.py`-使用crontab设置定时任务:`crontab-e`-添加一行:`01***/usr/bin/python3/path/to/update_geoserver.py`(每天凌晨1点执行)注意:确保Python环境安装了psycopg2和requests库。另外,如果只想重新加载特定图层(而不是整个GeoServer),可以使用以下RESTAPI:-清除图层缓存:POST/geoserver/rest/layers/{workspace}:{layer}/layer.xml?reload=true例如:http://localhost:8080/geoserver/rest/layers/my_workspace:my_layer/layer.xml?reload=true修改reload_geoserver函数为:```pythondefreload_geoserver_layer(workspace,layer_name):url=f'http://localhost:8080/geoserver/rest/layers/{workspace}:{layer_name}/layer.xml?reload=true'auth=('admin','geoserver')response=requests.post(url,auth=auth)#...同上```这样,在更新数据库后,可以针对每个更新的图层调用此函数。总结:-用户需要先配置QGIS连接PostgreSQL,然后配置GeoServer发布图层。-定时更新通过外部脚本(定时任务+数据库更新+GeoServerRESTAPI重新加载)实现。引用说明:我们参考了GeoServer和PostGIS的一般配置流程,以及GeoServerRESTAPI文档[^1]。</think>### 通过QGIS连接PostgreSQL数据库及GeoServer定时发布配置指南 #### 一、QGIS连接PostgreSQL/PostGIS数据库 1. **准备数据库** - 确保PostgreSQL已安装PostGIS扩展: ```sql CREATE EXTENSION postgis; ``` - 创建空间表(示例): ```sql CREATE TABLE buildings ( id SERIAL PRIMARY KEY, geom GEOMETRY(Polygon, 4326), name VARCHAR(50) ); ``` 2. **QGIS连接步骤** - 打开QGIS → 图层菜单 → 添加图层 → 选择**PostGIS** - 新建连接配置: - 名称:自定义(如`CityDB`) - 主机:数据库服务器IP - 端口:`5432`(默认) - 数据库:目标数据库名 - 用户名/密码:数据库凭证 - 点击**测试连接**确认成功后加载图层 > 连接成功后,可在QGIS中直接编辑空间数据并同步到数据库[^1]。 #### 二、GeoServer发布PostGIS图层 1. **创建数据存储** - 登录GeoServer(默认`http://localhost:8080/geoserver`) - 数据存储 → 添加新的数据存储 → 选择**PostGIS** - 配置参数: - 工作区:选择或新建 - 数据源名称:自定义(如`city_data`) - 数据库连接参数:与QGIS配置一致 - 关键参数: ```properties Expose primary keys = true Estimated extends = true ``` 2. **发布图层** - 选择新建的数据存储 → 发布 → 选择目标表 - 配置坐标参考系统(如`EPSG:4326`) - 发布标签页 → 设置默认样式 - 保存后通过`Layer Preview`测试 #### 三、定时更新与发布配置 1. **数据库端定时更新** - 使用`pgAgent`或`cron`执行SQL脚本: ```bash # 每日凌晨更新示例 0 0 * * * psql -d gisdb -f /scripts/update_buildings.sql ``` - 更新脚本内容: ```sql UPDATE buildings SET geom = ST_Transform(new_data.geom, 4326) FROM temp_table AS new_data WHERE buildings.id = new_data.id; ``` 2. **GeoServer自动刷新方案** - **方案1:SQL视图定时刷新** - 发布图层时选择**SQL视图** ```sql SELECT * FROM buildings WHERE update_time > CURRENT_TIMESTAMP - INTERVAL '1 hour' ``` - 设置**缓存过期时间**(秒)实现定时刷新 - **方案2:REST API触发更新** ```python # Python脚本示例(需安装requests库) import requests auth = ('admin', 'geoserver') # 清除图层缓存 requests.post( 'http://localhost:8080/geoserver/rest/layers/city:buildings.xml?reload=true', auth=auth ) # 重置数据存储 requests.post( 'http://localhost:8080/geoserver/rest/reload', auth=auth ) ``` - 将此脚本加入系统定时任务(cron或Task Scheduler) 3. **视图自动发布技巧** - 在PostgreSQL创建物化视图: ```sql CREATE MATERIALIZED VIEW vw_daily_buildings AS SELECT * FROM buildings WHERE update_date = CURRENT_DATE; ``` - 使用`REFRESH MATERIALIZED VIEW`命令更新 - GeoServer直接发布该视图作为图层 > 建议结合数据库触发器和GeoServer REST API实现全自动流程[^1]。 #### 四、验证与调试 1. **日志检查** - GeoServer日志路径:`GEOSERVER_DATA_DIR/logs/geoserver.log` - 监控关键词: ``` Reloading store 'city_data' SQL view refresh for 'vw_daily_buildings' ``` 2. **性能优化** - 为时间字段添加索引: ```sql CREATE INDEX idx_buildings_time ON buildings(update_time); ``` - 在GeoServer图层配置中启用**DBMS缓存** --- ### 相关问题 1. **如何实现PostGIS空间数据与QGIS的实时同步编辑?** 2. **GeoServer发布WMS/WFS服务时如何优化矢量图层的渲染性能?** 3. **PostgreSQL中如何配置逻辑复制实现地理数据库的主从同步?** 4. **除了定时任务,还有哪些方法可以触发GeoServer图层的自动更新?** [^1]: 引用来源:PostgreSQL+PostGIS+QGIS+GeoServer集成实践指南
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值