在线编辑

使用GeoServer发布的WFS(web Feature Service)服务支持对地理要素的插入,更新,删除,检索和发现服务。该服务根据HTTP客户请求返回GML(Geography Markup Language、地理标识语言) 数据。 WFS对应于常见桌面程序中的条件查询功能,WFS通过OGC Filter构造查询条件,支持基于空间几何关系的查询,基于属性域的查询,当然还包括基于空间关系和属性域的共同查询。

使用的接口:

  • GetCapabilities 返回服务级元数据
  • DescribeFeatureType 返回要素结构,以便客户端进行查询和其他操作。
  • GetFeature 可根据查询要求返回一个符合GML规范的数据文档。GetFeature是最重要的接口。

在Web上实现编辑功能,使用WFS的请求不是以SQL实现的,而是通过XML来实现,可扩展性更强。WFS所返回的是查询的结果集,WFS的结果集是由完整的Schema定义和约束的结果集,以GML为载体。

事务型WFS

WFS 规范同时定义了要素编辑的规则,这就为基于 Web 进行矢量数据编辑打开了大门。 通过 WFS 服务对源数据库中的数据进行更改称为事务性 WFS 或 WFS-T 。 一旦启用了事务功能,WFS 客户端便可使用事务性 WFS 方法对地理数据库中的数据进行更改。 MapServer 本身不支持 WFS-T , 作为套件的一部分,有 TinyOWS 可供选择。 在本书中对这部分的具体技术不多作介绍,仅在下面把概念说明一下。

TWFS操作以HTTP作为分布式计算平台,支持对地理要素的插入(INSERT)、更新(UPDATE)、 删除(DELETE)、查询(QUERY)和发现(DISCOVERY)操作。

顾名思义,WFS是通过网络操作Feature的服务。 它支持客户端对服务器的Feature执行 INSERT , UPDATE , DELETE , LOCK , QUERY ,DISCOVERY 操作。

事务是WFS的一个功能,在WFS同数据存储系统的交互中用来保证对数据的改变的一致性。 本书中事务是指由多个数据操纵操作组成的一个逻辑工作单位。 由于对地理数据永久性存储的行为不属于TWFS讨论的范围,所以这里假设没有如原子性失败等事务语义。 另外,这里也承认许多系统支持标准的、并发事务语义的事实, 因此假设一个WFS能够充分利用这些系统(如基于SQL的关系数据库系统)。

处理一个WFS请求的协议的过程如下:

1.客户请求来自WFS—份功能文档。这份文档包含WFS支持的所有操作的描述和可以服务的所有要素的列表。

2.客户(可选)向WFS请求可以服务的一个或多个要素类型的定义(文档)。

3.根据要素类型的定义,客户生成由该文档指定格式的请求。

4.请求被提交到一个Web服务器。

5.Web服务器调用WFS来接收并服务该请求。

6.当WFS完成对请求的处理,它将生成一个状态报告并返回给客户,如果发生错误,就生成异常报告。

一个事务型的WFS将支持基本WFS的所有操作,另外还将实现事务操作。 一个事务WFS可以实现可选的 Transaction 操作和 LockFeature 操作。

TWFS 对地理要素操作的主要功能包括:

  • 创建一个新要素实例。

  • 删除一个要素实例。

  • 更新一个要素实例。

  • 根据空间的或非空间条件查询要素。

发布GML

继续使用上次导入数据发布。

select one多选框内选择发布方式为GML

选择gml

接着会弹出窗口内容内容为GML。

显示gml

对修改的要素提交到GeoServer进行保存,相当于重新发布

在上节的代码中继续添加

function queryWfs() {
        // 重新查询更改
        if (wfsVectorLayer) {
           map.removeLayer(wfsVectorLayer);
        }

        // 创建新的图层来加载wfs的要素
        wfsVectorLayer = new ol.layer.Vector({
            source: new ol.source.Vector({
                format: new ol.format.GeoJSON({
                    geometryName: 'geom' // 将shp格式矢量文件导入PostgreGIS数据库中,对应的表中增加了一个字段名为geom的字段,所有这里的名称就是数据库表中增加的那个字段名称
                }),

                url:'http://localhost:8080/geoserver.war/demo00/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=demo00%3Akaz_adm2_v0792&maxFeatures=50&outputFormat=gml3'//图层地址
          }),
            style: function(feature, resolution) {
                return new ol.style.Style({
                    stroke: new ol.style.Stroke({
                        color: 'blue',
                        width:1
                    })
                });
            }
        });
        map.addLayer(wfsVectorLayer);
    }
    function onSave() {
    //if (modifiedFeatures && modifiedFeatures.getLength() > 0) {

        // 转换坐标
        var modifiedFeature = modifiedFeatures.item(0).clone();
        // 通过ID才能找到对应修改的feature
        modifiedFeature.setId(modifiedFeatures.item(0).getId());
        // 调换经纬度坐标,以符合wfs协议中经纬度的位置
        modifiedFeature.getGeometry().applyTransform(function(flatCoordinates, flatCoordinates2, stride) {
            for (var j = 0; j < flatCoordinates.length; j += stride) {
                var y = flatCoordinates[j];
                var x = flatCoordinates[j + 1];
                flatCoordinates[j] = x;
                flatCoordinates[j + 1] = y;
            }
        });
        modifyWfs([modifiedFeature]);
   // }
}
 // 提交修改
function modifyWfs(features) {

    var WFSTSerializer = new ol.format.WFS();
    var featObject = WFSTSerializer.writeTransaction(null,
        features, null, {
            featureType: 'kaz_adm2_v0792',  //图层名
            featureNS: 'http://localhost:8080/demo00',  // 注意这个值必须为创建工作区时的命名空间URI
            srsName: 'EPSG:4326'
        });
    // 转换为xml内容发送到服务器端
    var serializer = new XMLSerializer();
    var featString = serializer.serializeToString(featObject);
    var request = new XMLHttpRequest();
    request.open('POST', 'http://localhost:8080/geoserver.war/demo00/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=demo00%3Akaz_adm2_v0792&maxFeatures=50&outputFormat=gml3');//URL地址
    // 指定内容为xml类型
    request.setRequestHeader('Content-Type', 'text/xml');
    request.send(featString);
}