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("\\.");
// 防止使用中文名称通过工具类转换 你好-> nihao
return 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;
@Before
public void initGeoServerUtil() {
geoServerUtil = new GeoServerUtil("http://localhost:8888/geoserver", "admin", "geoserver");
}
/**
* 获取栅格bbox(Bounding Box)测试
*/
@Test
public 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文件
*/
@Test
public 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文件
*/
@Test
public void publishTiffsTest() {
geoServerUtil.publishTiffs("C:\\Users\\Administrator\\Desktop\\tif", "15000");
}
/**
* 发布矢量图层 shp
*/
@Test
public 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文件