1. Maven依赖
栅格文件对应Tif文件 (即: 栅格就是tif)
矢量文件对应shp文件(即: 矢量就是shp)
注: 有的依赖可能在中央仓库及一些镜像仓库找不到需要手动指定仓库, 在依赖最下方
<!-- 中文转拼音工具类 --><dependency><groupId>com.belerweb</groupId><artifactId>pinyin4j</artifactId><version>2.5.0</version></dependency><!-- 工具类 --><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.3</version></dependency><!-- geoserver管理工具类 --><dependency><groupId>it.geosolutions</groupId><artifactId>geoserver-manager</artifactId><version>1.7.0</version></dependency><!-- geojson工具类 --><dependency><groupId>org.geotools</groupId><artifactId>gt-geojson</artifactId><version>25.3.01</version></dependency><!-- geoserver数据库工具类 --><dependency><groupId>org.geotools</groupId><artifactId>gt-epsg-hsql</artifactId><version>24.2</version></dependency><!-- 中央仓库没有 gt-geotiff, gt-shapefile 指定新的仓库 --><repositories><repository><id>GeoSolutions</id><url>http://maven.geo-solutions.it/</url></repository></repositories>
2. GeoServerUtil工具类
工具类主要方法如下:
- 发布tif
- 发布shp
- 获取栅格bbox (Bounding Box) 经纬度边界
- 获取矢量bbox (Bounding Box) 经纬度边界
等
注: 其中使用到了
pinyin4j
主要防止文件命名是中文, 使用改工具类可以使中文转换为拼音 默认非大小驼峰命名
, 可根据需要自行更改.'你好'->'nihao'
import cn.hutool.core.io.FileUtil;
import cn.hutool.extra.pinyin.engine.PinyinFactory;
import it.geosolutions.geoserver.rest.GeoServerRESTManager;
import it.geosolutions.geoserver.rest.GeoServerRESTPublisher;
import it.geosolutions.geoserver.rest.GeoServerRESTReader;
import it.geosolutions.geoserver.rest.decoder.*;
import it.geosolutions.geoserver.rest.encoder.GSLayerGroupEncoder;
import it.geosolutions.geoserver.rest.encoder.GSResourceEncoder;
import it.geosolutions.geoserver.rest.encoder.datastore.GSShapefileDatastoreEncoder;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.io.File;
import java.io.FileNotFoundException;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.List;/*** @author Cookie* @date 2024/8/22* @desc GeoServerUtil*/
public class GeoServerUtil {private static final Logger logger = LoggerFactory.getLogger(GeoServerUtil.class);public static GeoServerRESTManager geoServerRESTManager;public static GeoServerRESTManager buildManager(String url, String username, String password) {try {if (geoServerRESTManager == null)geoServerRESTManager = new GeoServerRESTManager(new URL(url), username, password);return geoServerRESTManager;} catch (MalformedURLException e) {logger.error("GeoServer连接失败,请检查连接地址是否正确");logger.error(e.getMessage(), e);return null;}}private String url;private String username;private String password;public GeoServerUtil(String url, String username, String password) {this.url = url;this.username = username;this.password = password;}public GeoServerUtil() {}/*** 发布shp文件* 要求: 压缩包名称和压缩包内所有的文件名的名字相同并且只有一级* 示例:* shp_demo.zip:* * * shp_demo.dbf* * * shp_demo.fix* * * shp_demo.prj* * * shp_demo.shp* * * shp_demo.shx** @param zipFile shp压缩文件路径* @param workspace 工作空间* @param store 存储仓库* @param layerName 图层名* @param layerGroup 图层组* @param layerStyle 图层样式*/public boolean publishShp(String zipFile, String workspace, String store, String layerName, String layerGroup, String layerStyle) {if (verifyFileExists(new File(zipFile))) return false;if (StringUtils.isEmpty(layerStyle))layerStyle = "polygon";GeoServerRESTManager geoServerRESTManager = buildManager(this.url, this.username, this.password);if (geoServerRESTManager == null)throw new RuntimeException("GeoServer连接失败");GeoServerRESTPublisher publisher = geoServerRESTManager.getPublisher();//创建工作空间List<String> workspaceNames = geoServerRESTManager.getReader().getWorkspaceNames();logger.info("存在的workspace:{}", workspaceNames);if (!workspaceNames.contains(workspace)) {if (!publisher.createWorkspace(workspace)) {return false;}}//创建存储RESTDataStore datastore = geoServerRESTManager.getReader().getDatastore(workspace, store);try {if (datastore == null) {String str = File.separator;if (str.equals("\\")) {str = "\\\\";}String[] split = zipFile.split(str);String name = split[split.length - 1];name = name.substring(0, name.lastIndexOf("."));String urlDatastore = "file:data/" + workspace + "/" + name + "/" + name + ".shp";GSShapefileDatastoreEncoder storeEncoder = new GSShapefileDatastoreEncoder(store, new URL(urlDatastore));storeEncoder.setCharset(StandardCharsets.UTF_8);if (!geoServerRESTManager.getStoreManager().create(workspace, storeEncoder)) {return false;}}//发布图层if (!publisher.publishShp(workspace, store, new NameValuePair[]{new NameValuePair("charset", "utf-8")}, layerName,GeoServerRESTPublisher.UploadMethod.FILE, new File(zipFile).toURI(), "EPSG:4326", layerStyle)) {return false;}} catch (FileNotFoundException e) {logger.error("文件不存在:{}", e.getMessage());throw new RuntimeException("文件不存在");} catch (MalformedURLException e) {logger.error("URL格式错误:{}", e.getMessage());throw new RuntimeException("URL格式错误");}if (layerGroup != null) {//加入图层组RESTLayerGroup restLayerGroup = geoServerRESTManager.getReader().getLayerGroup(workspace, layerGroup);GSLayerGroupEncoder gsLayerGroupEncoder = new GSLayerGroupEncoder();gsLayerGroupEncoder.addLayer(layerName);if (restLayerGroup == null) {geoServerRESTManager.getPublisher().createLayerGroup(workspace, layerGroup, gsLayerGroupEncoder);} else {geoServerRESTManager.getPublisher().configureLayerGroup(workspace, layerGroup, gsLayerGroupEncoder);}}return true;}/*** 发布shp文件** @param zipFile shp压缩文件路径* @param workspace 工作空间* @param layerGroup 图层组* @param layerStyle 图层样式*/public boolean publishShp(String zipFile, String workspace, String layerGroup, String layerStyle) {File file = new File(zipFile);if (verifyFileExists(file)) return false;String fileName = getFileName(file);return publishShp(zipFile, workspace, fileName, fileName, layerGroup, layerStyle);}/*** 发布shp文件** @param zipFile shp压缩文件路径* @param workspace 工作空间* @param layerGroup 图层组*/public boolean publishShp(String zipFile, String workspace, String layerGroup) {return publishShp(zipFile, workspace, layerGroup, null);}public boolean deleteStore(String workspace, String storeName) {GeoServerRESTManager geoServerRESTManager = buildManager(this.url, this.username, this.password);if (geoServerRESTManager == null)throw new RuntimeException("GeoServer连接失败");GeoServerRESTPublisher publisher = geoServerRESTManager.getPublisher();return publisher.removeDatastore(workspace, storeName, false);}/*** 获取栅格bbox** @param workspace 工作空间* @param store 存储仓库* @param layerName 图层名称* @return [minX, minY, maxX, maxY]*/public double[] getTiffBbox(String workspace, String store, String layerName) {GeoServerRESTManager restManager = buildManager(this.url, this.username, this.password);if (restManager == null)throw new RuntimeException("GeoServer连接失败");GeoServerRESTReader reader = restManager.getReader();RESTCoverage coverage = reader.getCoverage(workspace, store, layerName);RESTBoundingBox nativeBoundingBox = coverage.getNativeBoundingBox();return new double[]{nativeBoundingBox.getMinX(), nativeBoundingBox.getMinY(), nativeBoundingBox.getMaxX(), nativeBoundingBox.getMaxY()};}/*** 获取栅格bbox(Bounding Box)* store和layerName相同** @param workspace 工作空间* @param layerName 图层名称* @return [minX, minY, maxX, maxY]*/public double[] getTiffBbox(String workspace, String layerName) {return getTiffBbox(workspace, layerName, layerName);}/*** 获取矢量bbox(Bounding Box)* 经纬度边框** @param workspace 工作空间* @param layerName 图层名称* @return min(x, y) max(x,y)*/public double[] getShpBbox(String workspace, String layerName) {GeoServerRESTReader reader = geoServerRESTManager.getReader();RESTLayer layer = reader.getLayer(workspace, layerName);RESTFeatureType featureType = reader.getFeatureType(layer);RESTBoundingBox nativeBoundingBox = featureType.getNativeBoundingBox();return new double[]{nativeBoundingBox.getMinX(), nativeBoundingBox.getMinY(), nativeBoundingBox.getMaxX(), nativeBoundingBox.getMaxY()};}/*** 发布tif文件** @param filePath 文件路径* @param workspace 工作空间* @param styleName 样式名称 (样式不存在默认为空)* @param store 存储仓库* @param layerName 图层名称* @return true/false*/public boolean publishTiff(String filePath, String workspace, String styleName, String store, String layerName) {if (verifyFileExists(new File(filePath))) return false;if (StringUtils.isEmpty(styleName))// 默认样式名称styleName = "raster";GeoServerRESTManager geoServerRESTManager = buildManager(this.url, this.username, this.password);if (geoServerRESTManager == null)throw new RuntimeException("GeoServer连接失败");GeoServerRESTPublisher publisher = geoServerRESTManager.getPublisher();//创建工作空间List<String> workspaceNames = geoServerRESTManager.getReader().getWorkspaceNames();if (!workspaceNames.contains(workspace) && !publisher.createWorkspace(workspace))return false;try {return publisher.publishGeoTIFF(workspace, store, layerName, new File(filePath), "EPSG:4326", GSResourceEncoder.ProjectionPolicy.NONE, styleName, null);} catch (Exception e) {logger.error("发布tif文件失败: 异常信息{}", e.getMessage());return false;}}/*** 发布tiff文件* 使用默认coverageName和store** @param filePath 文件路径样式* @param workspace 工作空间* @param styleName 样式名称* @return 是否发布成功*/public boolean publishTiff(String filePath, String workspace, String styleName) {File file = new File(filePath);if (verifyFileExists(file)) return false;String fileName = getFileName(file);return publishTiff(filePath, styleName, fileName, workspace, fileName);}/*** 发布tiff文件* 使用默认coverageName和store** @param filePath 文件路径样式* @param workspace 工作空间* @return 是否发布成功*/public boolean publishTiff(String filePath, String workspace) {File file = new File(filePath);if (verifyFileExists(file)) return false;String fileName = getFileName(file);return publishTiff(filePath, "", fileName, workspace, fileName);}/*** 发布多个TIFF文件* 注: 存储仓库默认使用文件名** @param localFolder 本地文件夹路径* @param workspace 命令空间* @param styleName 矢量或栅格图层使用的样式(不传使用默认样式)*/public void publishTiffs(String localFolder, String workspace, String styleName) {List<File> files = FileUtil.loopFiles(localFolder, file -> file.getName().endsWith(".tif"));for (File file : files) {String fileName = getFileName(file);System.err.println("文件路径:" + file.getAbsolutePath());// 使用默认样式boolean publish = false;try {publish = publishTiff(file.getPath(), workspace, styleName, fileName, fileName);} catch (Exception e) {System.err.println("发布失败: " + e.getMessage());}System.out.println(file.getName() + "发布结果:" + (publish ? "成功" : "失败"));}}/*** 发布多个TIFF文件* 注: 存储仓库默认使用文件名** @param localFolder 本地文件夹路径* @param workspace 命令空间*/public void publishTiffs(String localFolder, String workspace) {publishTiffs(localFolder, workspace, null);}/*** 获取文件名* 注: 支持中文转换为拼音** @param file FILE* @return 文件名*/private static String getFileName(File file) {String[] split = file.getName().split("\\.");// 防止使用中文名称通过工具类转换 你好-> nihaoreturn PinyinFactory.get().getPinyin(split[0], "");}/*** 校验文件是否存在** @param file file* @return*/private static boolean verifyFileExists(File file) {if (!file.exists()) {logger.error("文件不存在");return true;}return false;}}
3. 工具类测试
其中有一些重载方法可根据需要自行修改
/*** @Author Cookie* @Date 2024/8/22* @Desc*/
public class GeoserverTest {private GeoServerUtil geoServerUtil;@Beforepublic void initGeoServerUtil() {geoServerUtil = new GeoServerUtil("http://localhost:8888/geoserver", "admin", "geoserver");}/*** 获取栅格bbox(Bounding Box)测试*/@Testpublic void getTiffBboxTest() {// 这里重载了一个方法,手动指定仓库名称. 默认仓库名等于文件名double[] shpBbox = geoServerUtil.getTiffBbox("15000", "20240819_yumi");System.out.println(Arrays.toString(shpBbox));// [minX, minY, maxX, maxY]// [112.92316424712779, 47.753672584652726, 113.22898940248196, 48.01270170916157]}/*** 发布tif文件*/@Testpublic void publishTiffTest() {// 重载方法一: 默认仓库名等于文件名
// geoServerUtil.publishTiff("C:\\Users\\Administrator\\Desktop\\tif\\2024_dadou.tif", "15000");// 重载方法二: 指定图层样式
// geoServerUtil.publishTiff("C:\\Users\\Administrator\\Desktop\\tif\\2024_dadou.tif", "15000", "raster-dadou");// 重载方法三: 指定图层名称和仓库名称geoServerUtil.publishTiff("C:\\Users\\Administrator\\Desktop\\tif\\20240819_dadou.tif", "15000", "raster-dadou-out", "dadou_store", "dadou1");}/*** 批量发布tif文件*/@Testpublic void publishTiffsTest() {geoServerUtil.publishTiffs("C:\\Users\\Administrator\\Desktop\\tif", "15000");}/*** 发布矢量图层 shp*/@Testpublic void publishShpTest() throws Exception {// 重载方法一: 默认图层名称等于文件名geoServerUtil.publishShp("C:\\Users\\Administrator\\Desktop\\neihuang_2800.zip", "15000", "neihuang");// 重载方法二: 指定样式geoServerUtil.publishShp("C:\\Users\\Administrator\\Desktop\\neihuang_2800.zip", "15000", "neihuang", "polygon");// 重载方法三: 全指定geoServerUtil.publishShp("C:\\Users\\Administrator\\Desktop\\neihuang_2800.zip", "15000", "neihuang_store", "neihuang_2024", "neihuang", "polygon");}
4. 结果查看
如果shp文件点击
图层预览
的OpenLayers
后是直接下载本地, 检查一下图层的样式是否正确
1. tif文件查看
在geoserver中的
图层预览
和图层
中都可以看到这两个图层, 点击OpenLayers
可查看图层,
给图层绑定一下样式得到如下效果:
到这里基本就完成了图层的发布. 图层打开后的链接, 换成公网可以访问的链接就可以给前端的同事使用了.
关于样式的发布可以参考官方文档 geoserverSLD造型
2.shp文件查看
示例如下:
如果依赖一直拉不下来可以试试下面的方式清理一下本地maven仓库中的 .lastUpdated文件
重新下载
maven快速清除lastUpdated文件