最近做一个WebGIS的项目,使用的是Openlayers3 v3.17.1的版本,需要用到ajax调用ArcGIS for Server 10.2发布的WMS服务,业务应用于GIS服务不在一个域内,需要解决跨域的问题。
1、(不是最终解决方案,可略过)网上有一篇关于跨域的解决办法,讲的比较明白:http://www.cnblogs.com/dojo-lzz/p/4265637.html
几种解决办法,基本都要更改GIS服务器端的内容,暂时决定采用JSONP的方式来解决该问题,这时需要解决的另外一个问题出现了,那就是修改WMS的查询结果的格式。
2、(不是最终解决方案,可略过)查询ArcGIS for Server的帮助文档,看到其可以自定义 WMS GetFeatureInfo 响应,以为发现了神器,结果不知道是参数传递的问题,还是其他原因,不成功。
有一段话,特别重要。
使用 xslt_template 参数时,XSLT 模板不必遵循与默认模板相同的命名约定,但它需要经由 URL 提供。指定本地路径或 UNC 路径会导致请求失败。
从ArcGIS for Server的安装目录ArcGIS\Server\Styles\WMS中拷贝一个XSLT的模板出来,发布出来,保证可以正常访问。
将我的WMS的GetFeatureInfo的请求地址放到这里,还请大家能够看看有没有问题,将无论version是1.1.1和1.3.0都不行,
http://192.168.1.125:6080/arcgis/services/ymfb/ymfb/MapServer/WMSServer?service=WMS&version=1.3.0&request=GetFeatureInfo&layers=10&query_layers=10&INFO_FORMAT=text/plain&I=21&J=59&WIDTH=256&HEIGHT=256&SRS=EPSG:4326&CRS=EPSG:4326&STYLES=&BBOX=33.75,109.6875,36.5625,112.5&xsl_template=http://localhost:8081/ymgis/data/featureinfo_application_geojson.xsl
3、(终极解决方案)这时候,突然想起来以前用过httpclient,能不能用这个来实现呢?
httpclient的项目的地址:http://hc.apache.org/
使用异步请求插件HttpAsyncClient 4.1.2,官方包里有简单的应用例子,可以参照下。
需要强调的是,httpclient的ajax请求,只能是get,不能用post,这主要是由于ArcGIS for Server决定的,和httpclient本身无关。通过这种方式,最终拿到了wms的返回结果。
4、部分代码,自定义的中转跨域请求的代码,proxyData变量作为返回到前台的变量,本项目用的Struts2,应用原理都是一样的。
4.1用来中转请求的Action代码
public static String Inputstr2Str_Reader(InputStream in, String encode) { String str = ""; try { if (encode == null || encode.equals("")) { // 默认以utf-8形式 encode = "utf-8"; } BufferedReader reader = new BufferedReader(new InputStreamReader(in, encode)); StringBuffer sb = new StringBuffer(); while ((str = reader.readLine()) != null) { sb.append(str).append("\n"); } return sb.toString(); } catch (UnsupportedEncodingException e1) { e1.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return str; } public String proxyAjax() throws ExecutionException, IOException, InterruptedException { HttpServletRequest request = ServletActionContext.getRequest(); String url = request.getParameter("url"); CloseableHttpAsyncClient httpClient = HttpAsyncClients.createDefault(); try { // Start the client httpClient.start(); // One most likely would want to use a callback for operation result final CountDownLatch latch1 = new CountDownLatch(1);//线程辅助类,官方例子 final HttpGet request2 = new HttpGet(url);//wms服务, arcgis只能用get调用 httpClient.execute(request2, new FutureCallback<HttpResponse>() { @Override public void completed(final HttpResponse response2) { latch1.countDown(); InputStream inputStream; try { inputStream = response2.getEntity().getContent(); proxyData=Inputstr2Str_Reader(inputStream, "UTF-8"); } catch (UnsupportedOperationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } @Override public void failed(final Exception ex) { latch1.countDown(); System.out.println(request2.getRequestLine() + "->" + ex); } @Override public void cancelled() { latch1.countDown(); System.out.println(request2.getRequestLine() + " cancelled"); } }); latch1.await(); } finally { httpClient.close(); } // this.proxyData = url; return ActionSupport.SUCCESS; }
4.2前台JS代码
function(e) { var viewResolution = map.getView().getResolution(); var url = wmsSource.getGetFeatureInfoUrl(e.coordinate,iewResolution,"EPSG:4326",{ INFO_FORMAT : "text/plain" }); var ajaxUrl="http://localhost:8081/ymgis/proxyAjax.action?url="+encodeURIComponent(url); $.ajax({url:ajaxUrl,success:function(data){ alert(data); }}); }