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)