June 26, 2007 | tags ArcGIS Server | views 1578 <script type="text/javascript"></script>
有状态和无状态的应用程序2
我们继续讨论web程序的状态问题。其实写过诸如asp jsp的人都知道,类似session、cookie等东西在web页面程序中应用的非常广泛,因为这是我们让程序记住一个用户标志的方法,唯有使用这些对象,我们才能区分不同的用户。
事实上,有状态的web程序是极其常见的,许多我们根本没有意识到的“无状态”操作都依赖有状态的方法来实现,这种方法我们称为“浅状态程序”,例如下面这个例子,我们启动一个页面,然后点击一个“固定放大”按钮去放大地图,看起来似乎与状态无关,但是仔细想想,这种固定放大是依赖地图放大前一次的范围的,这意味着我们必须记录前一次的地图状态,这其实就是一种状态程序。
我们下面写这个代码:
页面启动:
private void Page_Load(object sender, System.EventArgs e)
{
// 在此处放置用户代码以初始化页面
if(!Page.IsPostBack)
{
if(Session.IsNewSession)
{
ESRI.ArcGIS.Server.WebControls.ServerConnection pServerConn=new ESRI.ArcGIS.Server.WebControls.ServerConnection("nbjbt");
pServerConn.Connect();
IServerObjectManager pSOM=pServerConn.ServerObjectManager;
//将SOM保存到全局变量区
Application.Set("som",pSOM);
IServerContext pSC=pSOM.CreateServerContext("nbserver","MapServer");
IServerObject pSO=pSC.ServerObject;
IMapServer pMapServer=(IMapServer)pSO;
IMapServerInfo pMapServerInfo=pMapServer.GetServerInfo(pMapServer.DefaultMapName);
IMapDescription pMapDesc=pMapServerInfo.DefaultMapDescription;
//将pMapDesc序列化为一个字符串,保存到一个session中
string ss=pSC.SaveObject(pMapDesc);
Session["md"]=ss;
//显示启动时默认地图
this.Image1.ImageUrl=this.CreateImage(pMapDesc,pSC);
//释放进程
pSC.ReleaseContext();
}
}
}
下面是按下固定放大时候的代码:
private void Button1_Click(object sender, System.EventArgs e)
{
IServerObjectManager pSom=(IServerObjectManager)Application.Get("som");
IServerContext pSC=pSom.CreateServerContext("nbserver","MapServer");
IMapServer pMapServer=(IMapServer)pSC.ServerObject;
//从session中取出上一次地图的描述对象
string smd=(string)Session["md"];
IMapDescription pMapDesc=(IMapDescription)pSC.LoadObject(smd);
IMapArea ma=pMapDesc.MapArea;
IEnvelope pEnv=ma.Extent;
pEnv.Expand(0.9,0.9,true);
IMapExtent mx=(IMapExtent)ma;
mx.Extent =pEnv;
pMapDesc.MapArea =ma;
//改变地图
this.Image1.ImageUrl=this.CreateImage(pMapDesc,pSC);
//将改变后的地图描述对象存入同名的session中
string ss=pSC.SaveObject(pMapDesc);
Session["md"]=ss;
pSC.ReleaseContext();
}
有“浅状态程序”,也就有相应的“深状态程序”了,后者必须是一种独占式的SO才行,因为深状态程序做的内容可能包括删除地图中的一个图层等操作,如果是非独占式的SO,显然不行,这就是说我们在深状态程序中,必须使用非池化SO才行。
最后还需要记住的一点是,如果访问非共享池模式的SO时产生了session,需要在Session_End事件中手工将这些session清除,这是因为服务器的空间和性能是有限的,产生太多的session会对服务器的性能有影响,而且对于非共享池模式的session而言,反正是独占式享用SO,在退出时保留session是浪费资源而已。