基于Mapserver的WebGIS设计

这是从我另外一个blog转过来的(打算全部移到这个blog上来)
http://www.gisempire.com/blog/user1/813/index.html
 
基于Mapserver的WebGIS设计
 

/***棒棒唐****/

package MapserverServlet;

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.*;
import edu.umn.gis.mapscript.*;

class  MapServlet
{
 /*
  1、定义一个出图参数对象。
  2、定义mapObj对象,属于全局级别(application),所有的Seesion都共用该对象。
###############################################################################################
  两种方案:
    1)、先前考虑过如果每个Seesion一个mapObj的话,mapObj的状态就不用管了,它自己会维护出图状态
    而且能保证前一次出图和后一次出图的连续性。但是如果每个Seesion一个mapObj的话,并发量上
    很受限制,内存都不够用。
    不过,这样一个session一个mapObj有这样一个好处,每个session可以做自己的专题图,做自己的分析
    :路径分析、缓冲分析等所产生的辅助线(多边形,点),而其他session不受一点影响。如果这样的话
    缓存又不好实现。
       当新的一个session产生时,调用mapObj的cloneMap很容易实现为该session生成一个mapObj,效率比
    new要高多了。
    2)、如果所有的session共用一个mapOjet的话,在并发量上,应该是没有什么问题,但是在控制每个session
    出图的状态就比较复杂了(因为要考虑到前一次出图和后一次出图的连续性),需要把所有的出图参数,
    根据相应的地图操作都执行一遍,如果管理不好的话,很容易回到最初状态,这个开销上是需要花时间的。
    管理好出图参数是关键。有了出图参数,比较容易建立缓存。如果动态做专题图的话,这个状态的跟踪就
    比较麻烦。(需要把每个图层的class信息在每个session中存储下来。)其实就是把每个layerObj复制一份cloneLayer
    ,在MapParam中,需要定义一个layerObj数组,这样每个Session都有一个自己的layerObj数组,在使用时候
     把layerObj数组赋值给mapObj,但是mapOjet并没有getLayer这个方法,先需要removeLayer,然后需要一个一个地insertLayer,把layerObj添加到mapObj中,
     这个过程不知道消耗的资源跟每个session一个mapObj消耗的资源差不多。

     缓存对于这种个人行为比较多的操作,起的作用不大,估计不采用缓存,效果估计还好一些。
     需要仔细权衡这量中思路。每种方案都自己的好处,如果做一个仅仅是看看的地图,那么采用第二种方式比较好(不需要在seesion中存储layerObj数组)。如果所进行的地图操作对于每个人来说都是很特别的
     也就是说公共的东西比较少,采用第一种方式比较好,来得方便实在也容易实现。
     基本上对于每个session,servlet都会给它开一个线程。
#################################################################################################
  3)、如果采用缓存技术的话,需要考虑到线程同步性
       hashtable是线程同步的而hashMap不是,尽量采用hashtable,可以省略自己关系线程安全的烦恼。
  4)、对于一个mapfile,可以考虑用一个hashtable,也可以所有的mapfile共有一个hashtable做缓存
       关键是看出图参数怎么定义咯。
    原则上来将一个mapfile需要一个mapObj,当然也可以所有的mapfile共用一个mapobj,但是这样不好
    线程的同步性不易控制,需要先关闭了,然后在new一个mapObj.
    咱们原则上是为每个mapfile生成一个mapObj。方便控制与管理。
  5)、在本MapServlet中,咱们只考虑一个mapfile,如果是多个mapflie的话,咱们就用多
  个MapServlet来与之对应吧。在web.xml中设定就可以了。
 */
 public void init() throws ServletException
 {
  //读取配置文件,根据配置文件找到mapfile,以及output目录  
   mapfile="D:/SuperMap/SuperMapISJava/thirdparty/tomcat/webapps/mapserver/tutorial.map";
   outputDir="output/";
   //构造一个默认的出图参数对象
   /*
   1、读取配置文件,根据配置文件找到mapfile,以及output目录
   2、构造一个默认的出图参数对象MapParam
   3、构造一个mapObj对象
   4、定义一个hashtable,用MapParam作为key,用出图的图片名作为value,用于缓存。
      hashtable是同步的,比hashMap相对要安全一些。
   5、高级:
      1)、采用一种策略管理hashtable表,不然内存就有可能耗光哦,
          一般可以通过建立一个守候线程(进程)来实现。锁是关键
   */
 }

 
 public void destroy()
 {
  /*
   1、hashtable清空
   2、mapObj对象清理资源
  */
 }

 public void service(HttpServletRequest request,
      HttpServletResponse response) throws
   ServletException, IOException
 {
  
  //保证一个session一个地图对象(如果用地图出图参数对象节约的内存可能会更少一些,
  //如果有出图参数对象,缓存实现起来也比较容易。
  //这样地图对象的状态得以恢复
  /*
   1、先从Session里读取出图参数对象MapParam,如果有则使用该出图参数对象,如果没有则从
   默认的出图对象clone一个。
   2、读取request传进来的地图命令以及参数。并修改MapParam对象,只修改改变的成员变量。
   
   3、根据MapParam对象出图。
    判断是否使用了缓存,如果MapParam是一样的,就把放在hashtable中的图片名称返回。
    否则,根据MapParam对象出图:其实就是根据request传进来的地图命令进行地图操作
    最后,要根据MapParam执行一遍(主要是extent、图层显示状态、trackingLayer),最后
    再出图。 drawQuery(mapObj map, imageObj image)
             draw(mapObj map, imageObj image)
       这两个都需要按顺序执行一遍,不然查询的状态就保存不下来了。

    
    1)* 这个MapParam一定要做到冗余度最小,以免进行不必要的操作。
     1)地图出图范围是最重要的。
     2)地图的图层状态(是否可视) 
     3)trackingLayer,必须要这么一个图层哦,可以在该图层上绘制当前会话的一些临时操作结果
       比如:缓冲分析是,所选中的featrue、以及缓冲的轮廓(比如点缓冲是一个圆)等辅助线(多边形)
             距离量算所画的折线,以及面积量算所画的多边形或者圆等
       查询时候,查询结果的高亮显示(就是就是在trackingLayer把选中的featrue再绘制了
       一遍)
     由于Mapserver没有trackingLayer这个说法,我们可以这样做:为每个session生成一个layerObj
     对象,把需要绘制的featrue,通过addFeature(shapeObj shape)添加到该layerobj上 ,别忘记了
     增加一个class哦,不然就绘制不出来
     再设置这个class的style等。
     不过也可以把距离,面积量算时,所绘制的线放到客户端以javascript来实现,其实想距离面积的量算
     完全可以放在客户端来实现(关键是把地理范围用Ajax技术传输到客户端。)
     2)*对于其他图层的编辑,就不需要每个seesion单独存储了,所有的session共用一个,但是必须处理
     锁的问题。(数据如果是在数据库中,就不需要考虑加锁的问题,数据库中的锁有行锁、表锁、
     列锁), 但是如果编辑的是一个shp文件或mif文件,就必须考虑加锁的问题。(现在不知道在Mapserver中
     是否已经处理好了这个锁的问题。是不是线程安全的?)
         在java中可以用synchronized来实现多线程的加锁问题(servlet是用多线程来处理每个session的),也可以自己来实现锁(标记,数据),在修改数据前,先查看标记看是否有其他线
      程在修改数据,这个标记起它一个锁的作用。
     加锁,需要考虑操作的原子性,在修改数据前,注意保存数据的前景,等修改完全成功了,才把数据前景给删除,否则需要回滚

     4、根据request决定是否生成图例与比例尺
         (也可以考虑是否采用缓存哦)
     5、输出的XML字符串大致包括如下内容。
        1)、图片的URL、Extent以及图片的高度宽度
     2)、图例的URL、以及图片的高度宽度
     3)、比例尺的URL、以及图片的高度宽度
     6、客户端request请求的图片包括RUL和图片的地理范围等,服务器端只需要传送客户需要的图片,然后在
     客户端进行拼接(对小图块)(这叫做在客户端缓存,仅仅传输需要的图块,节省网宽流量)

  */


 }

 
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值