首先吐槽下GeoServer(其實(shí)是GeoWebCache)的切片保存路徑竟然如此奇葩,且不可配置侍咱,即不能遷移到其他系統(tǒng),也不能發(fā)布其他系統(tǒng)生產(chǎn)的切片(雖然GeoWebCache有對(duì)ArcGIS Server切片的插件耐床,但那個(gè)東西卻無(wú)法和GeoServer集成)。這種情況似乎將在下個(gè)版本(GeoServer2.17/GeoWebCache1.17)中有所改善,加入了對(duì)TMS切片的支持楔脯,其切片路徑是我們熟悉的{z}/{x}/{y}撩轰,但這并不能滿足我們的需求,首先它是TMS切片昧廷,與WMTS切片在y方向相反堪嫂;其次我們想要的就是隨心所欲。
看來短時(shí)間內(nèi)指望GeoServer在這方面有所改觀是不太可能了木柬,于是,只好自己來寫一個(gè)擴(kuò)展吧皆串,希望可以讓GeoServer實(shí)現(xiàn)通過配置路徑模板的方式來適應(yīng)其他類型切片,如ArcGIS或者Cesiumlab眉枕。
1恶复、首先下載插件(今天才發(fā)現(xiàn)怜森,簡(jiǎn)書竟然不能上傳文件,先上傳到百度云吧)
鏈接:https://pan.baidu.com/s/16R5yIxh5Jz32fyi08qCixA
提取碼:rn1p
將下載到的custom-filestroe-1.0-SNAPSHOT.jar谤牡,放到<geoserver>\webapps\geoserver\WEB-INF\lib中副硅,重啟geoserver。
2翅萤、配置BlobStore恐疲,在Add? new BlobStore頁(yè)面選擇Custom FileStore,頁(yè)面如下套么。
通過設(shè)置路徑模板參數(shù)來匹配切片路徑流纹,如ArcGIS Server的切片路徑是這樣的:LayerName\L03\R00000002\C00000005.png,那么這里需要這樣填寫:{layer}\L{level:%02d}\R{row:%08x}\C{col:%08x}
而Cesiumlab切片路徑是這樣的:LayerName\{z}\{x}\{y}.png违诗,則這里需要這樣趕寫:{layer}\{level:%d}\{col:%d}\{row:%d}
3、發(fā)布切片疮蹦。在geoserver中的geowebcache.xml文件中添加一個(gè)wmsLayer:
<wmsLayer>
??????<blobStoreId>arcgis</blobStoreId>
??????<enabled>true</enabled>
??????<name>33</name>
??????<mimeFormats>
????????<string>image/jpeg</string>
??????</mimeFormats>
??????<gridSubsets>
????????<gridSubset>
??????????<gridSetName>EPSG:900913</gridSetName>
??????????<extent>
????????????<coords>
??????????????<double>8176078.237521</double>
??????????????<double>704818.027536</double>
??????????????<double>1.5037685885628E7</double>
??????????????<double>7086873.419584</double>
????????????</coords>
??????????</extent>
????????</gridSubset>
??????</gridSubsets>
??????<wmsUrl>
????????<string>http://localhost:8081/geoserver/wms?</string>
??????</wmsUrl>
????</wmsLayer>
其中诸迟,blobStoreId是第二步中所配置的BlobStore的Identifier;name為圖層名稱愕乎;mimeFormats為切片的mineType阵苇;gridSubsets配置EPSG和對(duì)應(yīng)的坐標(biāo)范圍。
4感论、瀏覽绅项。在GeoServer的Tile Layers頁(yè)面找到剛剛配置的圖層。
在PreView下拉列表中選擇對(duì)應(yīng)的EPSG/mineType比肄,跳轉(zhuǎn)到預(yù)覽頁(yè)面快耿,如下:
此插件應(yīng)該能自動(dòng)匹配大多數(shù)切片路徑,但像GeoServer這樣奇葩的路徑芳绩,這里不掀亥!兼!容妥色!
5搪花、核心代碼 :該插件代碼非常簡(jiǎn)單,簡(jiǎn)單到不好意思將其作為一個(gè)項(xiàng)目開源出來嘹害,就把其核心代碼貼到下面吧:
public File tilePath(TileObject tile, MimeType mimeType) {
final long[] tileIndex = tile.getXYZ();
long x = tileIndex[0];
int z = (int) tileIndex[2];
long y =0;
try {
y = getY(tile.getLayerName(), tile.getGridSetId(), x, tileIndex[1], z);
}catch (GeoWebCacheException e) {
e.printStackTrace();
return null;
}
StringBuilder path =new StringBuilder(256);
String fileExtension = mimeType.getFileExtension();
path.append(cacheRoot);
path.append(File.separatorChar);
String layer = tile.getLayerName();
String[] wl = layer.split(":");
String templatePath ="";
if(wl.length ==2){
templatePath =template.replace("{workspace}",wl[0]);
templatePath =template.replace("{layer}",wl[1]);
}
else{
templatePath =template.replace("{workspace}","");
templatePath =template.replace("{layer}",layer);
}
templatePath = templatePath.replace("{gridset}", tile.getGridSetId());
long shift = z /2;
long half =2 << shift;
int digits =1;
if (half >10) {
digits = (int) (Math.log10(half)) +1;
}
long halfx = x / half;
long halfy = y / half;
templatePath = templatePath.replace("{halfx}",zeroPadder(halfx, digits));
templatePath = templatePath.replace("{halfy}",zeroPadder(halfy, digits));
String levelPattern ="\\{level:([^}]*)\\}";
String levelTemplate = getString(templatePath,levelPattern);
String rowPattern ="\\{row:([^}]*)\\}";
String rowTemplate = getString(templatePath,rowPattern);
String colPattern ="\\{col:([^}]*)\\}";
String colTemplate = getString(templatePath,colPattern);
String level = String.format(levelTemplate, z);
templatePath = templatePath.replace(levelTemplate, level.substring(7,level.length() -1));
String row = String.format(rowTemplate, y);
templatePath = templatePath.replace(rowTemplate, row.substring(5,row.length() -1));
String col = String.format(colTemplate, x);
templatePath = templatePath.replace(colTemplate, col.substring(5,col.length() -1));
path.append(templatePath);
path.append('.');
path.append(fileExtension);
File tileFile =new File(path.toString());
if(!tileFile.exists()){
if(fileExtension.toLowerCase() =="jpeg"){
tileFile =new File(path.toString().replace("jpeg","jpg"));
}
}
return tileFile;
}
本想基于GeoServer2.17版本開發(fā)撮竿,但2.17版本在BlobStore方面做了比較大的修改,因此只好基于現(xiàn)有版本GeoServer2.16開發(fā)笔呀。
謹(jǐn)以此篇為自己2019年的工作畫一個(gè)句號(hào)幢踏,并恭祝大家2020年萬(wàn)事如意!