1. 程式人生 > >OpenLayer+PostGIS+GeoServer--無額外後臺實現地理分析與查詢框架

OpenLayer+PostGIS+GeoServer--無額外後臺實現地理分析與查詢框架

 

 OpenLayer+PostGIS+GeoServer--無額外後臺實現地理分析與查詢框架

1.1 傳統流程

在一般情況下,人們使用PostGIS儲存空間資料,以Geoserver釋出資料服務,以OpenLayer客戶端展示地圖。客戶端操作與地理查詢,如果查詢等比較複雜,一般會使用ajax將ol的請求引數傳給後臺,由後臺完成操作後返回前端。流程如下:

 

1.2 框架問題說明

1 GeoServer只是簡單釋出了地理資料,單個圖層,只能接受簡單的wms顯示,wfs查詢,wps分析。產生的問題是,面對多個圖層的疊加分析與查詢,幾乎做不到,所以很多圖層的分析只能交由後臺伺服器完成。

2 使用後臺伺服器處理地理資料,產生的問題是,對資料庫的訪問比較頻繁,分析的結果,由於是空間資料,對資料的解析儲存有要求,工作量增大。

3 作為GIS專業開發人員的苦惱是我曾加入一個j2ee專案組,作為Java的門外漢,我做一個哪怕最簡單的查詢,都要寫好多個java類檔案與資料結構類檔案,為了滿足j2ee框架需求。這令我感到很苦惱,在我看來,作為業務開發人員,他們需要這個框架,但作為地圖開發人員,我的精力都在研究各個地圖技術和框架上而不是語言本身,既不必要也無精力。能不能有個gis開發框架,使我專注於地理資料的查詢與分析而脫離業務框架本身的束縛,這讓我感到很有必要。

二 獨立於業務的地理資料操作框架

結構說明:1 複雜的多圖層的分析,全是在資料庫中以function指令碼編寫。

2 geoserver釋出要顯示地圖表。釋出function作為檢視引數。 對geoserver來說,table,view,function本質都是資料來源,是一樣的,所以都可以釋出。

3 使用時,普通的表用來顯示地圖,function用來分析地圖。

 

優勢:無論加入哪個專案組,我根本不用關心他們的框架與資料結構,整合時,自己負責地圖,業務負責業務,各司其職。

原來後臺服務全被改寫到資料庫中,這樣,在運算速度上也比驅動的快且少了一個額外的後臺。

 

三 框架使用示例

以最最簡單的需求作為說明示例:

需求: 我要根據道路名稱,查詢道路某個距離的緩衝區內的興趣點。

3.1 實現具體分析功能的資料庫function指令碼

[sql] view plain copy print?

  1. CREATE OR REPLACE FUNCTION queryplottingbyroad(  
  2.                 IN roadname text,  
  3.                 in distance double precision,  
  4.                 OUT gid int,  
  5.                 OUT shapearea double precision,  
  6.                 out swglm text,  
  7.                 out idcode text,  
  8.                 out gljg_dm text,  
  9.                 out editdate timestamp without time zone,  
  10.                 out geom geometry  
  11.         )  
  12.          returns SETOF record AS  
  13. $BODY$  
  14. DECLARE  
  15.         queryGeom geometry;  
  16.         rec record;  
  17.         sql text;  
  18. BEGIN  
  19.     --依據道路名稱查詢道路圖形  
  20.     sql:='select geom from road where name='''||roadname||'''';  
  21.     raise notice 'sql:%',sql;  
  22.     EXECUTE sql into rec;  
  23.     --對查詢的道路進行緩衝  
  24.     queryGeom:=ST_Buffer(rec.geom,distance);  
  25.     --查詢落在緩衝區內或與緩衝區相交的指定圖層資料  
  26.     sql:='select * from plottingwithqx t where ST_Within(t.geom,ST_GeomFromText('''||st_astext(queryGeom)||''',3857)) or ST_Intersects(t.geom,ST_GeomFromText('''||st_astext(queryGeom)||''',3857))';  
  27.     raise notice 'sql:%',sql;  
  28.     --查詢資料蒐集返回呼叫者  
  29.     for rec in execute sql loop  
  30.         gid:= rec.gid;  
  31.         shapearea:= rec.shapearea;  
  32.         swglm:= rec.swglm;  
  33.         idcode:= rec.idcode;  
  34.         gljg_dm:= rec.gljg_dm;    
  35.         editdate:= rec.editdate;          
  36.         geom:= rec.geom;  
  37.         return next;  
  38.     end loop;  
  39.     return;  
  40. END;  
  41. $BODY$  
  42. LANGUAGE 'plpgsql' VOLATILE STRICT;  

CREATE OR REPLACE FUNCTION queryplottingbyroad(
                IN roadname text,
				in distance double precision,
				OUT gid int,
				OUT shapearea double precision,
				out swglm text,
				out idcode text,
				out gljg_dm text,
				out editdate timestamp without time zone,
				out geom geometry
        )
         returns SETOF record AS
$BODY$
DECLARE
		queryGeom geometry;
		rec record;
		sql text;
BEGIN
	--依據道路名稱查詢道路圖形
	sql:='select geom from road where name='''||roadname||'''';
	raise notice 'sql:%',sql;
	EXECUTE sql into rec;
	--對查詢的道路進行緩衝
	queryGeom:=ST_Buffer(rec.geom,distance);
	--查詢落在緩衝區內或與緩衝區相交的指定圖層資料
	sql:='select * from plottingwithqx t where ST_Within(t.geom,ST_GeomFromText('''||st_astext(queryGeom)||''',3857)) or ST_Intersects(t.geom,ST_GeomFromText('''||st_astext(queryGeom)||''',3857))';
	raise notice 'sql:%',sql;
	--查詢資料蒐集返回呼叫者
	for rec in execute sql loop
		gid:= rec.gid;
		shapearea:= rec.shapearea;
		swglm:=	rec.swglm;
		idcode:= rec.idcode;
		gljg_dm:= rec.gljg_dm;	
		editdate:= rec.editdate;		
		geom:= rec.geom;
		return next;
	end loop;
	return;
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE STRICT;


3.2 Geoserer釋出function

 

在  圖層》釋出檢視服務中釋出一個檢視服務,具體參照geoserver官網。

3 客戶端呼叫

以wms查詢為例:

[plain] view plain copy print?

  1. http://localhost:8090/geoserver/nkstarTax/wms?LAYERS=nkstarTax:queryPlottingbyroad&TRANSPARENT=TRUE&VIEWPARAMS=name:'東方紅路';distance:100&BBOX=1.3304724687752E7,3812889.1757509,1.3323585520889E7,3829641.4938807&WIDTH=512&HEIGHT=434&SRS=EPSG:900913&format=image/png&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&STYLES=  

http://localhost:8090/geoserver/nkstarTax/wms?LAYERS=nkstarTax:queryPlottingbyroad&TRANSPARENT=TRUE&VIEWPARAMS=name:'東方紅路';distance:100&BBOX=1.3304724687752E7,3812889.1757509,1.3323585520889E7,3829641.4938807&WIDTH=512&HEIGHT=434&SRS=EPSG:900913&format=image/png&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&STYLES=


viewparams是客戶端把引數放這個裡面,傳給geoserver,然後伺服器解析引數,查詢資料庫並返回結果。上方的url請求返回 道路名稱為'東方紅路'的100米範圍內的查詢圖層的符合要求資料。

 

查詢 200米範圍內的指定圖層符號要求資料

 

[plain] view plain copy print?

  1. http://localhost:8090/geoserver/nkstarTax/wms?LAYERS=nkstarTax:queryPlottingbyroad&TRANSPARENT=TRUE&VIEWPARAMS=name:'東方紅路';distance:200&BBOX=1.3304724687752E7,3812889.1757509,1.3323585520889E7,3829641.4938807&WIDTH=512&HEIGHT=434&SRS=EPSG:900913&format=image/png&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&STYLES=  

 

http://localhost:8090/geoserver/nkstarTax/wms?LAYERS=nkstarTax:queryPlottingbyroad&TRANSPARENT=TRUE&VIEWPARAMS=name:'東方紅路';distance:200&BBOX=1.3304724687752E7,3812889.1757509,1.3323585520889E7,3829641.4938807&WIDTH=512&HEIGHT=434&SRS=EPSG:900913&format=image/png&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&STYLES=

效果如下,範圍擴大之後,多了一條記錄。

 

使用wfs查詢也是一樣的,使用viewparams將引數傳給伺服器,伺服器查詢資料庫。

 

總的來說,將傳統流程的複雜分析,摒棄了後臺,直接放在資料庫中的function中完成,由geoserver作為後臺,響應客戶端請求,無論wms,wfs都可以,並根據引數返回圖片或資料。

 

文章來源:http://blog.csdn.net/freeland1/article/details/42171949