Существенно, что GeoServer, PostgreSQL и разрабатываемое приложение располагаются на разных серверах. Потребовалось по клику на точечном объекте получить его данные из GeoServer (имя слоя и идентификатор выбранного объекта для последующего запроса к PosgreSQL).
Известно, что OpenLayers не получает ответа на запрос типа OpenLayers.loadURL, если он загружен с другого хоста. Для преодоления этого препятствия разработчиками OpenLayers было предложено использовать прокси. В GWT-OpenLayers реализован такой прокси. Это сервлет GwtOpenLayersProxyServlet, который размещён в gwt-openlayers-server-0.5.jar.
В процессе разработки выяснилось, что этот способ не работает! Помогла статья wfs:dwithin MassGIS Geospatial Web Services Wiki. В ней предложено два способа запроса к WFS GeoServer: через HTTP POST XML и через HTTP GET с параметром cql_filter.
Выполняя запрос
http://webgar:8080/geoserver/wfs?request=getfeature
&version=1.1.0&service=wfs&outputformat=json&typename=rptp:ps
&propertyName=tip,nomer_tp&cql_filter=DWITHIN(geom,POINT(15398 14449),600,meters)
{"type":"FeatureCollection","features":
[{"type":"Feature","id":"ps.9","geometry":null,"properties":
{"tip":"ПС","nomer_tp":"ПС \"Ново-Измайлово\""}}]}
http://localhost:8080/map_war/gwtOpenLayersProxy?targetURL=
http%3A%2F%2Fwebgar%3A8080%2Fgeoserver%2Fwfs%3Frequest%3Dgetfeature
%26version%3D1.1.0%26service%3Dwfs%26outputformat%3Djson
%26typename%3Drptp%3Aps%26propertyName%3Dtip%2Cnomer_tp
%26cql_filter%3DDWITHIN(geom%2CPOINT(15398%2014449)%2C600%2Cmeters)
HTTP Status 500 -
type Status report
description The server encountered an internal error () that prevented it from fulfilling this request.
Apache Tomcat/7.0.10
http://localhost:8080/map_war/gwtOpenLayersProxy?targetURL=
http%3A%2F%2Fwebgar%3A8080%2Fgeoserver%2Fwfs%3Frequest%3Dgetfeature%26version
%3D1.1.0%26service%3Dwfs%26outputformat%3Djson%26typename%3Drptp%3Aps
%26propertyName%3Dtip%2Cnomer_tp
{"type":"FeatureCollection","features":
[{"type":"Feature","id":"ps.1","geometry":null,"properties":
{"tip":"ПС","nomer_tp":"53 ПС \"Герцево\""}},
{"type":"Feature","id":"ps.2","geometry":null,"properties":
{"tip":"ПС","nomer_tp":"ПС \"Матвеевская\""}},
{"type":"Feature","id":"ps.3","geometry":null,"properties":
{"tip":"ПС","nomer_tp":"ПС \"Щедрино\""}},
{"type":"Feature","id":"ps.4","geometry":null,"properties":
{"tip":"ПС","nomer_tp":"850 \"Ново-Внуково\""}},
{"type":"Feature","id":"ps.5","geometry":null,"properties":
{"tip":"ПС","nomer_tp":"ПС \"Дубнинская\""}},
{"type":"Feature","id":"ps.6","geometry":null,"properties":
{"tip":"ПС","nomer_tp":"68 ПС \"Битца\""}},
{"type":"Feature","id":"ps.7","geometry":null,"properties":
{"tip":"ПС","nomer_tp":"844 ПС \"Магистральна"}},
{"type":"Feature","id":"ps.8","geometry":null,"properties":
{"tip":"ПС","nomer_tp":"ПС \"Мневники\""}},
{"type":"Feature","id":"ps.9","geometry":null,"properties":
{"tip":"ПС","nomer_tp":"ПС \"Ново-Измайлово\""}},
{"type":"Feature","id":"ps.10","geometry":null,"properties":
{"tip":"ПС","nomer_tp":"ПС \"Горьковская\""}}]}
curl.exe -H "Content-type: text/xml" -d @request.xml
-X POST http://webgar:8080/geoserver/wfs > response.xml
<wfs:GetFeature xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.opengis.net/wfs
http://webgar:8080/geoserver/schemas/wfs/1.1.0/WFS-basic.xsd"
xmlns:gml="http://www.opengis.net/gml"
xmlns:wfs="http://www.opengis.net/wfs"
xmlns:ogc="http://www.opengis.net/ogc" service="WFS"
version="1.1.0">
<wfs:Query typeName="rptp:ps"
xmlns:rptp="http://rptp.dev-city.ru">
<ogc:PropertyName>tip</ogc:PropertyName>
<ogc:PropertyName>nomer_tp</ogc:PropertyName>
<ogc:Filter>
<ogc:DWithin>
<ogc:PropertyName>geom</ogc:PropertyName>
<gml:Point srsName="EPSG:100001"
xmlns:gml="http://www.opengis.net/gml">
<gml:coordinates decimal="." cs="," ts="">
15398,14449</gml:coordinates>
</gml:Point>
<ogc:Distance units="meter">600</ogc:Distance>
</ogc:DWithin>
</ogc:Filter>
</wfs:Query>
</wfs:GetFeature>
<?xml version="1.0" encoding="utf-8"?>
<wfs:FeatureCollection numberOfFeatures="1"
timeStamp="2011-04-15T10:47:52.440+04:00"
xsi:schemaLocation="http://rptp.dev-city.ru
http://webgar:8080/geoserver/wfs?service=WFS&version=1.1.0&
request=DescribeFeatureType&typeName=rptp%3Aps http://www.opengis.net/wfs
http://webgar:8080/geoserver/schemas/wfs/1.1.0/wfs.xsd"
xmlns:egko="http://egko.dev-city.ru"
xmlns:ogc="http://www.opengis.net/ogc"
xmlns:gml="http://www.opengis.net/gml"
xmlns:rptp="http://rptp.dev-city.ru"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:ows="http://www.opengis.net/ows"
xmlns:wfs="http://www.opengis.net/wfs">
<gml:featureMembers>
<rptp:ps gml:id="ps.9">
<rptp:tip>ПС</rptp:tip>
<rptp:nomer_tp>ПС "Ново-Измайлово"</rptp:nomer_tp>
</rptp:ps>
</gml:featureMembers>
</wfs:FeatureCollection>
Осталось только реализовать формирование запроса и обработку ответа в нашем приложении. На стороне клиента на карте создаётся экземпляр MapClickListener и реализуется его метод onClick с параметром MapClickEvent, через который будут определяться методом getLonLat() текущие координаты x, y. Эти координаты, имя слоя и радиус поиска будут передаваться как входные параметры сервиса, который расширяет RemoteServiceServlet. Можно заготовить шаблон файла request.xml, в который будут вставляться значения этих параметров. Метод getSelectedFeatureInfo будет возвращать перечень семантических данных найденных объектов:
@Override
public List getSelectedFeatureInfo(double x, double y, double distance, String layer) {
String urlStr = getServletContext().getInitParameter("geoserver-url") + "wfs";
String requestTemplate = getServletContext().getRealPath("/") + "xml/request.xml";
File file = new File(requestTemplate);
List featuresInfo = null;
try {
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = builder.parse(file);
Element root = doc.getDocumentElement();
// Установка имени слоя
NodeList list = root.getElementsByTagName("wfs:Query");
NamedNodeMap attr = list.item(0).getAttributes();
Node node = attr.getNamedItem("typeName");
node.setNodeValue(layer);
// Установка координат
node = root.getElementsByTagName("gml:coordinates").item(0);
node.setTextContent(x + "," + y);
// Установка расстояния
node = root.getElementsByTagName("ogc:Distance").item(0);
node.setTextContent(String.valueOf(distance));
// Установка соединения с GeoServer
URL url = new URL(urlStr);
URLConnection con = url.openConnection();
con.setDoOutput(true);
con.setDoInput(true);
con.setRequestProperty("Content-Type", "text/xml");
// Формирование запроса
Transformer transformer = TransformerFactory.newInstance().newTransformer();
StringWriter out = new StringWriter();
transformer.transform(new DOMSource(doc), new StreamResult(out));
OutputStreamWriter writer = new OutputStreamWriter(con.getOutputStream());
writer.write(out.toString());
writer.flush();
writer.close();
// Получение ответа
doc = builder.parse(con.getInputStream());
root = doc.getDocumentElement();
NodeList tip = root.getElementsByTagName("rptp:tip");
NodeList nomer_tp = root.getElementsByTagName("rptp:nomer_tp");
featuresInfo = new ArrayList(tip.getLength());
for (int i = 0; i < tip.getLength(); i++) {
String tipVal = tip.item(i).getTextContent();
String nomer_tpVal = nomer_tp.item(i).getTextContent();
FeatureInfo featureInfo = DB_RP.getFeatureInfo(tipVal,
nomer_tpVal, getServletContext());
if (featureInfo != null)
featuresInfo.add(i, featureInfo);
}
} catch (Throwable e) {
e.printStackTrace();
}
return featuresInfo;
}
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.File;
import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;
OpenLayers.setProxyHost("gwtOpenLayersProxy?targetURL=");
Комментариев нет:
Отправить комментарий