通过Java代码自动发布Geoserver的地图服务WMS

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

GeoServer 顾名思义。是一个Server,它是开源的,允许用户查看和编辑地理数据的服务器,它可以比较容易的在用户之间迅速共享空间地理信息。利用Geoserver可以把数据作为maps/images来发布(利用WMS来实现)也可以直接发布实际的数据(利用WFS来实现),它同时也提供了修改,删除和新增的功能(利用WFS-T)。

为什么要使用GeoServer?相比较同类产品ArcServer不是一个开源GIS服务器,所有想在Web地图应用开发中使用ArcServer就需要付费,而且价格比较高(ref:GeoServer与ArcServer对比)。本文将完成用ArcGIS切片好的数据,通过代码自动发布Geoserver 中。如果不清楚手动发布流程和实现的效果,可以看我的另外一篇文章:GeoServer手动发布本地Shapefile地图。

一、引入pom依赖

指定远程仓库


      GeoSolutions
      http://maven.geo-solutions.it/
   

加入dependency 


    it.geosolutions
    geoserver-manager
    1.7.0
  

二、编写发布工具类

常量类Constants

public class Constant {

    public static final int BYTE_BUFFER = 1024;

    public static final int BUFFER_MULTIPLE = 10;

    /**
     * 县图集类型
     */
    public class AtlasType {
        //点位图
        public static final String ATLAS_TYPE_1 = "1";
        //单元图
        public static final String ATLAS_TYPE_2 = "2";
        //土壤类型图
        public static final String ATLAS_TYPE_3 = "3";
        //评价结果表
        public static final String ATLAS_TYPE_4 = "4";
    }

    public class FileType{
        public static final int FILE_IMG = 1;
        public static final int FILE_ZIP = 2;
        public static final int FILE_VEDIO= 3;
        public static final int FILE_APK = 4;
        public static final int FIVE_OFFICE = 5;
        public static final String FILE_IMG_DIR= "/img/";
        public static final String FILE_ZIP_DIR= "/zip/";
        public static final String FILE_VEDIO_DIR= "/video/";
        public static final String FILE_APK_DIR= "/apk/";
        public static final String FIVE_OFFICE_DIR= "/office/";
    }


    public static String parseAtlasTypeToName(String type){
        String typeName="";
        switch (type){
            case AtlasType.ATLAS_TYPE_1: typeName="bitMap"; break;
            case AtlasType.ATLAS_TYPE_2: typeName="unitMap"; break;
            case AtlasType.ATLAS_TYPE_3: typeName="typeMap"; break;
            default:break;
        }
        return  typeName;
    }

    public static class FilePostFix{
        public static final String ZIP_FILE =".zip";

        public static final String [] IMAGES ={"jpg", "jpeg", "JPG", "JPEG", "gif", "GIF", "bmp", "BMP"};
        public static final String [] ZIP ={"ZIP","zip","rar","RAR"};
        public static final String [] VIDEO ={"mp4","MP4","mpg","mpe","mpa","m15","m1v", "mp2","rmvb"};
        public static final String [] APK ={"apk","exe"};
        public static final String [] OFFICE ={"xls","xlsx","docx","doc","ppt","pptx"};

    }

    public class Atlas {
        public static final int ATLAS_FIELD_STATUS_HIDE = 0;
        public static final int ATLAS_FIELD_STATUS_SHOW = 1;
    }

}

发布工具类

import it.geosolutions.geoserver.rest.GeoServerRESTManager;
import it.geosolutions.geoserver.rest.GeoServerRESTPublisher;
import it.geosolutions.geoserver.rest.GeoServerRESTReader;
import org.apache.commons.httpclient.NameValuePair;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ResourceBundle;

public class GeoServerUtil {
    public static final String RESTURL;

    public static final String RESTUSER;

    public static final String RESTPW;

    public static final String GS_VERSION;

    public static java.net.URL URL;

    public static GeoServerRESTManager manager;

    public static GeoServerRESTReader reader;

    public static GeoServerRESTPublisher publisher;

    private static ResourceBundle bundle = ResourceBundle.getBundle("constant");

   //初始化用户名密码赋值,发布图集时会进行身份认证
    static {
        RESTURL = getenv("gsmgr_resturl", "http://localhost:18080/geoserver/");
        RESTUSER = getenv("gsmgr_restuser","admin");
        RESTPW = getenv("gsmgr_restpw", "geoserver");
        GS_VERSION = getenv("gsmgr_version", "2.11.2");
        try {
            URL = new URL(RESTURL);
            manager = new GeoServerRESTManager(URL, RESTUSER, RESTPW);
            reader = manager.getReader();
            publisher = manager.getPublisher();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
    }

   //获取环境信息
    private static String getenv(String envName, String envDefault) {
        String env = System.getenv(envName);
        String prop = System.getProperty(envName, env);
        return prop != null ? prop : envDefault;
    }

    public  static boolean  publishShpAndReloadStore(String workspace,String zipFilePath,String storeName,String layerName,String styleType,String coordinateSystem) throws  Exception{
        //坐标系,判断是否为空
        if(ComUtil.isEmpty(coordinateSystem)){
            coordinateSystem=GeoServerRESTPublisher.DEFAULT_CRS;
        }
        //存在相应的工作区
        if(!reader.existsWorkspace(workspace)){
            publisher.createWorkspace(workspace);
        }
        boolean published;
        if(Constant.AtlasStyleType.ATLAS_STYLE_TYPE_5.equals(styleType)){
             published = publisher.publishShp(workspace, storeName, layerName, new File(zipFilePath),coordinateSystem,
                                  new NameValuePair[]{new NameValuePair("charset", "GBK")});
        }else{
            //读取style文件
            String styleFile = bundle.getString("geoServer-dir")+"/"+styleType+".sld";
            File file  = new File(styleFile);
            String strStyle = "style"+styleType;
            //是否已经发布了改style
            if(!reader.existsStyle(workspace,strStyle)){
                publisher.publishStyleInWorkspace(workspace,file,strStyle);
            }
            //创建发布类,放入用户名密码和url
            GeoServerRESTPublisher geoServerRESTPublisher  =new GeoServerRESTPublisher(RESTURL,RESTUSER,RESTPW);
                                                        //工作区      数据存储名称
            published =geoServerRESTPublisher.publishShp( workspace,  storeName, new NameValuePair[]{new NameValuePair("charset", "GBK")},
                   //图层名称               指定用于发布资源的方法
                    layerName, it.geosolutions.geoserver.rest.GeoServerRESTPublisher.UploadMethod.FILE,
                    //        zip图集的地址           坐标系         样式
                    new File(zipFilePath).toURI(),coordinateSystem, strStyle);
        }
        return published;
    }

    public static boolean unPublishShpAndReloadStore(String workspace,String storeName){
        return publisher.removeLayer(workspace,storeName);
    }


}

三、解压zip文件工具类



import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipFile;
import org.apache.tools.zip.ZipOutputStream;

import java.io.*;
import java.nio.channels.FileChannel;
import java.util.*;

/**
 * 

* 文件操作类 *

* * @author liugh * @since 2018/3/20 */ public class FileUtils { private static ResourceBundle bundle = ResourceBundle.getBundle("constant"); //配置文件里获得,根目录地址 /data/test-version public static String fileUploadPath =bundle.getString("file-upload.dir"); /** * 判断当前文件是否是zip文件 * * @param fileName * 文件名 * @return true 是 */ public static boolean isZip(String fileName) { return fileName.toLowerCase().endsWith(Constant.FilePostFix.ZIP_FILE); } /** * 删除目录 * @param fileName */ public static void removeDocument(String fileName){ File file=new File(fileName); if(file.exists() && file.isFile()) { file.delete(); } if(file.isDirectory()){ delDir(fileName); } if (fileName.lastIndexOf(Constant.FilePostFix.ZIP_FILE) > 0) { delDir(fileName.substring(0,fileName.lastIndexOf(Constant.FilePostFix.ZIP_FILE))+"/"); } } /** * 获取坐标系 * @param filePath * @return */ public static String getCoordinate(String filePath){ try{ InputStreamReader reader = new InputStreamReader(new FileInputStream(filePath),"UTF-8"); BufferedReader br = new BufferedReader(reader); String line; StringBuilder sb =new StringBuilder(); while ((line = br.readLine()) != null) { sb.append(line); } br.close(); reader.close(); String str = sb.toString(); String substring = str.substring(str.indexOf("\"") + 1, str.indexOf("\",")); return parseCoordinate(substring); } catch(IOException e){ e.printStackTrace(); } return null; } private static String parseCoordinate(String coordinate){ switch (coordinate){ case "Beijing_1954_GK_Zone_21N": return "EPSG:21481"; case "Beijing_1954_GK_Zone_22N": return "EPSG:21482"; case "GCS_Xian_1980": return "EPSG:4610"; case "GCS_WGS_1984": return "EPSG:4326"; default:return null; } } /** * 检查第一级目录是否有.shp文件 * @param sourcePath * @return */ public static boolean checkZipFile(String sourcePath){ System.setProperty("sun.zip.encoding", System.getProperty("sun.jnu.encoding")); ZipFile zipFile =null; try { File sourceFile = new File(sourcePath); zipFile = new ZipFile(sourcePath, "gbk"); if ((!sourceFile.exists()) && (sourceFile.length() <= 0)) { throw new Exception("要解压的文件不存在!"); } Enumeration e = zipFile.getEntries(); while (e.hasMoreElements()) { ZipEntry zipEnt = (ZipEntry) e.nextElement(); if (zipEnt.isDirectory()) { return false; } if(zipEnt.getName().endsWith(".shp")){ return true; } } } catch (Exception e) { e.printStackTrace(); return false; }finally { try { if(null!=zipFile){ zipFile.close(); } } catch (IOException e) { e.printStackTrace(); } } return false; } private static List listFile = new ArrayList<>(); /** * 将存放在sourceFilePath目录下的源文件,打包成fileName名称的zip文件,并存放到zipFilePath路径下 * (把指定文件夹下的所有文件目录和文件都压缩到指定文件夹下) * @param sourceFilePath * :待压缩的文件路径 * @param zipFilePath * :压缩后存放路径 * @param fileName * :压缩后文件的名称 * @return */ public static boolean fileToZip(String sourceFilePath,String zipFilePath,String fileName)throws Exception{ boolean flag = false; FileOutputStream fos =null; ZipOutputStream zos =null; BufferedInputStream bis =null; FileInputStream fis =null; BufferedOutputStream bufferedOutputStream =null; File sourceFile = new File(sourceFilePath); if(sourceFile.exists() == false){ throw new Exception("待压缩的文件目录:"+sourceFilePath+"不存在."); }else{ try { File zipFile = new File(zipFilePath +fileName ); if(zipFile.exists()){ throw new Exception(zipFilePath + "目录下存在名字为:" + fileName +Constant.FilePostFix.ZIP_FILE +"打包文件."); }else{ File[] sourceFiles = sourceFile.listFiles(); if(null == sourceFiles || sourceFiles.length<1){ throw new Exception("待压缩的文件目录:" + sourceFilePath + "里面不存在文件,无需压缩."); }else{ fos = new FileOutputStream(zipFile); bufferedOutputStream = new BufferedOutputStream(fos); zos = new ZipOutputStream(bufferedOutputStream); byte[] bufs = new byte[1024*10]; for(int i=0;i e = zipFile.getEntries(); while (e.hasMoreElements()) { ZipEntry zipEnt = (ZipEntry) e.nextElement(); gbkPath = zipEnt.getName(); if (zipEnt.isDirectory()) { strtemp = strPath + File.separator + gbkPath; File dir = new File(strtemp); dir.mkdirs(); continue; } else { // 读写文件 is = zipFile.getInputStream((ZipEntry) zipEnt); bis = new BufferedInputStream(is); gbkPath = zipEnt.getName(); strtemp = strPath + File.separator + gbkPath; // 建目录 String strsubdir = gbkPath; for (int i = 0; i < strsubdir.length(); i++) { if ("/".equalsIgnoreCase(strsubdir.substring(i, i + 1))) { String temp = strPath + File.separator + strsubdir.substring(0, i); File subdir = new File(temp); if (!subdir.exists()) { subdir.mkdir(); } } } FileOutputStream fos = new FileOutputStream(strtemp); BufferedOutputStream bos = new BufferedOutputStream(fos); int c; while ((c = bis.read()) != -1) { bos.write((byte) c); } bos.flush(); fos.close(); bos.close(); } } zipFile.close(); return true; } catch (Exception e) { e.printStackTrace(); return false; }finally { try { if (is != null) { is.close(); } if (bis != null) { bis.close(); } } catch (IOException e) { e.printStackTrace(); } } } public static boolean deleteUploadedFile(String fileName) { String filePath = bundle.getString("file-upload.dir") + fileName; File file = new File(filePath); if(file.exists()){ if(file.isFile()) { file.delete(); }else{ removeDocument(fileName); } return true; }else{ return false; } } public static int getFileType(String originalFilename) { String postFix = originalFilename.split("//.")[originalFilename.split("//.").length-1]; if(Arrays.asList(Constant.FilePostFix.IMAGES).contains(postFix)){ return Constant.FileType.FILE_IMG; } if(Arrays.asList(Constant.FilePostFix.ZIP).contains(postFix)){ return Constant.FileType.FILE_ZIP; } if(Arrays.asList(Constant.FilePostFix.VIDEO).contains(postFix)){ return Constant.FileType.FILE_VEDIO; } if(Arrays.asList(Constant.FilePostFix.APK).contains(postFix)){ return Constant.FileType.FILE_APK; } if(Arrays.asList(Constant.FilePostFix.OFFICE).contains(postFix)){ return Constant.FileType.FIVE_OFFICE; } return Constant.FileType.FILE_IMG; } }

四、可能会遇到的问题

1.坐标系问题(显示位置错乱)。

GeoServer的坐标系要根据ArcGIS切片好的数据的图集坐标系一一对应起来,不然会位置错乱。左边坐标系可以在图集的.prj文件里找到,右边是GeoServer需要的,目前常用的是这几个

通过Java代码自动发布Geoserver的地图服务WMS_第1张图片

2.发布图集报错(表现为点击OpenLayers直接下载了空文件):

  • 可能与style有关,检查编码。我遇到一个大坑,在windows上修改的带中文的.sld文件复制到linux上就会乱码,导致图集报错。
  • 可能与zip文件内容有关(尽量用.zip,rar有低版本问题解决不了)。zip压缩的文件必须是第一级目录就有.shp等文件,不能包含目录

   通过Java代码自动发布Geoserver的地图服务WMS_第2张图片

  • 获取url发布地址问题。可以通过读取本地Geoserver所在路径,加上发布的工作区名字,拼接图层的id到url上即可。
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.ResourceBundle;


/**
 * 

* xml解析工具类 *

* * @author liugh * @since 2018/4/3 */ public class XmlUtil { private static String GEO_SERVER_PATH = ResourceBundle.getBundle("constant").getString("geoServer-dir"); private static String BUNDLE_URL = ResourceBundle.getBundle("constant").getString("geoServer-url"); private static String XML_ELEMENT_NAME="latLonBoundingBox"; public static void main(String[] args)throws Exception { getMapUrl("1522723368940","unitMap"); } //获取图集发布地址 public static String getMapUrl(String layerId,String workspace)throws Exception{ File file =new File(GEO_SERVER_PATH+File.separator+workspace); String[] fileList = file.list(); StringBuilder mapUrl = new StringBuilder(); mapUrl.append(BUNDLE_URL+workspace) .append("/wms?service=WMS&version=1.1.0&request=GetMap&layers=").append(workspace+":"+layerId).append("&styles=&bbox="); if(!ComUtil.isEmpty(fileList)){ for (String fileName:fileList) { if(fileName.equals(layerId)){ String [] coordinates = readXMLDocument(layerId,workspace); mapUrl.append(coordinates[0]+","+coordinates[2]+","+coordinates[1]+","+coordinates[3]).append("&width=768&height=437&srs=").append(coordinates[4]); } } }else{ return null; } return mapUrl.toString(); } private static String [] readXMLDocument(String layerId, String workspace){ File file = new File(GEO_SERVER_PATH+File.separator+workspace+ File.separator+layerId+File.separator+layerId+File.separator+"featuretype.xml"); if (!file.exists()) { try { throw new IOException("Can't find the path"); } catch (IOException e) { e.printStackTrace(); } } //创建SAXReader对象 SAXReader saxReader = new SAXReader(); Document document; try { //读取文件 转换成Document document = saxReader.read(file); //获取根节点元素对象 遍历当前节点下的所有节点 for (Iterator iter = document.getRootElement().elementIterator(); iter.hasNext();){ //获取节点 Element e1 = (Element) iter.next(); //如果过节点的名称等于beanName那么继续进入循环读取beanName节点下的所有节点 if(e1.getName().equalsIgnoreCase(XML_ELEMENT_NAME)){ String [] ss = new String[5]; int i =0; //遍历beanName当前节点下的所有节点 for (Iterator iter1 = e1.elementIterator(); iter1.hasNext();){ Element e2 = (Element) iter1.next(); ss[i]= e2.getStringValue(); i++; } return ss; } } } catch (DocumentException e) { e.printStackTrace(); return null; } return null; } }

3.过滤属性问题。

当鼠标点击GeoServer发布地图的某个区域,会在下方显示属性。我这里通过Http方式获取到所有值,然后用Jsoup来解析,类似于爬虫的方式。返回属性后可以根据业务屏蔽或展示一些属性值。

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 

* HTTP请求工具类 *

* * @author liugh * @since 2018/3/20 */ public class HttpLayerPropertyUtil { /** * 获取图层所有属性 * @param layerPreviewURL * @return */ public static List> getLayerProperty(String layerPreviewURL){ List> retList = new ArrayList(); try { Document doc = Jsoup.connect(layerPreviewURL).get(); Elements select = doc.select("th"); Elements select1 = doc.select("td"); for (int i = 0; i < select.size(); i++) { HashMap tempMap = new HashMap<>(16); tempMap.put(cutValue(select.get(i).toString()), cutValue(select1.get(i).toString())); retList.add(tempMap); } return retList; } catch (IOException e) { System.out.println("页面获取异常!"); e.printStackTrace(); } return null; } private static String cutValue(String s){ String substring = s.substring(4,s.indexOf("

如果读者还遇到其他问题,或者想要资源,可以在下方评论,我看见就会回复你。

转载于:https://my.oschina.net/liughDevelop/blog/1926551

你可能感兴趣的:(通过Java代码自动发布Geoserver的地图服务WMS)