国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

利用多態(tài),實(shí)現(xiàn)一般處理程序(ashx)中的AOP(切面編程)

2019-11-14 14:33:09
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

本文是對(duì)工作中的項(xiàng)目進(jìn)行代碼優(yōu)化(完善登陸驗(yàn)證的AOP切面編程)時(shí),所遇到的各種解決方案思考過(guò)程。

項(xiàng)目背景:由ashx+nvelocity構(gòu)建的簡(jiǎn)單B/S問(wèn)卷系統(tǒng),現(xiàn)需要優(yōu)化登錄驗(yàn)證環(huán)節(jié)(時(shí)隔若干個(gè)月在回顧代碼果然是一個(gè)痛苦的過(guò)程~)

nvelocity是velocity框架針對(duì).net的版本,核心是拼html字符串后返回客戶端,與MVC的前后端代碼隔離有異曲同工之妙。加之一般處理程序ashx不需要像asp.net那樣走生成控件樹(shù)的過(guò)程,執(zhí)行上更是省時(shí)省力。故簡(jiǎn)單系統(tǒng)用ashx+nvelocity的形式構(gòu)建筆者個(gè)人還是比較推薦的。如果那么在意訪問(wèn)地址(如www.abc.com/news/index.ashx?id=234)中的ashx后綴不好看,完全可以通過(guò)模塊(HttpModule)來(lái)實(shí)現(xiàn)url重寫。

本文討論的是:如何在ashx中體現(xiàn)AOP切面編程思想?

(1)回顧asp.net,所有頁(yè)面繼承自Page類,可通過(guò)Page的子類來(lái)實(shí)現(xiàn)AOP。原來(lái)是:Default : Page,切面插入后是:Default : LoginCheckPage,LoginCheckPage : Page。如此便能在LoginCheckPage類中編寫登錄驗(yàn)證的代碼,且能實(shí)現(xiàn)所有需要驗(yàn)證頁(yè)面的有效解耦——解耦是相對(duì)于專門寫一個(gè)LoginCheck類,并在各個(gè)Default頁(yè)面做驗(yàn)證(如LoginCheck.Check(context))而言,更利于修改與拓展。

(2)回顧MVC,可以依樣畫葫蘆像上述asp.net那樣,原來(lái)是:HomeController:Controller,切面插入后是:HomeController:LoginCheckController,LoginCheckController:Controller。除此之外,還能利用類/方法頭上的特性標(biāo)簽來(lái)做AOP。

在asp.net與MVC中的AOP體現(xiàn)還有許多做法,此處拋磚引玉、僅為比對(duì)ashx的AOP做思考:上述方法在ashx中能行得通嗎? 能!但要做些微調(diào):

(獨(dú)寫一個(gè)LoginCheck類,然后在每個(gè)需要驗(yàn)證的ashx.PR()中加上LoginCheck.Check(context)實(shí)在不是長(zhǎng)久之計(jì),故本文就不另說(shuō)了)

第一種嘗試:(沒(méi)錯(cuò),本文最后一次才嘗試成功,不過(guò)寫出嘗試過(guò)程也是為了將自己所走的彎路做下記錄,且希望能給讀者更多思考的提示,感謝堅(jiān)持讀完三種嘗試的朋友。)

利用HttpModule。類似url重寫那樣,url重寫不都是每次請(qǐng)求一來(lái)就做處理嗎,那Module應(yīng)該也能做登陸吧——兩者差異:普通的url重寫不涉及客戶端隔離、不考慮請(qǐng)求的資源,登錄驗(yàn)證要做客戶端隔離(cookie)、要考慮請(qǐng)求的資源(并不是所有資源都不給訪問(wèn),有的是游客級(jí)別就行的)。

對(duì)于要考慮請(qǐng)求資源的差異,如果惡心一點(diǎn),可以在代碼中寫死(可優(yōu)化成在webcofig、其他配置文件、數(shù)據(jù)庫(kù)存儲(chǔ))來(lái)做差異化處理——以正則表達(dá)式匹配請(qǐng)求地址,用來(lái)隔離需要驗(yàn)證登陸的請(qǐng)求與不需要驗(yàn)證的請(qǐng)求。

對(duì)于客戶端隔離,能否直接在Module中用session?首先要使HttpModule繼承自IReadonlySessionState/IRequiresSessionState接口(HttpHandler也是如此),以便在走管道的時(shí)候能被.net認(rèn)出來(lái)你這個(gè)Module想用session。注冊(cè)到BeginRequest事件。別忘了還要注冊(cè)到webconfig。一切就緒,調(diào)試,報(bào)錯(cuò)——Httpapplication中的Session屬性報(bào)錯(cuò),未將對(duì)象引用設(shè)置到對(duì)象實(shí)例。是不是注冊(cè)的事件錯(cuò)了?我查了一遍HttpApplication管道中的19個(gè)事件,最佳的切入點(diǎn)在第10-11個(gè)事件之間,也就是+=PostAcquireRequest,才能在獲取Session之后、在執(zhí)行ashx之前做登陸驗(yàn)證。

然而并沒(méi)有什么X用……依舊未將對(duì)象引用設(shè)置到對(duì)象實(shí)例。怎么還是沒(méi)有呢,奇了怪了。

又是一邊各種查,查到一句話說(shuō)得好:Module是應(yīng)用程序級(jí)的事兒,是過(guò)濾作用,而Session是頁(yè)面級(jí)的事兒,是要根據(jù)發(fā)來(lái)的請(qǐng)求做不同的處理,故在Module中用Session本就不是最佳方案。故放棄Module這條彎路。

第二種嘗試:

自定義繼承自IHttpHandler的ashx。原來(lái):Index:IHttpHandler,優(yōu)化后:Index:LoginCheckHandler,LoginCheckHandler:IHttpHandler。學(xué)的上述asp.net與mvc中的插入到繼承樹(shù)的方法。但調(diào)試結(jié)果是根本不走Index的ProcessRequest(),直接走完LoginCheckHandler.ProcessRequest()就返回了,客戶端就是空白一片。究其原因:實(shí)現(xiàn)IHttpHandler的一般處理程序(無(wú)論是Index,還是LoginCheckHandler),都只會(huì)執(zhí)行一次ProcessRequest()。

第三種嘗試:

在第二種的基礎(chǔ)上修改為:LoginCheckHandler中的ProcessRequest()改為virtual,并在Index子類中override重寫,并在Index.ProcessRequest()中調(diào)用base.ProcessRequest(context)。執(zhí)行的時(shí)候,程序會(huì)因?yàn)榭吹給verride而忽略父類的PR方法,而Index子類中的base.PR()又要求程序先走父類的PR方法,且結(jié)合Response.Redirect()的立即輸出特性(先Flush,在End),可以使得不滿足登錄驗(yàn)證條件的請(qǐng)求被擋在門外。小功告成!

麻煩的是,要修改子類為override,且在子類中存在base.PR()代碼(也只比簡(jiǎn)單粗暴的調(diào)用LoginCheck.Check(context)來(lái)驗(yàn)證減少了一些些耦合度),那么還有更好的AOP方法嗎?望各位大牛看官提點(diǎn)。


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 垫江县| 博客| 濮阳市| 谷城县| 平原县| 綦江县| 舞钢市| 许昌县| 淅川县| 宁河县| 玛曲县| 长武县| 五莲县| 清河县| 永寿县| 双流县| 陇川县| 玉屏| 南木林县| 页游| 万宁市| 榆树市| 库车县| 南郑县| 鄄城县| 原阳县| 汕头市| 霍城县| 武义县| 亚东县| 迁西县| 高雄市| 亳州市| 齐河县| 泰安市| 靖远县| 滦南县| 崇左市| 清苑县| 江安县| 旅游|