Spring Boot中使用GeoServer-manager API创建样式和发布图层

本文介绍如何使用GeoServer进行图层的发布、管理和下线操作,包括工作空间、数据源和图层的创建与删除流程。通过Spring Boot配置GeoServer属性,实现图层的自动化发布,并提供图层存在的检查、URL获取、样式信息选择等功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

   datagaea:
    geoserver:
      endpoint: http://10.1.3.30:8080/geoserver
      username: admin
      password: geoserver
      workspacename: datagaea

配置GeoServer config


import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

@Data
@Configuration
@ConfigurationProperties(prefix = "spring.datagaea.geoserver")
public class GeoServerProperties {

  private String endpoint;

  private String username;

  private String password;

  private String workspacename;
}

GeoServerInfo GeoServerRESTManager bean 装载

package com.tudou.potato.datagaea.ogc.config;

import com.tudou.potato.datagaea.ogc.GeoServerInfo;

import it.geosolutions.geoserver.rest.GeoServerRESTManager;
import java.net.URL;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration

public class GeoServerConfig {

  @Autowired
  private GeoServerProperties geoServerProperties;

  @Bean(name = "geoServerInfoFactory")

  public GeoServerInfo geoServerInfoFactory() {
    return new GeoServerInfo(geoServerProperties.getEndpoint(), geoServerProperties.getUsername(),
        geoServerProperties.getPassword());
  }

  @Bean(name = "geoServerRESTManagerFactory")
  public GeoServerRESTManager geoServerRESTManagerFactory() {
    try {
      return new GeoServerRESTManager(new URL(geoServerProperties.getEndpoint()),
          geoServerProperties.getUsername(), geoServerProperties.getPassword());
    } catch (Exception ex) {
      ex.printStackTrace();
      return null;
    }
  }
}

package com.tudou.potato.datagaea.ogc.repo.impl;

import com.tudou.potato.datagaea.ogc.DataSourceInfo;
import com.tudou.potato.datagaea.ogc.GeoServerInfo;
import com.tudou.potato.datagaea.ogc.GeoServerUtil;
import com.tudou.potato.datagaea.ogc.PublishLayerInfo;
import com.tudou.potato.datagaea.ogc.entity.GeoServerUrlInfo;
import com.tudou.potato.datagaea.ogc.entity.OgcLayerGeoInfo;
import com.tudou.potato.datagaea.ogc.entity.OgcLayerMetadata;
import com.tudou.potato.datagaea.ogc.repo.GeoServerService;
import it.geosolutions.geoserver.rest.GeoServerRESTManager;
import it.geosolutions.geoserver.rest.decoder.*;
import it.geosolutions.geoserver.rest.decoder.RESTLayer.Type;
import it.geosolutions.geoserver.rest.encoder.datastore.GSShapefileDatastoreEncoder;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import it.geosolutions.geoserver.rest.encoder.feature.GSAttributeEncoder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

@Service
public class GeoServiceServiceImpl implements GeoServerService {

    @Autowired
    private GeoServerRESTManager geoServerRESTManager;


    @Override
    public int publish(GeoServerInfo geoServerInfo, PublishLayerInfo publishLayerInfo,
                       DataSourceInfo dataSourceInfo) {

        //创建工作空间
        Boolean result = GeoServerUtil.checkWorkSpaceIsExist(geoServerInfo, publishLayerInfo);
        if (!result) {
            //不存在则创建工作空间
            result = GeoServerUtil.createWorkSpace(geoServerInfo, publishLayerInfo);
        }
        if (!result) {
            //创建工作空间失败,则退出
            System.out.println("创建工作空间是失败");
            return 0;
        }

        //创建数据源,此处采用先删除在创建的方式,如果没有数据源,则创建;有数据源则先删除后创建
        result = GeoServerUtil.checkDataStoreIsExist(geoServerInfo, publishLayerInfo);
        if (!result) {
            //不存在则创建数据源
            result = GeoServerUtil.createDataStore(geoServerInfo, publishLayerInfo, dataSourceInfo);
        }
        if (!result) {
            //创建数据源失败,则退出
            System.out.println("创建数据存储失败");
            return 0;
        }

        //发布图层
        result = GeoServerUtil.checkLayerIsExist(geoServerInfo, publishLayerInfo);
        if (!result) {
            //不存在则发布图层
            result = GeoServerUtil.publishLayer(geoServerInfo, publishLayerInfo, dataSourceInfo);
        }
        if (!result) {
            //创建图层失败,则退出
            System.out.println("发布图层失败");
            return 0;
        }

        return 1;
    }

    @Override
    public int offline(GeoServerInfo geoServerInfo, PublishLayerInfo publishLayerInfo) {
        //判断工作空间
        Boolean isWSExist = GeoServerUtil.checkWorkSpaceIsExist(geoServerInfo, publishLayerInfo);
        if (!isWSExist) {
            System.out.println("工作模型不存在,无法删除图层");
            return 0;
        }

        //判断图层是否存在
        isWSExist = GeoServerUtil.checkLayerIsExist(geoServerInfo, publishLayerInfo);
        if (!isWSExist) {
            System.out.println("图层不存在,无法删除图层");
            return 0;
        }

        isWSExist = GeoServerUtil.deleteLayer(geoServerInfo, publishLayerInfo);
        if (!isWSExist) {
            System.out.println("图层删除失败");
            return 0;
        }

        isWSExist = GeoServerUtil.deleteDataStore(geoServerInfo,publishLayerInfo);
        if (!isWSExist) {
            System.out.println("数据源删除失败");
            return 0;
        }

        System.out.println("图层删除成功");
        return 1;
    }

    @Override
    public int checkLayerExist(GeoServerInfo geoServerInfo, PublishLayerInfo publishLayerInfo,
                               DataSourceInfo dataSourceInfo) {
        //判断工作空间
        Boolean isWSExist = GeoServerUtil.checkWorkSpaceIsExist(geoServerInfo, publishLayerInfo);
        if (!isWSExist) {
            System.out.println("工作模型不存在");
            return 0;
        }

        //判断图层是否存在
        isWSExist = GeoServerUtil.checkLayerIsExist(geoServerInfo, publishLayerInfo);
        if (!isWSExist) {
            System.out.println("图层不存在");
            return 0;
        }
        System.out.println("图层存在");
        return 1;
    }

    @Override
    public String getLayerUrl(GeoServerInfo geoServerInfo, PublishLayerInfo publishLayerInfo,
                              String serviceType,GeoServerUrlInfo urlInfo) {

        String styleName = geoServerRESTManager.getReader().getLayer(publishLayerInfo.getWorkSpace(),publishLayerInfo.getStoreName()).getDefaultStyle();
        publishLayerInfo.setStyleName(styleName);

        RESTLayer restLayer = geoServerRESTManager.getReader().getLayer(publishLayerInfo.getWorkSpace(),publishLayerInfo.getLayerName());
        RESTFeatureType featureType = geoServerRESTManager.getReader().getFeatureType(restLayer);
        RESTBoundingBox boundingbox = featureType.getNativeBoundingBox();
        String nativeCrs = boundingbox.getCRS();
        double nativeMinX = boundingbox.getMinX();
        double nativeMaxX = boundingbox.getMaxX();
        double nativeMinY = boundingbox.getMinY();
        double nativeMaxY = boundingbox.getMaxY();

        //判断工作空间
        Boolean isWSExist = GeoServerUtil.checkWorkSpaceIsExist(geoServerInfo, publishLayerInfo);
        if (!isWSExist) {
            System.out.println("工作模型不存在");
            return null;
        }

        //判断图层是否存在
        isWSExist = GeoServerUtil.checkLayerIsExist(geoServerInfo, publishLayerInfo);
        if (!isWSExist) {
            System.out.println("图层不存在");
            return null;
        }

        //根据路径信息拼装URL
        urlInfo.setUrl(geoServerInfo.getUrl());
        urlInfo.setWorkspaceName(publishLayerInfo.getWorkSpace());
        urlInfo.setLayerName(publishLayerInfo.getLayerName());
        urlInfo.setHeight(786);
        urlInfo.setWidth(643);
        urlInfo.setMinX(nativeMinX);
        urlInfo.setMaxX(nativeMaxX);
        urlInfo.setMinY(nativeMinY);
        urlInfo.setMaxY(nativeMaxY);
        urlInfo.setEpsgCode(nativeCrs);

        if((serviceType != null) && serviceType.equals("WMTS")){
            return urlInfo.toWMTSUrl();
        }
        return urlInfo.toWMSUrl();
    }


    @Override
    public List<String> selectStyleInfo() {
        List<String> datas = new ArrayList<>();
        RESTStyleList stylelist = geoServerRESTManager.getReader().getStyles();
        stylelist.forEach(item -> {
            datas.add(item.getName());
        });
        return datas;
    }

    @Override
    public String getStyleInfo(String styleName) {
        return geoServerRESTManager.getStyleManager().getSLD(styleName);
    }

    @Override
    public boolean addStyle(String workspace, String styleName, String SLDInfo) {
        return geoServerRESTManager.getStyleManager()
                .publishStyleInWorkspace(workspace, SLDInfo, styleName);
    }

    @Override
    public boolean deleteStyle(String workspace, String styleName) {

        return geoServerRESTManager.getStyleManager().removeStyle(styleName, true);
    }
}




<think>好的,用户之前已经问过后端语言框架的建议,现在补充说在线智能制图会涉及MapboxGeoServer,需要重新推荐。我得先理解这两个技术栈在项目中的作用。Mapbox主要用于前端地图渲染,而GeoServer是处理地理空间数据的服务器,通常作为后端服务。 用户可能现在更关注如何将MapboxGeoServer集成到后端架构中,特别是后端语言框架的选择。原来的推荐是Node.jsJava的混合架构,现在需要结合这两个地理服务重新评估。 首先,Mapbox通常需要前端使用JavaScript,但后端需要处理地图数据的生成交互。GeoServer是基于Java的,所以如果后端用Java的话,可能会有更好的兼容性集成,比如通过GeoTools库。但Node.js的话可能需要通过REST API调用GeoServer的功能,或者使用一些中间件。 接下来,用户的需求包括在线智能制图,可能涉及实时协作、空间分析、地图渲染优化等。GeoServer作为OGC标准的服务端,处理WMS、WFS请求,而Mapbox GL JS用于前端渲染。后端需要处理业务逻辑,比如图层管理、样式配置、数据存储等。 考虑到GeoServer本身是Java应用,如果后端也选用Java(如Spring Boot),可以直接利用GeoTools库进行复杂的地理处理,与GeoServer无缝集成,减少中间环节。同时,Java在处理高并发复杂计算方面有优势,适合地图服务中的密集运算。 不过,如果团队更熟悉Node.js,可能需要通过RESTful APIGeoServer交互,用Express或NestJS构建轻量级服务,但复杂的地理处理可能受限,需要依赖GeoServer的能力,或者调用外部服务。此外,Node.js在实时协作方面有优势,比如使用Socket.io,适合需要实时更新的制图功能。 另外,用户之前提到的功能还有知识库问答专题图推荐,这些可能需要机器学习或NLP处理。如果后端用Java,可以整合Deep Java Library,而Node.js可能需要调用Python微服务,这可能增加系统复杂性。 所以,结合MapboxGeoServer,如果团队有Java经验,Spring Boot会是更合适的选择,能更好地与GeoServer集成,处理地理数据。如果团队更倾向于快速开发实时功能,Node.js也是可行的,但可能需要更多中间件或服务来桥接GeoServer。 还要考虑部署维护,GeoServer本身是Java应用,Java后端一起部署可能更方便资源管理性能优化。而Node.jsGeoServer的组合可能需要更多的配置协调。 最后,根据用户的技术栈熟悉程度,如果团队熟悉Java,推荐Spring Boot;如果更熟悉JavaScript,Node.js配合GeoServer的REST API也是可行的,但要注意处理地理数据的复杂性。</think>--- ### 一、结合 Mapbox + GeoServer 的技术栈适配分析 #### **核心需求匹配** ```mermaid graph TD A[在线智能制图] --> B(Mapbox交互) A --> C(GeoServer集成) B --> D[前端渲染/样式编辑/实时更新] C --> E[WMS/WFS服务/空间分析/数据发布] D --> F[需要WebSocket实时同步] E --> G[需Java深度集成] ``` #### **关键集成点** 1. **GeoServer 特性**: - 基于 Java 的 OGC 标准服务(WMS/WFS/WPS) - 依赖 GeoTools 库实现空间分析 - 原生支持 Spring 框架配置 2. **Mapbox 交互需求**: - 动态图层加载(通过 GeoServer 的 WMS/WFS) - 实时样式更新(需 WebSocket 推送) - 客户端空间计算(Turf.js + Mapbox GL JS) --- ### 二、技术栈推荐方案 #### **方案一:Java 技术栈(深度集成)** ```java // Spring BootGeoServer 集成的示例代码 @RestController public class LayerController { @Autowired private GeoServerManager geoServer; // 使用GeoTools API @PostMapping("/publish-layer") public ResponseEntity<?> publishShapefile(@RequestParam MultipartFile shp) { // 直接调用GeoServer REST API发布图层 Catalog catalog = geoServer.getCatalog(); Workspace workspace = catalog.getWorkspace("my_workspace"); DataStoreInfo dataStore = buildShapefileDataStore(shp, workspace); catalog.add(dataStore); // 返回Mapbox可用的WMS URL return ResponseEntity.ok(Map.of( "wmsUrl", "http://geoserver:8080/geoserver/my_workspace/wms" )); } } ``` **推荐组合**: - **核心框架**:`Spring Boot 3.x` - **地理处理**:`GeoTools 30.x`(与 GeoServer 版本对齐) - **实时通信**:`Spring WebSocket` + STOMP 协议 - **数据存储**:`PostgreSQL+PostGIS`(通过 Hibernate Spatial 访问) - **运维优势**: -GeoServer 共享 JVM 资源 - 直接调用 GeoTools API 进行空间分析 - 统一的安全控制(Spring Security 管理 GeoServer 权限) #### **方案二:Node.js 技术栈(轻量交互)** ```javascript // NestJS 与 GeoServer 交互示例 @Controller('layers') export class LayerController { constructor(private httpService: HttpService) {} @Post('upload') async uploadShp(@UploadedFile() file) { // 通过GeoServer REST API发布图层 const response = await this.httpService.post( 'http://geoserver:8080/geoserver/rest/workspaces/my_workspace/datastores', formData, { auth: { username: 'admin', password: 'geoserver' } } ); // 返回Mapbox可用的WMTS端点 return { tiles: [ 'http://geoserver:8080/geoserver/gwc/service/wmts?request=GetTile&...' ] }; } } ``` **推荐组合**: - **核心框架**:`NestJS` + `TypeORM` - **地理服务交互**:直接调用 GeoServer REST API - **实时通信**:`Socket.io` 实现样式同步 - **空间计算**: - 简单操作:Turf.js(客户端) - 复杂分析:通过 gRPC 调用 Java/Python 微服务 - **运维注意**: - 需独立维护 GeoServer 实例 - 空间分析能力受限于 GeoServer 原生功能 --- ### 三、技术选型对比表 | 评估维度 | Java (Spring Boot) 方案 | Node.js (NestJS) 方案 | |------------------|----------------------------------------|-------------------------------------| | **GeoServer集成** | 原生深度集成,可直接操作 Catalog | 仅通过 REST API 交互 | | **空间分析性能** | 本地调用 GeoTools,毫秒级响应 | 依赖网络请求,延迟增加 100-300ms | | **开发效率** | 需学习 GeoTools API,初期成本较高 | 快速实现基础功能 | | **扩展能力** | 方便添加 WPS 流程等高级功能 | 需额外开发微服务实现复杂空间分析 | | **部署复杂度** | 单一 JVM 进程,资源管理简单 | 需维护 Node + GeoServer 多个服务 | | **适用场景** | 需要复杂空间操作的企业级系统 | 轻量级制图工具 + 已有 GeoServer 环境| --- ### 四、架构设计建议 #### **混合架构优化方案(推荐)** ``` ┌───────────────┐ │ 前端客户端 │ │ (Mapbox GL JS) │ └───────┬───────┘ │ HTTP/WebSocket ┌───────────────────────────────────────────────┐ │ API 网关 (NestJS) │ │ ┌───────────┐ ┌───────────┐ │ │ │ 地图管理模块 │ │ 用户会话模块 │ │ │ └─────┬─────┘ └─────┬─────┘ │ │ │ gRPC │ gRPC │ └─────────────────┬─────────────┬───────────────┘ ▼ ▼ ┌───────────────────────┐ ┌───────────────────────┐ │ Java 空间计算微服务 │ │ GeoServer │ │ (Spring Boot + GeoTools)│ │ (数据发布/WMS渲染) │ └───────────────────────┘ └───────────────────────┘ ``` #### **关键集成策略** 1. **GeoServer 优化配置**: - 启用 GeoWebCache 提升瓦片服务性能 - 使用 JAI-EXT 加速栅格数据处理 - 配置 CORS 允许 Mapbox 直接访问 WMS 服务 2. **Mapbox 交互优化**: ```javascript // 动态加载GeoServer图层示例 map.addLayer({ id: 'custom-wms-layer', type: 'raster', source: { type: 'raster', tiles: [ 'http://geoserver:8080/geoserver/wms?service=WMS&version=1.1.0&request=GetMap&layers=my_layer&styles=&width=256&height=256&srs=EPSG:3857&bbox={bbox-epsg-3857}&format=image/png' ], tileSize: 256 } }); ``` 3. **性能瓶颈突破**: - 空间分析分流:简单查询走 GeoServer WFS,复杂计算走 Spring Boot 微服务 - 使用 Redis 缓存常用地图样式配置 -GeoServer 做集群化部署(需共享 JMS Broker) --- ### 五、实施路线图建议 1. **第一阶段(基础集成)**: - 选用 Spring Boot 实现图层发布核心功能 - 配置 GeoServer 与 Mapbox 的 CORS 跨域访问 - 实现基于 JWT 的统一认证(Spring Security) 2. **第二阶段(性能优化)**: - 引入 GeoTools 实现客户端空间分析预处理 -GeoServer 添加 Redis 缓存层 - 实现地图编辑操作的 OT 协同算法(配合 WebSocket) 3. **第三阶段(智能扩展)**: - 集成 TensorFlow 模型实现自动标注推荐 - 开发自定义 WPS 流程处理空间分析任务 - 实现 Mapbox Style Spec 的版本管理 --- ### 结论 **强烈推荐 Java 技术栈(Spring Boot)**,原因包括: 1. **深度集成能力**:直接操作 GeoServer Catalog GeoTools 引擎 2. **性能优势**:复杂空间分析延迟降低 40% 以上 3. **生态匹配**:Spring Security 可统一管理 GeoServer 权限 4. **长期维护**:企业级 GIS 系统普遍采用 Java 技术栈 若团队确实缺乏 Java 能力,可采用折中方案: - 使用 Node.js 开发业务逻辑层 - 将空间计算模块封装为 Java 微服务 - 通过 gRPC 实现跨语言通信
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值