GeoServer系列-java发布样式和应用样式
1,官方接口文档
https://docs.geoserver.org/latest/en/api/#1.0.0/styles.yaml
2,准备sld样式文件
能导出样式文件的软件很多,比如QGIS,ARCGISPRO,Udig,但是亲测只有udig导出的sld文件上传到geojson能正常预览
3,测试demo
根据官方文档的rest接口,实现上传,设置图层默认样式,删除样式,查询所有样式
实际生产中一个图层在前端可能会以多种样式展示,实际渲染哪种样式是有前端设置
import cn.hutool.http.HttpException;
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import com.cqdh.group.its.db.model.MapDispositionDO;
import okhttp3.*;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
public class GeoServerStyle {
public static void main(String[] args) throws IOException {
//GeoServer的连接配置
String url = "http://127.0.0.1:8016/geoserver";
String username = "admin";
String passwd = "geoserver";
String styleFile = "D:/测试文件/geoserver样式/绿地-蓝底绿边.sld";
//上传样式
publishStyle(url, username, passwd, styleFile);
//设置图层默认样式
String layerName = "test:faa87f497ac4f9a172b2bf5179ec9ccc";
//applyStyle(url + "/rest/layers/" + layerName, username, passwd, "绿地-蓝底绿边");
//删除样式(如果同名样式已存在,调用上传样式会报403重复的错误)
//delStyle(url + "/rest/styles/绿地-蓝底绿边", username, passwd);
//查询所有样式
//List<String> styleList = getStyles(url,username,passwd);
}
/**
* 发布样式
* curl -v -u admin:geoserver -X POST -H "Content-type: application/vnd.ogc.sld+xml" -T D:/测试文件/geoserver样式/stbhhx2.sld http://127.0.0.1:8016/geoserver/rest/styles?name=stbhhx2style
*
* @param url http://127.0.0.1:8016/geoserver
* @param username
* @param password
* @param styleFilePath D:/测试文件/geoserver样式/绿地-蓝底绿边.sld
*/
public static boolean publishStyle(String url, String username, String password, String styleFilePath) {
// 配置请求url和样式文件路径
String uploadUrl = url + "/rest/styles";
String styleName = styleFilePath.substring(styleFilePath.lastIndexOf("/") + 1).replace(".sld", "");
// 创建OkHttp客户端和请求体
OkHttpClient client = new OkHttpClient().newBuilder()
.authenticator((route, response) -> {
String credential = Credentials.basic(username, password);
return response.request().newBuilder().header("Authorization", credential).build();
})
.build();
RequestBody requestBody = RequestBody.create(MediaType.parse("application/vnd.ogc.sld+xml"), new File(styleFilePath));
// 构造请求
HttpUrl.Builder httpBuilder = HttpUrl.parse(uploadUrl).newBuilder();
httpBuilder.addQueryParameter("name", styleName);
String requestUrl = httpBuilder.build().toString();
Request request = new Request.Builder()
.url(requestUrl)
.post(requestBody)
.build();
// 发送请求并处理响应
Call call = client.newCall(request);
try {
Response response = call.execute();
if (response.isSuccessful()) {
System.out.println("添加样式成功");
return true;
} else {
if (response.body() != null && response.body().string().contains("already exists")) {
System.err.println("样式已存在. ");
return true;
} else {
System.err.println("添加样式失败. 错误信息: " + response.body().string());
return false;
}
}
} catch (Exception e) {
System.err.println("添加样式失败: " + e.getMessage());
return false;
}
}
/**
* 应用样式到指定图层
*
* @param url http://127.0.0.1:7012/geoserver/rest/layers/ws:layername
* @param username
* @param password
* @param styleName
*/
private static void applyStyle(String url, String username, String password, String styleName) {
try {
String client = username + ":" + password;
client = "Basic " + Base64.getEncoder().encodeToString(client.getBytes());
System.out.println("应用样式:" + url);
String res = HttpRequest.put(url)
.header("Authorization", client)
.header("content-type", "application/json")
.header("accept", "application/json")
.timeout(1000)
.body("{\"layer\":{\"defaultStyle\":{\"name\":\"#style\"}}}".replace("#style", styleName))
.execute().body();
System.out.println("应用样式:" + styleName + " -> " + url + ",结果:" + res);
} catch (HttpException e) {
System.out.println("应用图层样式失败");
}
}
/**
* curl -X DELETE http://localhost:8080/geoserver/rest/styles/ss?purge=true&recurse=true-H "accept: application/json" -H "content-type: application/json"
*
* @param delUrl
* @param username
* @param password
*/
public static void delStyle(String delUrl, String username, String password) {
OkHttpClient client = new OkHttpClient();
HttpUrl url = HttpUrl.parse(delUrl).newBuilder()
.addQueryParameter("purge", "true")
.addQueryParameter("recurse", "true")
.build();
String credential = Credentials.basic(username, password);
Request request = new Request.Builder()
.url(url)
.header("accept", "application/json")
.header("content-type", "application/json")
.header("Authorization", credential)
.delete()
.build();
try (Response response = client.newCall(request).execute()) {
if (response.isSuccessful()) {
System.out.println("样式删除成功 " + delUrl);
} else {
System.out.println("Error: " + response.code() + " " + response.message());
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 查询geoserver已发布的样式列表
*
* @return
*/
public static List<String> getStyles(String baseUrl, String username, String password) {
//http://127.0.0.1:8016/geoserver/rest/workspaces/test/datastores/DLTB/featuretypes/DLTB.json
if (!baseUrl.endsWith("/")) {
baseUrl = baseUrl + "/";
}
//先获取图层资源存储仓库 http://192.168.3.36:8089/geoserver/rest/workspaces/test/layers/aanp
String geoserverUrl = baseUrl + "rest/styles";
String client = username + ":" + password;
client = "Basic " + Base64.getEncoder().encodeToString(client.getBytes());
String result = null;
try {
result = getString(client, geoserverUrl, 3);
//log.info("查询图层仓库信息:{}", result);
JSONObject jsObject = new JSONObject(result);
Object obj = jsObject.get("styles");
if (obj instanceof String || "".equals(obj)) {
return null;
}
JSONObject jsObject2 = new JSONObject(obj);
JSONArray styleList = new JSONArray(jsObject2.get("style"));
if (styleList.size() == 0) {
return null;
}
List<String> styles = new ArrayList<>();
for (Object style : styleList) {
JSONObject styleInfo = new JSONObject(style);
styles.add((String) styleInfo.get("name"));
}
return styles;
} catch (Exception e) {
System.out.println("查询图层信息异常:" + e);
return null;
}
}
/**
* 循环请求
*
* @param client
* @param url
* @param reTrynum 重试次数
* @return
*/
private static String getString(String client, String url, int reTrynum) {
String result;
result = HttpRequest.get(url)
.header("Authorization", client)
.header("content-type", "application/json")
.header("accept", "application/json")
.timeout(1000)
.execute().body();
if (!result.startsWith("{") && reTrynum > 0) {
reTrynum--;
return getString(client, url, reTrynum);
}
return result;
}
}
4,前端指定样式预览
url = geoserver的服务地址 + /工作空间/+ wms
layers= 工作空间:图层名
styles= 样式名称 ,可以从上面的getStyles()方法获取geoserver上已发布的样式
// 添加wms服务
const addWmsServer = async (key: string, url: string, layers: string, style: string) => {
console.log('url', url)
console.log('layers', layers)
console.log('style', style)
// 待验证
viewer?.imageryLayers.remove(viewer.imageryLayers.get(2))
const imageryProvider = new Cesium.WebMapServiceImageryProvider({
url: "http://127.0.0.1:8016/geoserver/ws/wms",
layers: "ws:xxxx",
parameters: {
service: 'WMS',
format: 'image/png',
transparent: true,
styles: 'CONTOUR2绿色'
}
})
viewer.imageryLayers.addImageryProvider(imageryProvider)