当前位置: 首页 > 工具软件 > OWS > 使用案例 >

OpenLayer3通过wfs修改Geoserver中图层要素,并出现图层只读问题解决(is read-only</ows:ExceptionText>)

钱振
2023-12-01

最近在学习OpenLayer教程,通过OpenLayer加载geoserver中图层,其中遇到的问题并解决在此做下记录;

一、参考文件:
1.学习的教程为‘扯淡大叔’的OpenLayer教程,非常好,非常详细,在学习过程中遇到不懂的也请教过作者的帮助,很适合初学者学习,地址为:通过wfs修改要素
2.在遇到修改的图层提交后,network显示200,Context length:0,is read-only,这些问题,是在解决方法在这里
二、具体步骤
1.将shp格式文件加载到postgresGIS数据库,使用Geoserver中postGIS发布图层的方法发布加载的图层,具体可参考我之前的博客;
2.在通过扯淡大叔的教程编写代码,即可加载和显示发布的图层;
3.具体代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>更新WFS要素</title>
    <link href="../css/ol.css">
    <script src="../js/ol,js.js"></script>
    <script src="../js/jquery-1.3.1.js"></script>
</head>
<body>
<input type="button" value="查询" onclick="queryWfs();" />
<input id="select" type="checkbox" value="select" />选择
<input id="modify" type="checkbox" value="modify" />编辑
<input id="save" type="button" value="保存" onclick="onSave();" />
<div id="map" style="height: 70%;">
</div>

</body>

<script>
    var modifiedFeatures=null;
    var wfsVectorLayer = null;
    var selectInteraction=new ol.interaction.Select({
        style:new ol.style.Style({
            stroke:new ol.style.Stroke({
                color: 'red',
                width: 2
            })
        })
    });
    var modifyInteraction = new ol.interaction.Modify({
        style:new ol.style.Style({
            stroke:new ol.style.Stroke({
                color: 'black',
                width: 2
            })
        }),
        features: selectInteraction.getFeatures()
    });


    var map=new ol.Map({
        view:new ol.View({
            projection:'EPSG:4326',
            center:[129.631215,44.590727],
            maxZoom: 19,
            zoom: 13,
        }),
        target:'map',
        layers:[new ol.layer.Tile({
            source:new ol.source.OSM()
        })]
    })

    modifyInteraction.on('modifyend',function (p1) {
        modifiedFeatures = p1.features;
    })

    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的字段,所有这里的名称就是数据库表中增加的那个字段名称
                }),                                                                                              //PostgreGIS:xian_polygon为工作空间:图层名
                url: 'http://localhost:8087/geoserver/wfs?service=wfs&version=1.1.0&request=GetFeature&typeNames=PostgreGIS:xian_polygon&outputFormat=application/json&srsname=EPSG:4326'
            }),
            style: function(feature, resolution) {
                return new ol.style.Style({
                    stroke: new ol.style.Stroke({
                        color: 'blue',
                        width: 5
                    })
                });
            }
        });
        map.addLayer(wfsVectorLayer);
    }

    $('#select').change(function() {
        if (this.checked) {
            // 勾选选择复选框时,添加选择器到地图
            map.removeInteraction(selectInteraction);
            map.addInteraction(selectInteraction);
        } else {
            // 不勾选选择复选框的情况下,移出选择器和修改器
            map.removeInteraction(selectInteraction);
            document.getElementById('modify').checked = false;
            map.removeInteraction(modifyInteraction);
            modifiedFeatures = null;
        }
    });

    $('#modify').change(function() {
        if (this.checked) {
            // 勾选修改复选框时,添加选择器和修改器到地图
            document.getElementById('select').checked = true;
            map.removeInteraction(modifyInteraction);
            map.addInteraction(modifyInteraction);
            map.removeInteraction(selectInteraction);
            map.addInteraction(selectInteraction);
        } else {
            // 不勾选修改复选框时,移出修改器
            map.removeInteraction(modifyInteraction);
            modifiedFeatures = null;
        }
    });

    // 保存已经编辑的要素
    function onSave() {
        if (modifiedFeatures && modifiedFeatures.getLength() > 0) {

            // 转换坐标
            var modifiedFeature = modifiedFeatures.item(0).clone();
            // 注意ID是必须,通过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: 'xian_polygon',  //图层名
                featureNS: 'http://PostgreGIS.com',  // 注意这个值必须为创建工作区时的命名空间URI
                srsName: 'EPSG:4326'
            });
        // 转换为xml内容发送到服务器端
        var serializer = new XMLSerializer();
        var featString = serializer.serializeToString(featObject);
        var request = new XMLHttpRequest();
        request.open('POST', 'http://localhost:8087/geoserver/wfs?service=wfs');
        // 指定内容为xml类型
        request.setRequestHeader('Content-Type', 'text/xml');
        request.send(featString);
    }
</script>
</html>

三、发现问题
1.加载地图可以出现,查询要素可以出现,可以选择和编辑,点击保存后,network传输正确没有任何报错,但是返回值为空,显示提示为”/ows:ExceptionText>{http://PostgreGIS.com}xian_polygon is read-only“”,猜测应该是权限问题,百度后,在参考资料第二个链接中找到方法;
四、解决步骤
1.打开geoserver管理界面,点击左侧的“”Security“”中的“”Data“”栏,点击“Rule path”中的“..w”,勾选“Grant access to any role”下面的单选框,点击保存,清理缓存,再是修改后点击提交,保存成功。

 类似资料: