ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

基于OpenLayers使用WFS实现GeoServer地图要素的增删改查

2022-07-25 01:32:34  阅读:190  来源: 互联网

标签:map ol let GeoServer 改查 topp OpenLayers new WFS


1. 概述

Web Feature Service(WFS)接口标准定义了一组接口,用于在Internet上访问要素和要素属性级别的地理信息。WFS提供了检索或查询矢量要素的方法,这种方法独立于它们发布的底层数据存储,WFS还可以更新或删除矢量要素。WFS的实例还能够存储查询,以便使客户机应用程序能够在稍后的时间点检索或执行查询

更多信息可参考:

中文版站点(翻译不完全准确):WFS-简介 — OGC e-Learning 2.0.0 文档 (osgeo.cn)

WFS服务器必须支持的操作:

  • GetCapabilities:返回一个文档,该文档描述由服务器提供的WFS服务提供的功能和资源

  • DescribeFeatureType:返回WFS实例提供或接受的功能类型和功能属性的结构描述

  • ListStoredQueries:返回存储在WFS实例中的查询列表

  • DescribeStoredQueries:返回存储在WFS实例中的查询的说明

  • GetFeature:从通过WFS发布的数据存储中返回要素实例的选择

WFS服务器通常也支持的操作:

  • GetPropertyValue:检索一组要素实例的要素特性值或复杂要素特性值的一部分
  • GetFeatureWithLock:提供与GetFeature请求类似的功能,但具有锁定特性的附加功能,可能是为了后续更新或更改
  • LockFeature:锁定一组要素实例,以便在锁定到位时,其他操作都不能修改数据
  • Transaction:允许插入、更新或删除要素实例及其属性
  • CreateStoredQuery:创建并存储一个查询,客户机可以在稍后的时间点快速地触发该查询
  • DropStoredQuery:从服务器中删除以前存储的查询

参考:WFS参考 — GeoServer 2.19.x User Manual (osgeo.cn)

GeoServer作为GIS服务器,支持WFS定义的一系列操作

WFS操作大部分支持KVP格式(URL里包含键值对的形式)和XML格式,少部分只支持XML格式(主要是更新与新增操作)

编写XML终究繁琐,OpenLayers支持OGC的WFS规范,可以基于WFS来对空间数据进行增、删、改、查(CRUD)

本文基于OpenLayers提供的WFS操作API,实现对GeoServer发布的空间数据进行增、删、改、查

本文大量参考了这篇文章:OpenLayers教程:网络要素服务(WFS) - 知乎 (zhihu.com)

2. 环境准备

GeoServer的下载与配置跨域可参考:

从官方下载的GeoServer带有示例数据,参考:

登录GeoServer,默认登录账户密码是:

  • 用户名: admin
  • 密码: geoserver

笔者这里使用的数据是 Tasmania roads:

image-20220724222005331

另外,需要将此数据开启读写权限:

image-20220724222338174

使用的OpenLayers版本是最新版6.15.1,CDN引入:

<link rel="stylesheet"
      href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.15.1/css/ol.css" type="text/css">
<script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.15.1/build/ol.js"></script>

3. 查询要素

这里的查询要素主要是指使用GetFeature操作,即获取要素

GetFeature操作可以使用KVP格式构造URL地址,参考官方自带示例:

image-20220724223753454

可以通过构造URL来实现多种查询,构造的具体参数可以参考:

笔者这里查询Tasmania roads的所有要素并返回JSON格式:

http://localhost:8080/geoserver/topp/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=topp:tasmania_roads&outputFormat=application/json

此外我们还可以使用GeoServer自带的图层预览来复制构造的URL:

image-20220724224449695

直接在new ol.source.Vector中写入url参数,就可以利用WFS的KVP进行要素的查询,核心代码如下:

const vectorLayer = new ol.layer.Vector({
    source: new ol.source.Vector({
        url: 'http://localhost:8080/geoserver/topp/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=topp:tasmania_roads&outputFormat=application/json',
        format: new ol.format.GeoJSON()
    })
});
map.addLayer(vectorLayer);

完整代码如下:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Test</title>
    <link rel="stylesheet"
        href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.15.1/css/ol.css" type="text/css">
    <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.15.1/build/ol.js"></script>
    <style>
        html,
        body {
            height: 100%;
        }

        body {
            margin: 0;
            padding: 0;
        }

        #map {
            height: 100%;
        }
    </style>
</head>

<body>
    <div id="map"></div>
    <script>
        const map = new ol.Map({
            target: 'map',
            layers: [],
            view: new ol.View({
                center: [147.01, -42.26],
                zoom: 8,
                projection: 'EPSG:4326'
            })
        });
        map.addLayer(new ol.layer.WebGLTile({
            source: new ol.source.OSM()
        }));
        const vectorLayer = new ol.layer.Vector({
            source: new ol.source.Vector({
                url: 'http://localhost:8080/geoserver/topp/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=topp:tasmania_roads&outputFormat=application/json',
                format: new ol.format.GeoJSON()
            }),
            style: new ol.style.Style({
                stroke: new ol.style.Stroke({
                    color: '#0000ff',
                    width: 2
                })
            })
        });
        map.addLayer(vectorLayer);
    </script>

</body>

</html>

加载的地图如下:

image-20220724230249890

4. 添加要素

更新、添加、删除要素操作都不支持KVP格式,所以只能使用XML文档的形式来请求

一个完整的XML字段解释如下图:

image-20220725004346519

参考GeoServer自带的添加要素的示例:

image-20220724230653974

编写XML字符过于繁琐,OpenLayers提供了编写WFS XML的API:

image-20220724230933323

参考OpenLayers的API文档:OpenLayers v6.15.1 API - Class: WFS

核心代码如下:

// 服务配置,命名空间、图层、服务地址等
const geoserverData = {
    workSpaceName: 'topp',
    uri: 'http://www.openplans.org/topp',
    wfsURL: 'http://localhost:8080/geoserver/topp/ows?',
    layer: 'tasmania_roads'
}

function addFeatureWFS(features) {
    let WFS = new ol.format.WFS();
    // 生成XML格式的WFS请求信息
    let transact_xml = WFS.writeTransaction(
        features, null, null,
        {
            srcName: 'EPSG:4326',
            featureNS: geoserverData.uri,
            featurePrefix: geoserverData.workSpaceName,
            featureType: [geoserverData.layer],
        }
    );
    // 将XML格式请求信息序列化为字符串格式
    transact_str = (new XMLSerializer()).serializeToString(transact_xml);
    // 使用Fetch将请求发送到后端
    fetch('http://localhost:8080/geoserver/wfs', {
        method: 'POST',
        body: transact_str,
        headers: {
            'Content-Type': 'text/xml'
        }
    }).then(res => res.text()).then(res => {
        console.log(res);
    });
}

完整代码如下:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Test</title>
    <link rel="stylesheet"
        href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.15.1/css/ol.css" type="text/css">
    <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.15.1/build/ol.js"></script>
    <style>
        html,
        body {
            height: 100%;
        }

        body {
            margin: 0;
            padding: 0;
        }

        #map {
            height: 100%;
        }
    </style>
</head>

<body>
    <button id="draw">绘制</button>
    <button id="add">添加</button>
    <button id="exit">退出</button>
    <div id="map"></div>
    <script>
        const map = new ol.Map({
            target: 'map',
            layers: [],
            view: new ol.View({
                center: [147.01, -42.26],
                zoom: 8,
                projection: 'EPSG:4326'
            })
        });
        map.addLayer(new ol.layer.WebGLTile({
            source: new ol.source.OSM()
        }));
        const vectorLayer = new ol.layer.Vector({
            source: new ol.source.Vector({
                url: 'http://localhost:8080/geoserver/topp/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=topp:tasmania_roads&outputFormat=application/json',
                format: new ol.format.GeoJSON()
            }),
            style: new ol.style.Style({
                stroke: new ol.style.Stroke({
                    color: '#0000ff',
                    width: 2
                })
            })
        });
        map.addLayer(vectorLayer);

        // 绘制控件
        let drawedFeatures = [];
        let draw = new ol.interaction.Draw({
            source: vectorLayer.getSource(),
            type: 'MultiLineString',
            geometryName: 'the_geom'                // 注意:这里图形信息字段一定要和后端服务器一致
        });
        draw.on('drawend', (event) => {
            let feature = event.feature;
            // 为要素添加属性,我这里随便设置属性
            feature.set('TYPE', 'highway');
            drawedFeatures.push(event.feature);
        });
        map.addInteraction(draw);
        draw.setActive(false);

        document.querySelector('#add').addEventListener('click', (event) => {
            // 将绘制的要素添加到后台
            addFeatureWFS(drawedFeatures);
        });
        document.querySelector('#draw').addEventListener('click', (event) => {
            // 绘制要添加的要素
            draw.setActive(true);
        });
        document.querySelector('#exit').addEventListener('click', (event) => {
            // 退出绘制
            draw.setActive(false);
        });

        // 服务配置,命名空间、图层、服务地址等
        const geoserverData = {
            workSpaceName: 'topp',
            uri: 'http://www.openplans.org/topp',
            wfsURL: 'http://localhost:8080/geoserver/topp/ows?',
            layer: 'tasmania_roads'
        }

        function addFeatureWFS(features) {
            let WFS = new ol.format.WFS();
            // 生成XML格式的WFS请求信息
            let transact_xml = WFS.writeTransaction(
                features, null, null,
                {
                    srcName: 'EPSG:4326',
                    featureNS: geoserverData.uri,
                    featurePrefix: geoserverData.workSpaceName,
                    featureType: [geoserverData.layer],
                }
            );
            // 将XML格式请求信息序列化为字符串格式
            transact_str = (new XMLSerializer()).serializeToString(transact_xml);
            // 使用Fetch将请求发送到后端
            fetch('http://localhost:8080/geoserver/wfs', {
                method: 'POST',
                body: transact_str,
                headers: {
                    'Content-Type': 'text/xml'
                }
            }).then(res => res.text()).then(res => {
                let transactRes = WFS.readTransactionResponse(res);
                let str = transactRes.transactionSummary.totalInserted +
                    " totalInserted!, insertIds: " + transactRes.insertIds + "\n";
                str += transactRes.transactionSummary.totalUpdated + " totalUpdated!\n";
                str += transactRes.transactionSummary.totalDeleted + " totalDeleted!";
                alert(str);
            });
        }
    </script>

</body>

</html>

注意:

  • geometryName要和后端GIS服务器的数据保持一致,它将会被写为XML标签,可以从GetFeature结果查询,参考下图
  • WFS.writeTransaction中的featureType参数是图层名字,它将会被写为XML标签,参考下图

image-20220724233355327

image-20220724233359476

增加要素后的结果:

image-20220724233608770

5. 更新要素

使用OpenLayers,更新要素的流程:

  • 加载初始要素
  • 创建选择控件选择要素
  • 创建修改控件修改要素
  • 将修改后的要素和信息写为XML
  • 序列化XML
  • 提交XML到服务器

核心代码如下:

// 服务配置,命名空间、图层、服务地址等
const geoserverData = {
    workSpaceName: 'topp',
    uri: 'http://www.openplans.org/topp',
    wfsURL: 'http://localhost:8080/geoserver/topp/ows?',
    layer: 'tasmania_roads'
}

// 选择要素控件
let select = new ol.interaction.Select({
    layers: [vectorLayer],
    hitTolerance: 10
});
map.addInteraction(select);

// 修改要素控件
let modify = new ol.interaction.Modify({
    features: select.getFeatures()
});
// 保存修改完成的要素
let modifiedFeatures = null;    // 用于保存被修改的要素
modify.on('modifyend', (event) => {
    modifiedFeatures = event.features;
});
map.addInteraction(modify);

document.querySelector('#modify').addEventListener('click', (event) => {
    let features = [];
    modifiedFeatures.forEach(function (item, index, array) {
        features.push(item);
    });
    updateWFS(features);
});

function updateWFS(features) {
    let WFS = new ol.format.WFS();
    // 生成XML格式的WFS请求信息
    let transact_xml = WFS.writeTransaction(
        null, features, null,
        {
            srcName: 'EPSG:4326',
            featureNS: geoserverData.uri,
            featurePrefix: geoserverData.workSpaceName,
            featureType: [geoserverData.layer],
        }
    )
    // 将XML格式请求信息序列化为字符串格式
    transact_str = (new XMLSerializer()).serializeToString(transact_xml);
    // 使用Fetch将请求发送到后端
    fetch('http://localhost:8080/geoserver/wfs', {
        method: 'POST',
        body: transact_str,
        headers: {
            'Content-Type': 'text/xml'
        }
    }).then(res => res.text()).then(res => {
        console.log(res);
    });
}

完整代码如下:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Test</title>
    <link rel="stylesheet"
        href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.15.1/css/ol.css" type="text/css">
    <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.15.1/build/ol.js"></script>
    <style>
        html,
        body {
            height: 100%;
        }

        body {
            margin: 0;
            padding: 0;
        }

        #map {
            height: 100%;
        }
    </style>
</head>

<body>
    <button id="select">选择</button>
    <button id="modify">提交</button>
    <button id="exit">退出</button>
    <div id="map"></div>
    <script>
        const map = new ol.Map({
            target: 'map',
            layers: [],
            view: new ol.View({
                center: [147.01, -42.26],
                zoom: 8,
                projection: 'EPSG:4326'
            })
        });
        map.addLayer(new ol.layer.WebGLTile({
            source: new ol.source.OSM()
        }));
        const vectorLayer = new ol.layer.Vector({
            source: new ol.source.Vector({
                url: 'http://localhost:8080/geoserver/topp/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=topp:tasmania_roads&outputFormat=application/json',
                format: new ol.format.GeoJSON({
                    geometryName: 'the_geom'
                })
            }),
            style: new ol.style.Style({
                stroke: new ol.style.Stroke({
                    color: '#0000ff',
                    width: 2
                })
            })
        });
        map.addLayer(vectorLayer);

        document.querySelector('#select').addEventListener('click', (event) => {
            select.setActive(true);
        });
        document.querySelector('#exit').addEventListener('click', (event) => {
            select.setActive(false);
        });

        // 服务配置,命名空间、图层、服务地址等
        const geoserverData = {
            workSpaceName: 'topp',
            uri: 'http://www.openplans.org/topp',
            wfsURL: 'http://localhost:8080/geoserver/topp/ows?',
            layer: 'tasmania_roads'
        }

        // 选择要素控件
        let select = new ol.interaction.Select({
            layers: [vectorLayer],
            hitTolerance: 10
        });
        map.addInteraction(select);
        select.setActive(false);

        // 修改要素控件
        let modify = new ol.interaction.Modify({
            features: select.getFeatures()
        });
        // 保存修改完成的要素
        let modifiedFeatures = null;    // 用于保存被修改的要素
        modify.on('modifyend', (event) => {
            modifiedFeatures = event.features;
        });
        map.addInteraction(modify);

        document.querySelector('#modify').addEventListener('click', (event) => {
            let features = [];
            modifiedFeatures.forEach(function (item, index, array) {
                features.push(item);
            });
            updateWFS(features);
        });

        function updateWFS(features) {
            let WFS = new ol.format.WFS();
            // 生成XML格式的WFS请求信息
            let transact_xml = WFS.writeTransaction(
                null, features, null,
                {
                    srcName: 'EPSG:4326',
                    featureNS: geoserverData.uri,
                    featurePrefix: geoserverData.workSpaceName,
                    featureType: [geoserverData.layer],
                }
            )
            // 将XML格式请求信息序列化为字符串格式
            transact_str = (new XMLSerializer()).serializeToString(transact_xml);
            // 使用Fetch将请求发送到后端
            fetch('http://localhost:8080/geoserver/wfs', {
                method: 'POST',
                body: transact_str,
                headers: {
                    'Content-Type': 'text/xml'
                }
            }).then(res => res.text()).then(res => {
                let transactRes = WFS.readTransactionResponse(res);
                let str = transactRes.transactionSummary.totalInserted +
                    " totalInserted!, insertIds: " + transactRes.insertIds + "\n";
                str += transactRes.transactionSummary.totalUpdated + " totalUpdated!\n";
                str += transactRes.transactionSummary.totalDeleted + " totalDeleted!";
                alert(str);
            });
        }
    </script>

</body>

</html>

注意:

  • 此处加载WFS时需要指定geometryName
  • OpenLayers控件的使用可以参考官方API,Modify控件在Select控件选择后跟随圆点拖拽就行

修改后的结果如下:

image-20220725002000932

6. 删除要素

使用OpenLayers,删除要素的流程:

  • 加载初始要素
  • 创建选择控件选择要素
  • 将选择的要素和信息写为XML
  • 序列化XML
  • 提交XML到服务器

核心代码如下:

// 服务配置,命名空间、图层、服务地址等
const geoserverData = {
    workSpaceName: 'topp',
    uri: 'http://www.openplans.org/topp',
    wfsURL: 'http://localhost:8080/geoserver/topp/ows?',
    layer: 'tasmania_roads'
}

// 选择要素控件
let select = new ol.interaction.Select({
    layers: [vectorLayer],
    hitTolerance: 10
});
map.addInteraction(select);

document.querySelector('#delete').addEventListener('click', (event) => {
    let features = [];
    select.getFeatures().forEach(function (item, index, array) {
        features.push(item);
    });
    deleteWFS(features);
})

function deleteWFS(features) {
    let WFS = new ol.format.WFS();
    // 生成XML格式的WFS请求信息
    let transact_xml = WFS.writeTransaction(
        null, null, features,
        {
            srcName: 'EPSG:4326',
            featureNS: geoserverData.uri,
            featurePrefix: geoserverData.workSpaceName,
            featureType: [geoserverData.layer],
        }
    )
    // 将XML格式请求信息序列化为字符串格式
    transact_str = (new XMLSerializer()).serializeToString(transact_xml);
    // 使用Fetch将请求发送到后端
    fetch('http://localhost:8080/geoserver/wfs', {
        method: 'POST',
        body: transact_str,
        headers: {
            'Content-Type': 'text/xml'
        }
    }).then(res => res.text()).then(res => {
        console.log(res);
    });
}

完整代码如下:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Test</title>
    <link rel="stylesheet"
        href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.15.1/css/ol.css" type="text/css">
    <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.15.1/build/ol.js"></script>
    <style>
        html,
        body {
            height: 100%;
        }

        body {
            margin: 0;
            padding: 0;
        }

        #map {
            height: 100%;
        }
    </style>
</head>

<body>
    <button id="select">选择</button>
    <button id="delete">删除</button>
    <button id="exit">退出</button>
    <div id="map"></div>
    <script>
        const map = new ol.Map({
            target: 'map',
            layers: [],
            view: new ol.View({
                center: [147.01, -42.26],
                zoom: 8,
                projection: 'EPSG:4326'
            })
        });
        map.addLayer(new ol.layer.WebGLTile({
            source: new ol.source.OSM()
        }));
        const vectorLayer = new ol.layer.Vector({
            source: new ol.source.Vector({
                url: 'http://localhost:8080/geoserver/topp/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=topp:tasmania_roads&outputFormat=application/json',
                format: new ol.format.GeoJSON({
                    geometryName: 'the_geom'
                })
            }),
            style: new ol.style.Style({
                stroke: new ol.style.Stroke({
                    color: '#0000ff',
                    width: 2
                })
            })
        });
        map.addLayer(vectorLayer);

        document.querySelector('#select').addEventListener('click', (event) => {
            select.setActive(true);
        });
        document.querySelector('#exit').addEventListener('click', (event) => {
            select.setActive(false);
        });

        // 服务配置,命名空间、图层、服务地址等
        const geoserverData = {
            workSpaceName: 'topp',
            uri: 'http://www.openplans.org/topp',
            wfsURL: 'http://localhost:8080/geoserver/topp/ows?',
            layer: 'tasmania_roads'
        }

        // 选择要素控件
        let select = new ol.interaction.Select({
            layers: [vectorLayer],
            hitTolerance: 10
        });
        map.addInteraction(select);
        select.setActive(false);

        document.querySelector('#delete').addEventListener('click', (event) => {
            let features = [];
            select.getFeatures().forEach(function (item, index, array) {
                features.push(item);
            });
            deleteWFS(features);
        })

        function deleteWFS(features) {
            let WFS = new ol.format.WFS();
            // 生成XML格式的WFS请求信息
            let transact_xml = WFS.writeTransaction(
                null, null, features,
                {
                    srcName: 'EPSG:4326',
                    featureNS: geoserverData.uri,
                    featurePrefix: geoserverData.workSpaceName,
                    featureType: [geoserverData.layer],
                }
            )
            // 将XML格式请求信息序列化为字符串格式
            transact_str = (new XMLSerializer()).serializeToString(transact_xml);
            // 使用Fetch将请求发送到后端
            fetch('http://localhost:8080/geoserver/wfs', {
                method: 'POST',
                body: transact_str,
                headers: {
                    'Content-Type': 'text/xml'
                }
            }).then(res => res.text()).then(res => {
                let transactRes = WFS.readTransactionResponse(res);
                let str = transactRes.transactionSummary.totalInserted +
                    " totalInserted!, insertIds: " + transactRes.insertIds + "\n";
                str += transactRes.transactionSummary.totalUpdated + " totalUpdated!\n";
                str += transactRes.transactionSummary.totalDeleted + " totalDeleted!";
                alert(str);
            });
        }

    </script>

</body>

</html>

删除后的结果如下:

image-20220725005539772

7. 参考资料

[1]WFS - Introduction — OGC e-Learning 2.0.0 documentation (opengeospatial.github.io)

[2]WFS-简介 — OGC e-Learning 2.0.0 文档 (osgeo.cn)

[3]WFS参考 — GeoServer 2.19.x User Manual (osgeo.cn)

[4]使用.net c# 对GeoServer要素进行Insert和Delete操作_我是小怪兽-的博客-CSDN博客_c# geoserver

[5]开源GIS(十五)——openlayers通过geoserver中WFS删除要素_gis_morningsun的博客-CSDN博客

[6]OGC的网络要素服务(WFS)(持续更新。。。) - 知乎 (zhihu.com)

[7]OpenLayers v6.15.1 API - Class: WFS

[8]geoserver跨域 - 知乎 (zhihu.com)

标签:map,ol,let,GeoServer,改查,topp,OpenLayers,new,WFS
来源: https://www.cnblogs.com/jiujiubashiyi/p/16516062.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有