地图的开发研究--基于openlayers+geoserver+tomcat的离线地图-JAVA项目跨域问题的解决

时间:2022-08-28 16:06:23

 当我们开发openlayers+geoserver+tomca的地图的时候,在页面调用geoserver的WMS服务的时候不需要考虑此问题。不过如果要使用WFS服务(如过滤查询)的时候就需要考虑跨域问题了。注:此处针对的是JAVA WEB项目:

 由于本地开发部署项目的tomcat服务器和geoserver地图服务器不在同一个服务器上,前台所在域名下会调用地图服务器域名下的应用,所以此时产生了跨域问题。但是经测试可以发现,IE浏览器可以跨域访问,非IE浏览器则不行,为了兼容浏览器,跨域问题需要解决。 

   对于openlayers,它早已提供了一个跨域的解决策略,即在每一个js的开始加上一句话:

OpenLayers.ProxyHost = "cgi/proxy.cgi?url=";但是仅仅加上这句话经过测试发现,无法解决跨域问题,还需要进行一系列的配置操作,通过参考网上的解决方案,终于解决了此跨域问题。

具体的配置介绍如下:

① 下载Python.exe(python-2.7)工具(一种解析工具),安装到本地磁盘(推荐直接放到c盘根目录下)。此软件据猜想用于url地址的解析,经测试表明应该是类似个中转站,将网址转到了openlayers的主页,然后主页再进行转发到地图服务器,这也许就是造成地图查询结果缓慢的原因

② 修改本地项目部署tomcat服务器的context.xml添加<Context privileged="true">获取tomcat的管理员权限,使用tomcat的管理员权限的servlet如下图:

地图的开发研究--基于openlayers+geoserver+tomcat的离线地图-JAVA项目跨域问题的解决

① 在项目WEB_INF下添加一个目录和文件,proxy.cgi文件复制的是openlayers自带的跨域解决方案文件,具体应该在openlayers的源文件的examples文件夹中:

地图的开发研究--基于openlayers+geoserver+tomcat的离线地图-JAVA项目跨域问题的解决

打开proxy.cgi文件,allowedHosts数组中添加部署地图服务器的地址,如我们已经部署在局域网的的一台geoserver服务器(192.168.1.100:8080

地图的开发研究--基于openlayers+geoserver+tomcat的离线地图-JAVA项目跨域问题的解决

同时打开项目WEB_INF下的web.xml文件,如果第一步Python你没有安装到c盘,请修改红色区域的地址,此处使用的是tomcat的一个服务,具体干嘛的不清楚,从我的理解来看是用来对OpenLayers.ProxyHost = "cgi/proxy.cgi?url=";进行处理的,servlet的原理就不介绍了。

地图的开发研究--基于openlayers+geoserver+tomcat的离线地图-JAVA项目跨域问题的解决

 至此 跨域问题就解决了。在调用WFS服务的页面的js第一句话首先添上,即可解决wfs服务跨域问题

OpenLayers.ProxyHost = "modules/xj/app/GIS/cgi/proxy.cgi?url=";//如果tomcat和geoserver在同一台服务器上,不需要此句话



附: 

一、对前期所做的高亮查询的进一步优化

  前期学习geoserverWFS服务的时候,曾经提过优化的问题,使用openlayersOpenLayers.Filter.Logical方法,转换成xml转给地图服务器,调用WFS服务,返回相关信息。

   Wfs服务包含getFeature操作,用来检索要素信息,支持返回gml格式的地理要素表达。根据getFeature提供的参数FILTER,我们就可以实现条件查询。

   Filter是一种基于XML的并且符合OGC规范的语言。SLD用它来实现复杂的Rule选择。WFS在所有需要定位操作对象的地方都会使用Filter。Filter的作用是构建一个表达式,返回值就是Feature的集合,换句话说Filter就如他的名字一般为我们从一个集合中过滤出一个满足我们要求的子集。而过滤的方法就是Filter定义的操作符。Filter定义了三种操作符:地理操作符(Spatial operators),比较操作符(Comparison operators)和逻辑操作符(Logical operators)。

   所以就通过自定义XML语句作为查询条件,不过OpenLayers已经写好了Filter过滤条件和转成xml的类,这样Filter标签里的内容不用逐个编写了,如下:

Var Filter=OpenLayers.Filter.Logical({

                    type: OpenLayers.Filter.Logical.OR,

                    filters: [

                        new OpenLayers.Filter.Comparison({

                            type: OpenLayers.Filter.Comparison.LIKE,

                            property: "NAME",

                            value: area+"*"

                        })

                    ]

                })

 

  所以通过OpenLayers的这个方法可以大大缩小我们的开发时间,提高开发效率。

 相关代码:

function qry() {
	area = document.getElementById("qry").value;//获取输入框输入的待查询的区域
	if (area == "") {
		return;
	}
	if (i > 0) {
		temVectorLayer.setVisibility(false);//如果map已经添加了vector层,设置temVectorLayer不可见

	}

	temVectorLayer = new OpenLayers.Layer.Vector("WFS", {
		strategies : [ new OpenLayers.Strategy.BBOX() ],
		protocol : new OpenLayers.Protocol.WFS({
			url : geoServer_url + "/wfs",
			featureType : "bou2_4p",
			featureNS : "http://192.168.1.100:8080/geoserver/mytest/wms"   //调用远程服务器的geoserver的wfs服务
		}),
		styleMap : new OpenLayers.StyleMap({
			strokeWidth : 1,
			strokeColor : "grey",
			fillColor : "red",
			fillOpacity : 0.2

		}),
		filter : qyr1(area)    //根据区域获得过滤条件。通过openlayers构造
	});
	map.addLayers([ temVectorLayer ]);
	i++;
	map.setCenter(new OpenLayers.LonLat(103, 36), 1);
}

 
//根据区域获得过滤条件。通过openlayers构造
function qyr1(area) {return new OpenLayers.Filter.Logical({type : OpenLayers.Filter.Logical.OR,filters : [ new OpenLayers.Filter.Comparison({type : OpenLayers.Filter.Comparison.LIKE,property : "NAME",value : area + "*" //类似sql语句的 where name like xx*的模糊查询}) ]})}