GeoServer 顧名思義。是一個Server,它是開源的,容許用戶查看和編輯地理數據的服務器,它能夠比較容易的在用戶之間迅速共享空間地理信息。利用Geoserver能夠把數據做爲maps/images來發布(利用WMS來實現)也能夠直接發佈實際的數據(利用WFS來實現),它同時也提供了修改,刪除和新增的功能(利用WFS-T)。java
爲何要使用GeoServer?相比較同類產品ArcServer不是一個開源GIS服務器,全部想在Web地圖應用開發中使用ArcServer就須要付費,並且價格比較高(ref:GeoServer與ArcServer對比)。本文將完成用ArcGIS切片好的數據,經過代碼自動發佈Geoserver 中。若是不清楚手動發佈流程和實現的效果,能夠看個人另一篇文章:GeoServer手動發佈本地Shapefile地圖。node
指定遠程倉庫linux
<repository> <id>GeoSolutions</id> <url>http://maven.geo-solutions.it/</url> </repository>
加入dependency apache
<dependency> <groupId>it.geosolutions</groupId> <artifactId>geoserver-manager</artifactId> <version>1.7.0</version> </dependency>
常量類Constantswindows
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); } }
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.*; /** * <p> * 文件操做類 * </p> * * @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<String> 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<sourceFiles.length;i++){ //建立ZIP實體,並添加進壓縮包 ZipEntry zipEntry = new ZipEntry(sourceFiles[i].getName()); zos.putNextEntry(zipEntry); //讀取待壓縮的文件並寫進壓縮包裏 fis = new FileInputStream(sourceFiles[i]); bis = new BufferedInputStream(fis, Constant.BYTE_BUFFER *Constant.BUFFER_MULTIPLE); int read; while((read=bis.read(bufs, 0, Constant.BYTE_BUFFER *Constant.BUFFER_MULTIPLE)) != -1){ zos.write(bufs,0,read); } fis.close(); bis.close(); } flag = true; } } } catch (FileNotFoundException e) { e.printStackTrace(); throw new RuntimeException(e); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException(e); } finally{ //關閉流 try { if (null != bis) { bis.close(); } if (null != zos) { zos.close(); } if (null != bufferedOutputStream) { bufferedOutputStream.close(); } } catch (IOException e) { e.printStackTrace(); } } } return flag; } public static boolean updateLayerNameByZipFile(String sourcePath,String targetLayerName) { File file = new File(sourcePath); if (file.isDirectory()) { String[] fileList = file.list(); if (!ComUtil.isEmpty(fileList)) { for (String fileName : fileList) { File oldName = new File(sourcePath + File.separator + fileName); File newName = new File(sourcePath + File.separator + targetLayerName + fileName.substring(fileName.lastIndexOf("."))); if (".xml".equals(fileName.substring(fileName.lastIndexOf(".")))) { newName = new File(sourcePath + File.separator + targetLayerName + fileName.substring(fileName.lastIndexOf(".shp"))); } oldName.renameTo(newName); } return true; } return false; } return false; } /** * 保存文件到臨時目錄 * @param inputStream 文件輸入流 * @param fileName 文件名 */ public static void savePic(InputStream inputStream, String fileName) { OutputStream os = null; try { // 保存到臨時文件 // 1K的數據緩衝 byte[] bs = new byte[1024]; // 讀取到的數據長度 int len; // 輸出的文件流保存到本地文件 File tempFile = new File(fileUploadPath); if (!tempFile.exists()) { tempFile.mkdirs(); } os = new FileOutputStream(tempFile.getPath() + File.separator + fileName); // 開始讀取 while ((len = inputStream.read(bs)) != -1) { os.write(bs, 0, len); } }catch (Exception e) { e.printStackTrace(); } finally { // 完畢,關閉全部連接 try { os.close(); inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } public static String saveFile(InputStream file, int type, String name, String tag) throws Exception { Date time = new Date(); String fileName = fileName(time, type, name,tag); File newFile = getNewFile(fileName); File oldFile = createTemporaryFile(file, name); copyFile(newFile, new FileInputStream(oldFile)); oldFile.delete(); return fileName; } public static File createTemporaryFile(InputStream file, String name) throws Exception { File temp = new File(name); OutputStream out = new FileOutputStream(temp); try { int byteCount = 0; byte[] buffer = new byte[4096]; int bytesRead = -1; while ((bytesRead = file.read(buffer)) != -1) { out.write(buffer, 0, bytesRead); byteCount += bytesRead; } out.flush(); } finally { try { file.close(); } catch (IOException ex) { } try { out.close(); } catch (IOException ex) { } } return temp; } private static void copyFile(File newFile, FileInputStream file) throws Exception { FileOutputStream outFile = new FileOutputStream(newFile); FileChannel inC = file.getChannel(); FileChannel outC = outFile.getChannel(); int length = 2097152; while (true) { if (inC.position() == inC.size()) { inC.close(); outC.close(); outFile.close(); file.close(); return ; } if ((inC.size() - inC.position()) < 20971520) { length = (int) (inC.size() - inC.position()); }else { length = 20971520; } inC.transferTo(inC.position(), length, outC); inC.position(inC.position() + length); } } public static File getNewFile(String fileName) throws IOException { String filePath = bundle.getString("file-upload.dir") + fileName; File newFile = new File(filePath); File fileParent = newFile.getParentFile(); if(!fileParent.exists()){ fileParent.mkdirs(); } if (!newFile.exists()){ newFile.createNewFile(); } return newFile; } /** * 文件保存路徑 * @param time * @param type * @param name * @return */ private static String fileName(Date time, int type, String name,String tag) { StringBuffer str = new StringBuffer(); if (type== Constant.FileType.FILE_IMG) { str.append(Constant.FileType.FILE_IMG_DIR); } if (type==Constant.FileType.FILE_ZIP) { str.append(Constant.FileType.FILE_ZIP_DIR); } if (type==Constant.FileType.FILE_VEDIO) { str.append(Constant.FileType.FILE_VEDIO_DIR); } if (type==Constant.FileType.FILE_APK) { str.append(Constant.FileType.FILE_APK_DIR); } if (type==Constant.FileType.FIVE_OFFICE) { str.append(Constant.FileType.FIVE_OFFICE_DIR); } str.append(DateTimeUtil.formatDateToString(time)); str.append("/"); str.append(DateTimeUtil.currentidDatetime()); if(!ComUtil.isEmpty(tag)) { str.append(tag); } str.append("-"+name); return str.toString(); } public static String getFileUrl(String fileDir){ return bundle.getString("file-upload.url") + fileDir; } /** * 刪除文件目錄 * @param path */ private static void delDir(String path){ File dir=new File(path); if(dir.exists()){ File[] tmp=dir.listFiles(); for(int i=0;i<tmp.length;i++){ if(tmp[i].isDirectory()){ delDir(path+File.separator+tmp[i].getName()); }else{ tmp[i].delete(); } } dir.delete(); } } /** * 解壓zip格式的壓縮文件到指定位置 * * @param sourcePath * 壓縮文件 * @param targetPath * 解壓目錄 * @throws Exception */ public static boolean unZipFiles(String sourcePath, String targetPath) throws Exception { System.setProperty("sun.zip.encoding", System.getProperty("sun.jnu.encoding")); InputStream is =null; BufferedInputStream bis =null; try { (new File(targetPath)).mkdirs(); File sourceFile = new File(sourcePath); // 處理中文文件名亂碼的問題 ZipFile zipFile = new ZipFile(sourcePath, "UTF-8"); if ((!sourceFile.exists()) && (sourceFile.length() <= 0)) { throw new Exception("要解壓的文件不存在!"); } String strPath, gbkPath, strtemp; File tempFile = new File(targetPath); strPath = tempFile.getAbsolutePath(); Enumeration<?> 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; } }
GeoServer的座標系要根據ArcGIS切片好的數據的圖集座標系一一對應起來,否則會位置錯亂。左邊座標系能夠在圖集的.prj文件裏找到,右邊是GeoServer須要的,目前經常使用的是這幾個app
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; /** * <p> * xml解析工具類 * </p> * * @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; } }
當鼠標點擊GeoServer發佈地圖的某個區域,會在下方顯示屬性。我這裏經過Http方式獲取到全部值,而後用Jsoup來解析,相似於爬蟲的方式。返回屬性後能夠根據業務屏蔽或展現一些屬性值。dom
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; /** * <p> * HTTP請求工具類 * </p> * * @author liugh * @since 2018/3/20 */ public class HttpLayerPropertyUtil { /** * 獲取圖層全部屬性 * @param layerPreviewURL * @return */ public static List<Map<String,String>> getLayerProperty(String layerPreviewURL){ List<Map<String,String>> 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<String,String> 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("</")); return substring; } }
若是讀者還遇到其餘問題,或者想要資源,能夠在下方評論,我看見就會回覆你。maven