內蒙古java團隊

          j2se,j2ee開發組
          posts - 139, comments - 212, trackbacks - 0, articles - 65
            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

          MapGuide源碼分析【

          Posted on 2011-04-15 00:24 帥子 閱讀(376) 評論(0)  編輯  收藏 所屬分類: MapGuide

          本節中,我們將通過介紹如何完成枚舉資源功能來介紹MapGuide Web擴展的部分源代碼。

          在瀏覽器端的地址欄輸入類似如下字符串,就會發送一個枚舉資源的HTTP請求。

          http://hostname/mapGuide/mapagent.fcig?OPERATION=EnumerateResources&VERSION=1.0.0& RESOURCEID=Library:// &TYPE=FeatureSource&DEPTH=3

          下面我們來看看MapGuide Web擴展如何處理這個請求。

          在介紹MapGuide Web擴展如何處理枚舉資源HTTP請求之前,讓我們首先來看看MapGuide Web擴展用于處理HTTP請求和響應的類,這些類的類圖如圖19?4所示。

          clip_image002

          圖 19?5 HTTP請求和響應類的類圖

          類MgHttpRequest和類MgHttpResponse分別是對HTTP請求和響應結果的抽象,這兩個類可以用于任何類型的Web應用服務器,也就是說它們的代碼不依賴于任何Web應用服務器API。在文件夾“\MgDev\Web\src\HttpHandler”下可以找到所有前綴為“MgHttp”類的源代碼。

          類MgHttpRequest用于處理HTTP請求,它包含了一個HTTP請求頭MgHttpHeader的實例、一個HTTP請求參數HttpRequestParam的實例和一個HTTP請求元數據HttpRequestMetadata的實例。調用方法MgHttpRequest::Execute()會將HTTP請求轉發給MapGuide服務器,當MapGuide服務器處理完這個請求,將請求結果返回給Web擴展之后,這個方法會返回一個MgHttpResponse對象,它表示HTTP請求的響應結果。

          接下來讓我們看看MapGuide Web擴展如何處理枚舉資源的HTTP請求。大多數MapGuide用戶都是使用IIS作為Web應用服務器,并且使用Web擴展模塊isapi_MapAgent.dll來處理HTTP請求,所以本節側重于isapi_MapAgent.dll模塊處理HTTP請求的流程,這個處理流程的時序圖如圖19?5所示。

          clip_image004

          ?19?6 Web擴展處理枚舉資源請求的時序圖

          1) 加載Web應用服務器擴展模塊

          如果使用的是IIS Web應用服務,那么在接收到后綴為“fcgi”的HTTP請求后,IIS會加載Web應用服務器擴展模塊isapi_MapAgent.dll或MapAgent.exe。其中,isapi_MapAgent.dll基于IIS API,具有更好的性能;MapAgent.exe基于CGI技術,性能要稍微差一些。如果使用的是Apache Web應用服務器,那么在Windows平臺上Apache會加載Web應用服務器擴展模塊MapAgent.exe,在Linux平臺上會加載模塊mod_mgmapagent.so。

          這三個Web服務器擴展模塊實現了類似的功能,它們的源代碼位置如表19?2所示。

          服務器擴展模塊

          源代碼位置

          isapi_MapAgent.dll

          \Web\src\IsapiAgent

          MapAgent.exe

          \Web\src\CgiAgent

          mod_mgmapagent.so

          \Web\src\ApacheAgent

          ?19?2 Web服務器擴展模塊的源代碼位置

          從圖19?6中可以看到這三個Web服務器擴展模塊提供了類似的類,這些類提供了相同的接口,類XXXPostParser用于解析HTTP請求中傳入的參數及參數值,類XXXResponseHandler用于將HTTP請求的響應結果發送給客戶端。其中,“XXX”表示“Cgi”、“Isapi”或“Apache”。

          clip_image006

          ?19?7 Web擴展的請求處理模塊

          對于模塊isapi_MapAgent.dll,每個“fcgi”類型的HTTP請求會調用此模塊中的方法HttpExtensionProc,這個方法的代碼如下所示,為了便于理解我們只保留了一些核心代碼。

          DWORD WINAPI HttpExtensionProc(EXTENSION_CONTROL_BLOCK *pECB)

          {

          Initialize(pECB);

          // 調用GetServerVariable讀取諸如服務器名稱、端口號等服務器變量信息

          ......

          // 創建MgHttpRequest的實例,用于處理HTTP請求

          Ptr request = new MgHttpRequest(wUrl);

          // 解析HTTP請求中的參數,并且將這些參數置入MgHttpRequest對象中

          Ptr params = request->GetRequestParam();

          ......

          IsapiPostParser postParser(pECB);

          postParser.Parse(params);

          ......

          // 創建IsapiResponseHandler的實例,用于將響應請求返回給客戶端

          IsapiResponseHandler responseHandler(pECB);

          ......

          // 將HTTP請求轉發給MapGuide服務器,當MapGuide服務器處理完這個請求,

          // 將請求結果返回給Web擴展之后,這個方法會返回一個MgHttpResponse對象,

          // 它表示HTTP請求的響應結果。

          Ptr response = request->Execute();

          // 將響應結果返回給客戶端

          responseHandler.SendResponse(response);

          ......

          }

          2) 創建MgHttpRequest的實例,用于處理HTTP請求

          在加載Web應用服務器擴展模塊后,需要創建一個MgHttpRequest的實例用于處理HTTP請求。類MgHttpRequest并不關聯與任何類型的Web應用服務器,所以Web應用服務器擴展模塊會使用類XXXPostParser解析HTTP請求中傳入的參數及參數值,將這些參數設置到MgHttpRequest對象中。

          3) 調用方法MgHttpRequest::Execute()處理HTTP請求

          方法MgHttpRequest::Execute()的源代碼如下所示。為了便于理解,我們同樣只保留了一些核心代碼。

          MgHttpResponse* MgHttpRequest::Execute()

          {

          Ptr hResponse;

          Ptr result;

          // 創建MgHttpResponse對象,用于返回HTTP請求響應結果

          hResponse = new MgHttpResponse();

          result = hResponse->GetResult();

          // 獲得HTTP請求中參數“OPERATION”的值

          STRING sParamValue = m_requestParam->GetParameterValue(MgHttpResourceStrings::reqOperation);

          ......

          // 根據參數“OPERATION”的值取得對應操作的請求響應處理器

          Ptr rrHandler =

          CreateRequestResponseHandler(sParamValue, result);

          .......

          // 處理HTTP請求

          if(rrHandler != NULL) rrHandler->Execute(*hResponse);

          ......

          // 返回響應結果

          return SAFE_ADDREF((MgHttpResponse*)hResponse);

          }

          每個HTTP請求中包含一個參數“OPERATION”,它用于代表操作的類型。對于不同的操作,MapGuide定義了不同的請求響應處理器類,這個類會調用MapGuide服務中對應的方法處理這個操作,這些請求響應處理器類的類圖如圖19?7所示。從圖19?7可以看到,所有請求響應處理器類都繼承自類MgHttpRequestResponseHandler,每一種操作都有一個對應的子類,例如枚舉資源操作使用了類MgHttpEnumerateResources,描述模式操作使用了類MgHttpDescribeSchema。

          clip_image008

          ?19?8 HTTP請求響應處理器的類圖

          MapGuide定義了一個全局map對象用于存放每種操作對應的請求響應處理器類對象,它的鍵是操作的名稱,值是請求響應處理器類對象。

          // 定義一個全局map對象,用于存放每種操作對應的請求響應處理器類對象

          static map

          httpClassCreators;

          bool InitializeStaticData()

          {

          httpClassCreators[MgHttpResourceStrings::opGetMap] =

          MgHttpGetMap::CreateObject;

          httpClassCreators[MgHttpResourceStrings::opGetMapUpdate] =

          MgHttpGetMapUpdate::CreateObject;

          httpClassCreators[MgHttpResourceStrings::opGetDrawing] =

          MgHttpGetDrawing::CreateObject;

          ......

          httpClassCreators[MgHttpResourceStrings::opDescribeDrawing] = MgHttpDescribeDrawing::CreateObject;

          httpClassCreators[MgHttpResourceStrings::opEnumerateResources] = MgHttpEnumerateResources::CreateObject;

          ......

          }

          調用方法MgHttpRequest::CreateRequestResponseHandler(...)可以根據操作的名稱獲得對應的請求響應處理器類對象。對于枚舉資源操作,它會返回一個類MgHttpEnumerateResources的對象。

          調用這些請求響應處理器類的Execute(…)方法,會創建一個代理服務類對象,然后調用代理服務中對應的方法。為什么說創建的是一個代理服務類對象呢?我想看完圖19?8之后大家會有所明白。從圖19?8中可以看到,所有的MapGuide服務有兩個子類,一個是名稱為MgProxyXXXService的代理服務類,它是MapGuide Web擴展端的一個類,另一個是名稱為MgServerXXXService的服務器服務類,它是MapGuide服務器端的一個類。MgProxyXXXService最終會將服務請求轉發給服務器端類MgServerXXXService,所以說真正處理服務請求的類是MgServerXXXService,MgProxyXXXService僅僅起到一個轉發的作用,這也就是為什么稱類MgProxyXXXService為代理服務類的原因。

          clip_image010

          ?19?9 代理服務和服務器服務類的類圖

          對于枚舉資源操作,MgHttpEnumerateResources::Execute(...)的源代碼如下所示。調用這個方法會創建一個代理資源服務類MgProxyResourceService的對象,然后調用MgProxyResourceService::EnumerateResources(...)枚舉資源,最后將操作的執行結果放入MgHttpResponse對象中。

          void MgHttpEnumerateResources::Execute(MgHttpResponse& hResponse)

          {

          Ptr hResult;

          hResult = hResponse.GetResult();

          // 檢查HTTP請求中的參數

          ValidateCommonParameters();

          // 創建MgProxyResourceService實例

          Ptr mgprService =

          (MgResourceService*)(CreateService(MgServiceType::ResourceService));

          ......

          // 執行枚舉資源操作

          Ptr byteReader = mgprService->

          EnumerateResources(&mgrIdentifier, m_depth, m_type, m_computeChildren);

          // 如果需要,轉換響應請求的格式

          ProcessFormatConversion(byteReader);

          // 將操作結果放入響應請求中的MgHttpResult對象

          hResult->SetResultObject(byteReader, byteReader->GetMimeType());

          }

          MgByteReader* MgProxyResourceService::EnumerateResources(

          MgResourceIdentifier* resource, INT32 depth, CREFSTRING type,

          INT32 properties, CREFSTRING fromDate, CREFSTRING toDate,

          bool computeChildren)

          {

          MgCommand cmd;

          cmd.ExecuteCommand(m_connProp,

          MgCommand::knObject,

          MgResourceService::opIdEnumerateResources,

          7,

          Resource_Service,

          BUILD_VERSION(1,0,0),

          MgCommand::knObject, resource,

          MgCommand::knInt32, depth,

          MgCommand::knString, &type,

          MgCommand::knInt32, properties,

          MgCommand::knString, &fromDate,

          MgCommand::knString, &toDate,

          MgCommand::knInt8, (int)computeChildren,

          MgCommand::knNone);

          SetWarning(cmd.GetWarningObject());

          return (MgByteReader*)cmd.GetReturnValue().val.m_obj;

          }

          4) 將HTTP請求的響應結果返回給客戶端

          調用MgHttpRequest::Execute()會返回一個MgHttpResponse對象,這個對象包含了HTTP請求的響應結果。不過,還需要調用方法XXXResponseHandler::SendResponse(...),這樣Web應用服務器才會將這個響應結果返回給客戶端。

          主站蜘蛛池模板: 建瓯市| 佛山市| 民和| 定州市| 台东市| 淅川县| 江门市| 稻城县| 阜城县| 图们市| 秦皇岛市| 凉山| 田阳县| 青阳县| 伊宁县| 和平县| 大兴区| 望谟县| 将乐县| 马关县| 皋兰县| 南汇区| 上思县| 阳城县| 蛟河市| 兴化市| 登封市| 亚东县| 赤城县| 江阴市| 巨野县| 永安市| 无为县| 吉安县| 泌阳县| 全南县| 泽州县| 志丹县| 罗定市| 莆田市| 怀柔区|