1.开发控件的选择目前影响较大的国外地理服务器有Mapinfo MapXtreme、MapObject、Autodesk Map Guide、ArcIMS、Argcgisserver以及国内的Super Map等。由于考虑到我们是采用Java语言开发基于Web方式的Gis应用,最终对比之后采用Mapinfo公司的MapXtreme Java作为开发控件进行地理应用的二次开发工具。
MapXtreme Java 是目前用于 Internet 或企业 Intranet 唯一的 100% 纯 Java 的地图服务器。 MapInfo MapXtreme Java 与 J2EE 兼容,为开发人员开发应用提供了无与伦比的灵活性。 MapXtreme Java 向应用开发商提供了一个高度可视化的、直观的组件,方便他们将地图功能集成到任何 Web 应用中。
MapXtreme Java为 Internet 设计三种布署模式
瘦客户端
所有的地图生成 / 渲染是由服务器端完成的。客户只接收小于 20k 的 GIF 。在服务器端, MapXtreme 作为一个 Servlet 与 Web 服务器相连接,或者集成了 Web 服务器和应用服务器的功能。
中型客户端
Web 浏览器装载了一个 Java Applet ,但仍然从 MapXtreme 的 Servlet 中得到基于 GIF/JPEG 的地图图像。这种环境增加了灵活的用户交互,同时将从服务器下载的信息量降到最低。
胖客户端
装载了 applet 后,地图以一系列矢量的形式传输到 applet 中。这样,除了可从任何远程数据库中获得的空间对象外,所有的地图功能都属于客户 applet 。这种环境最适于更高带宽的内部网,所有的数据都能传输到每个客户端。要使用这种模式, MapXtreme 必须以命名用户方式注册。 MapXtremeJava 以压缩了 10 倍的数据格式形成矢量流,便于网络传输,减少响应时间。
考虑到IE对applet的支持,客户端用户对IE的设置的反感,我们决定采用瘦客户端的部署模式。所有的地图生成全部由服务器来完成,web gis应用中的客户端和普通web应用中的客户端一样。
2.MapXtreme Java的安装与使用2.1安装MapXtreme Java第一步:到网站http://www.mapinfo.com.cn下载开发控件MapXtreme Java Edition 4.8.0。
同时可以下载一些文档说明和sample地图供学习使用。
第二步:运行install.exe文件,跟普通的windows下安装软件一样安装。
安装成功后,开始菜单中会出现如下所示下拉菜单选项:
1.jpg
2.2 MapXtreme Java工具的使用
2.2.1 MapXtreme ServerMapXtreme Server是用于生成地图的web服务器,也即是地图服务器。
通过菜单栏中的“Start MapXtreme Server”启动地图服务器。
2.jpg
然后,我们可以打开IE在地址栏中输入http://127.0.0.1:8080/进行访问。
3.jpg
我们可以看到左边的导航条中有很多有用的链接信息。主要包括对tomcat的管理、API文档的说明、地图应用的sample。可以根据自己的兴趣进行点击查看,进行学习。推荐先查看Examples中的Servlet部分,然后查看Documentation中的MapXtreme Java API以便有针对性的学习。
通过点击菜单目录中的“Stop MapXtreme Server”来关闭地图服务器。
2.2.2 MapXtreme Java Manager通过点击菜单栏中的“MapXtreme Java Manager-WebServer”启动MapXtreme Java Manager。注意:必须在地图服务器启动以后,MapXtreme Java Manager-WebServer才能正常启动。
4.jpg
MapXtreme Java Manager启动成功以后,会弹出如下的界面:
5.jpg
也可通过菜单目录的“MapXtreme Java Manager-StandAlone”在独立模式下启动MapXtreme Java Manager。后者的启动不依赖于地图服务器的启动与否。二者的区别在于后者启动方式下功能比前者少,不能与地图服务器进行交互。独立模式下启动界面如下图所示:
6.jpg
我们可以通过MapXtreme Java Manager客户端对指定格式(*.mdf和*.gst)的地图文件进行查看及编辑,功能十分强大。此客户端还具有web应用程序定制、创建用于命名地图和图层的上下文、管理JDBC连接等高级功能。
7.jpg
3.构建自己的web gis应用3.1熟悉MapJ
APIMapJ对象管理地图的状态。该对象维护地图中心和缩放、坐标系、距离单位和共同构成地图的图层。MapJ位于MapXtreme客户机API的最顶端。
打开MapXtreme Java的API文档,选择com.mapinfo.mapj,对类 MapJ中的每个方法的使用我们都应该仔细阅读,因为在开发web gis的过程中我们将会用到。
8.jpg
其中,尤为关键的,我们需要了解如下几个方法:
MapJ对象初始化:MapJ()
加载地图:loadMapDefinition()
设置地图边界:setDeviceBounds()
设置地图中心:setCenter()
设置地图缩放比:setZoom()
3.2 熟悉Javascript中鼠标响应事件我们在客户端浏览器中往往需要点击地图上的位置进行精确定位,或对地图进行放大、缩小、平移等操作,这时候就需要将客户端的请求提交到服务器端,与地图服务器进行交互。
为了实现客户端与服务器的交互,必须要能捕捉到用户的鼠标响应事件,获得鼠标指针的当前位置等信息。
其中,特别需要关注的鼠标响应事件有:
鼠标按下事件:onmousedown
鼠标松开事件:onmouseup
鼠标指针移动到元素上触发事件:OnMouseOver
此外,还可能需要用到onclick、oncontextmenu、onmousewheel等事件,根据自己开发的web gis应用的需要来选择使用。
4.3 开发一个完整的web gis应用4.3.1 搭建开发环境进行web gis开发的编程环境:
支持开发web应用的Java IDE(如MyEclipse、Jbuilder),支持servlet的web应用服务器(如tomcat、weblogic),支持javascript的浏览器(如IE 6.0),标准格式的地图图片(*.gst,*.mdf)。
将安装目录中MapXtreme-4.8.0/apache-tomcat-5.5/webapps/mapxtreme480复制到自己的应用服务器发布目录下,或者仍沿用安装时MapXtreme默认安装的tomcat来部署地图服务器。
启动地图服务器,通过访问服务器地址http://127.0.0.1:80/mapxtreme480/servlet/mapxtreme来查看是否部署成功。若显示为一空白页面则表明已部署成功。
4.3.2 编写一个简单的servlet首先编写一个简单的servlet,后面我们将重写其doGet方法来生成地图。
将安装目录中/MapXtreme-4.8.0/lib/common中的文件和/MapXtreme-4.8.0/lib/server中的文件复制到自己的web应用中的/WEB-INF/lib目录下。
,然后启动web服务器,通过浏览器访问servlet看是否运行正常。
3.3.3 编写生成地图的服务端代码这里所指的生成地图的服务端代码是指web服务器中servlet响应客户端请求生成图片信息的代码,具体讲就是指servlet中重写的doGet( )方法中的代码。特别注意的是,这里所指的生成地图的代码是我们通过调用MapJ的API向地图服务器发送生成地图请求的代码;相对地图服务器而言,我们这里编写的又是地图服务的客户端代码;相当于web应用而言,我们这里编写的却又是服务端代码。
下面我们以一个实例来介绍如何调用MapJ API编写生成地图的服务端代码。
第一步:向地图服务器发送请求生成地图
[java] view plain copy print ?
-
- private static String mimeType = "image/gif";
-
- private static String m_mxtURL = "http://localhost:80/mapxtreme480/servlet/mapxtreme";
-
- public void doGet(HttpServletRequest request, HttpServletResponse response)
- throws IOException, ServletException {
-
- response.setContentType(mimeType);
-
- ServletOutputStream sos = response.getOutputStream();
-
- MapJ m_mapj = new MapJ();
- try {
-
- String m_mapPath="E://gisapp//MapData//Others//China.mdf";
- m_mapj.loadMapDefinition(m_mapPath);
-
- m_mapj.setDeviceBounds(new DoubleRect(0, 0, 800, 600));
- request.getSession().setAttribute("worldMap", m_mapj);
-
- ImageRequestComposer irc = ImageRequestComposer.create(m_mapj, 256,
- Color.white, mimeType);
-
- MapXtremeImageRenderer renderer = new MapXtremeImageRenderer(
- m_mxtURL);
-
- renderer.render(irc);
-
- renderer.toStream(sos);
-
- renderer.dispose();
- } catch (Exception e) {
- System.out.println("Error");
- e.printStackTrace();
- }
- }
// 输出图片的格式 private static String mimeType = "image/gif"; // mapxtremeservlet地图服务器url private static String m_mxtURL = "http://localhost:80/mapxtreme480/servlet/mapxtreme"; // 实现HttpServlet的doGet方法 public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { // 设置ContentType response.setContentType(mimeType); // 返回响应的输出流 ServletOutputStream sos = response.getOutputStream(); // 创建MapJ对象 MapJ m_mapj = new MapJ(); try { // 加载地图 String m_mapPath="E://gisapp//MapData//Others//China.mdf"; m_mapj.loadMapDefinition(m_mapPath); // 设置地图大小 m_mapj.setDeviceBounds(new DoubleRect(0, 0, 800, 600)); request.getSession().setAttribute("worldMap", m_mapj); // 创建图像请求器(包装mapj对象,图片的色位,底色,格式信息) ImageRequestComposer irc = ImageRequestComposer.create(m_mapj, 256, Color.white, mimeType); // 创建mxtj的图像渲染器 MapXtremeImageRenderer renderer = new MapXtremeImageRenderer( m_mxtURL); // 用渲染器渲染请求器 renderer.render(irc); // 渲染器输出图片流到输出流,客户端显示之 renderer.toStream(sos); // 释放渲染器对象 renderer.dispose(); } catch (Exception e) { System.out.println("Error"); e.printStackTrace(); } }
第一步显示效果如下:
1.jpg
第二步:控制地图的显示(响应客户端对地图放大、缩小、重定位、平移的请求)
CODE:
[java] view plain copy print ?
- int xpoint=Integer.parseInt(request.getParameter("xpoint"));
- int ypoint=Integer.parseInt(request.getParameter("ypoint"));
- double zoomSize=Double.parseDouble(request.getParameter("zoomSize"));
-
- ServletOutputStream sos = response.getOutputStream();
-
- MapJ m_mapj = (MapJ)request.getSession().getAttribute("worldMap");
- try {
-
- DoublePoint dpt= m_mapj.transformScreenToNumeric(new DoublePoint(xpoint,ypoint));
- m_mapj.setCenter(dpt);
-
- ImageRequestComposer irc = ImageRequestComposer.create(m_mapj, 256,
- Color.white, mimeType);
-
- MapXtremeImageRenderer renderer = new MapXtremeImageRenderer(
- m_mxtURL);
-
- renderer.render(irc);
-
- renderer.toStream(sos);
-
- renderer.dispose();
- } catch (Exception e) {
- e.printStackTrace();
- }
int xpoint=Integer.parseInt(request.getParameter("xpoint"));//鼠标left坐标 int ypoint=Integer.parseInt(request.getParameter("ypoint"));//鼠标top坐标 double zoomSize=Double.parseDouble(request.getParameter("zoomSize"));//缩放比 // 返回响应的输出流 ServletOutputStream sos = response.getOutputStream(); // 获取地图对象 MapJ m_mapj = (MapJ)request.getSession().getAttribute("worldMap"); try { // 设置地图大小 DoublePoint dpt= m_mapj.transformScreenToNumeric(new DoublePoint(xpoint,ypoint)); m_mapj.setCenter(dpt); // 创建图像请求器(包装mapj对象,图片的色位,底色,格式信息) ImageRequestComposer irc = ImageRequestComposer.create(m_mapj, 256, Color.white, mimeType); // 创建mxtj的图像渲染器 MapXtremeImageRenderer renderer = new MapXtremeImageRenderer( m_mxtURL); // 用渲染器渲染请求器 renderer.render(irc); // 渲染器输出图片流到输出流,客户端显示之 renderer.toStream(sos); // 释放渲染器对象 renderer.dispose(); } catch (Exception e) { e.printStackTrace(); }
第二步,点击放大后可看到主要城市的图层信息,效果如下:
2.jpg
进一步放大后,能看到更多的图层信息,效果如下:
3.jpg
第三步:查询图层信息(根据客户端点击的地图位置,展现不通的图层信息)
CODE:
[java] view plain copy print ?
- PrintWriter out = response.getWriter();
- HttpSession session = request.getSession();
- String xmlInfo = "";
- xmlInfo +="<LAYERS><CITY>";
- try {
- int xpoint=Integer.parseInt(request.getParameter("xpoint"));
- int ypoint=Integer.parseInt(request.getParameter("ypoint"));
- MapJ mainMap = (MapJ) session.getAttribute("worldMap");
- FeatureLayer layer = (FeatureLayer) mainMap.getLayers().get("CHCTY_2K");
-
- if (layer.isVisibleAtCurrentZoom()) {
- ArrayList columns = new ArrayList();
- columns.add("lace_Name");
- columns.add("Latitude");
- columns.add("Longitude");
- DoubleRect rect = mainMap.transformScreenToNumeric(new DoubleRect(new DoublePoint(xpoint-100, ypoint-100), new DoublePoint(xpoint+100, ypoint+100)));
- FeatureSet fs = layer.searchWithinRectangle(columns, rect, QueryParams.EMPTY_PARAMS);
- Feature f;
- while ((f = fs.getNextFeature()) != null ) {
- for (int i = 0; i < f.getAttributeCount(); i++) {
- switch (i)
- {
- case 0:
- xmlInfo +="<LACENAME>"+f.getAttribute(i)+"</PLACENAME>";
- break;
- case 1:
- xmlInfo +="<LATITUDE>"+f.getAttribute(i)+"</LATITUDE>";
- break;
- case 2:
- xmlInfo +="<LONGITUDE>"+f.getAttribute(i)+"</LONGITUDE>";
- break;
- }
-
- }
- }
- fs.dispose();
- }
- } catch (Exception ex) {
- ex.printStackTrace();
- }
- xmlInfo +="</CITY></LAYERS>";
- out.print(xmlInfo);
PrintWriter out = response.getWriter(); HttpSession session = request.getSession(); String xmlInfo = ""; xmlInfo +="<LAYERS><CITY>"; try { int xpoint=Integer.parseInt(request.getParameter("xpoint")); int ypoint=Integer.parseInt(request.getParameter("ypoint")); MapJ mainMap = (MapJ) session.getAttribute("worldMap"); FeatureLayer layer = (FeatureLayer) mainMap.getLayers().get("CHCTY_2K"); //创建一个图原层 if (layer.isVisibleAtCurrentZoom()) { ArrayList columns = new ArrayList(); columns.add("lace_Name"); columns.add("Latitude"); columns.add("Longitude"); DoubleRect rect = mainMap.transformScreenToNumeric(new DoubleRect(new DoublePoint(xpoint-100, ypoint-100), new DoublePoint(xpoint+100, ypoint+100))); FeatureSet fs = layer.searchWithinRectangle(columns, rect, QueryParams.EMPTY_PARAMS);//得到图元集 Feature f; while ((f = fs.getNextFeature()) != null ) { for (int i = 0; i < f.getAttributeCount(); i++) { switch (i) { case 0: xmlInfo +="<LACENAME>"+f.getAttribute(i)+"</PLACENAME>"; break; case 1: xmlInfo +="<LATITUDE>"+f.getAttribute(i)+"</LATITUDE>"; break; case 2: xmlInfo +="<LONGITUDE>"+f.getAttribute(i)+"</LONGITUDE>"; break; } } } fs.dispose(); } } catch (Exception ex) { ex.printStackTrace(); } xmlInfo +="</CITY></LAYERS>"; out.print(xmlInfo);
第三步,点击右键菜单,查看城市坐标图层信息:
4.jpg
查询出一定范围内的城市的坐标信息,示例效果如下:
5.jpg
3.3.4 控制页面与后台的交互
获取客户端鼠标点击位置:
CODE:
[java] view plain copy print ?
-
-
-
- var xOffset=0;
- var yOffset=0;
- function getObjOffset(){
- var obj=document.all('chinaMap');
- var xOff, yOff;
- xOff = 0;
- yOff = 0;
- while (null != obj) {
- xOff += obj.offsetLeft;
- yOff += obj.offsetTop;
- obj = obj.offsetParent;
- }
- xOffset=xOff;
- yOffset=yOff;
- }
- var xpoint=event.x- xOffset;
- vary point=event.y- yOffset;
/** *获取地图的偏移量 */ var xOffset=0; var yOffset=0; function getObjOffset(){ var obj=document.all('chinaMap'); var xOff, yOff; xOff = 0; yOff = 0; while (null != obj) { xOff += obj.offsetLeft; yOff += obj.offsetTop; obj = obj.offsetParent; } xOffset=xOff; yOffset=yOff; } var xpoint=event.x- xOffset;//鼠标x坐标 vary point=event.y- yOffset;//鼠标y坐标
设置鼠标指针样式:
element.style.cursor=”hand”;
element.style.cursor=”move”;
设置菜单位置(若有右键操作时可设置):
menuDiv.style.left=event.x;
menuDiv.style.top=event.y;