最近做一个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() {
@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); }}); }