where the amazing happens

          一個(gè)WEB框架功能的分析:用編碼規(guī)定代替配置文件

          Ruby on Rails有個(gè)設(shè)計(jì)思想是:用編碼規(guī)定代替繁瑣的配置文件。jvm平臺(tái)已經(jīng)有一些類(lèi)似ror的實(shí)現(xiàn),比如
          grails:http://docs.codehaus.org/display/GRAILS/2006/03/29/Groovy+on+Rails+(Grails)+0.1+Released

          雖然由于java自身的局限,它很難做出像ruby或者groovy那樣動(dòng)態(tài)語(yǔ)言那樣隨心所欲的動(dòng)作,但是利用它的運(yùn)行時(shí)反射、動(dòng)態(tài)代理等特性來(lái)盡可能體現(xiàn)“用編碼規(guī)定代替繁瑣的配置文件”這一思想。下面就轉(zhuǎn)入正題。

          ServletAPI對(duì)HTTP協(xié)議進(jìn)行了封裝,通過(guò)配置Web.xml來(lái)把不同的請(qǐng)求轉(zhuǎn)發(fā)給不同的servlet來(lái)處理。Web框架則用一個(gè)ActionServlet,根據(jù)自己的對(duì)Action的定義來(lái)轉(zhuǎn)發(fā)請(qǐng)求。
          拋開(kāi)那些繁瑣的配置文件,設(shè)想一下這樣一種方法:

          1.Web動(dòng)作的處理和響應(yīng)

          假設(shè)這樣一個(gè)POST請(qǐng)求:

          < form? action ="logic/group/NewTopic" ?method ="post" >

          Web動(dòng)作實(shí)現(xiàn)Bean:

          org.qqsns.web.logic.group.NewTopic

          注意后面的logic/group/NewTopiclogic.group.NewTopic, 動(dòng)作類(lèi)和Web動(dòng)作是通過(guò)請(qǐng)求路徑和包名相互關(guān)聯(lián)。
          這樣,對(duì)Web動(dòng)作的響應(yīng)就依賴(lài)于編譯期的代碼的組織結(jié)構(gòu)而不是執(zhí)行期的配置文件。這樣的好處是避免了維護(hù)繁瑣的配置文件,特別是在沒(méi)有IDE支持的情況下。

          org.qqsns.web.logic.group.NewTopic類(lèi)是一個(gè)實(shí)現(xiàn)net.wff.servlet.WebAction接口的POJO,下面是NewTopic中execute的方法片段:???

          // Only?method?must?be?implemented?for?interface?net.wff.servlet.WebAction
          ? public ?String?execute(HttpServletRequest?request,?HttpServletResponse?response)
          ?
          throws ?ServletException,?IOException {
          ??
          ??
          // return?"redirect?/success.html";?? // 請(qǐng)求重定向
          ?? return ? " /success.jsp " ;?????????????? // 請(qǐng)求轉(zhuǎn)發(fā)
          }

          ?execute方法的返回值手動(dòng)指定了一個(gè)轉(zhuǎn)發(fā)或重定向的路徑。

          2.輸入驗(yàn)證

          普通的Web框架都帶數(shù)據(jù)輸入驗(yàn)證功能,一般復(fù)雜程度和功能強(qiáng)大與否成正比。
          這里簡(jiǎn)單地要求從setter方法里拋出一個(gè)包含驗(yàn)證信息的異常,以此來(lái)實(shí)現(xiàn)輸入異常處理。
          ??????
          普通setter方法

          public ? void ?setName(String?name) {?
          ??
          this .name? = ?name;
          }

          添加輸入驗(yàn)證后的setter方法

          public ? void ?setName(String?name)? throws ?InputException {????
          ?
          if (name.length() < 3 )
          ????
          throw ? new ?InputException( " Topic?name?must?has?a?length?greater?than?3 " );?
          ??
          this .name? = ?name;
          }


          WaterFallServlet是如何處理驗(yàn)證信息的:

          WebAction?wa? = ?
          ????(WebAction)Class.forName(classPath).newInstance();
          ??????????
          // procces?forwarding
          ?????????? try ? {
          ????ActionHelper.setProperties(request,wa);
          ???}
          ? catch ?(InputException?e)? {
          ????
          // return?to?input?view
          ????
          // header:referer
          ????String?rtn? = ?request.getHeader( " referer " );
          ????
          // clear?old?errors
          ???? if (rtn.indexOf( " ? " ) != 1 ) {
          ?????rtn?
          = ?rtn.substring( 0 ,rtn.indexOf( " ? " ));
          ????}

          ????rtn
          = rtn + " ?error= " + URLEncoder.encode(e.getMessage(), " UTF-8 " );
          ????response.sendRedirect(rtn);
          ????
          return ;
          ???}

          這樣驗(yàn)證信息通過(guò)請(qǐng)求參數(shù)傳回到輸入頁(yè)面.

          3.數(shù)據(jù)綁定

          假設(shè)有這樣的html輸入:?

          < input? type ="text" ?name ="name" />
          < input? type ="text" ?name ="number" />
          < input? type ="text" ?name ="price" />

          ?下面是NewTopic中execute的方法全部:???

          public ?String?execute(HttpServletRequest?request,?HttpServletResponse?response)
          ?
          throws ?ServletException,?IOException {
          ??System.out.println(getName());
          ??System.out.println(getNumber());
          ??System.out.println(getPrice());
          ??System.out.println(getLength());
          ??
          return ? " /success.html " ;
          }

          自動(dòng)從request注入parameter,這也許是很多人喜歡Struts DynamicActionForm的原因之一。
          不過(guò)這里實(shí)現(xiàn)更類(lèi)似多了類(lèi)型轉(zhuǎn)換的<jsp:setProperty name="bean" property="*"/>
          因?yàn)镹ame的類(lèi)型是String,Number的類(lèi)型是Integer,Price的類(lèi)型是float,length的類(lèi)型是double.至于其他復(fù)雜的類(lèi)型,也許jsf的轉(zhuǎn)換器是個(gè)更好的主意。
          這樣就初步解決了數(shù)據(jù)的輸入綁定和驗(yàn)證。余下的就是業(yè)務(wù)邏輯的問(wèn)題。WaterfallWebFramework源代碼:
          http://www.aygfsteel.com/Files/zqc/WaterfallWebFramework.rar?(只有一個(gè)配置文件,其中只有1行配置信息!)

          以上就是框架的主要功能。用編碼規(guī)定代替配置文件,也許這會(huì)是一種更加高效率的開(kāi)發(fā)方式。

          posted on 2006-05-17 13:12 where the amazing happens 閱讀(2124) 評(píng)論(3)  編輯  收藏 所屬分類(lèi): 自制土器

          評(píng)論

          # re: 一個(gè)WEB框架功能的分析:用編碼規(guī)定代替配置文件 2006-05-17 18:28 原創(chuàng)專(zhuān)欄 開(kāi)源學(xué)習(xí)

          http://forum.javaeye.com/viewtopic.php?t=10894

          可以看看這個(gè)討論。
          大規(guī)模的項(xiàng)目這種方法還是不行滴。

            回復(fù)  更多評(píng)論   

          # re: 一個(gè)WEB框架功能的分析:用編碼規(guī)定代替配置文件 2006-05-17 19:44 鳥(niǎo)不生蛋蛋的地方

          去看仔細(xì)了下,覺(jué)得比較重要的是下面幾個(gè)問(wèn)題:
          1.url mapping pattern的問(wèn)題,就對(duì)一些特殊url的處理
          2.action對(duì)象重用的問(wèn)題.
          3.頁(yè)面rendering的問(wèn)題
          還沒(méi)使用jsp以外的腳本,所以不知道第3點(diǎn)怎么樣.
          1和2應(yīng)該算是url->class映射的副作用,傳統(tǒng)的通過(guò)mapping文件的定義可以使action對(duì)象從請(qǐng)求過(guò)程中脫離出來(lái),達(dá)到可重用性.這一點(diǎn)url->class映射也許就做不到.畢竟依賴(lài)的都是編譯期的代碼,如果抽出來(lái),那就又是配置文件了.

          對(duì),沒(méi)錯(cuò).大型項(xiàng)目上百個(gè)action,比起結(jié)構(gòu)整潔或者配上IDE支持的配置文件,這樣的方法確實(shí)不好管理.雖然它方便了開(kāi)發(fā)者.  回復(fù)  更多評(píng)論   

          # re: 一個(gè)WEB框架功能的分析:用編碼規(guī)定代替配置文件 2006-05-17 20:43 mixteluoyi

          對(duì)于維護(hù)和擴(kuò)展開(kāi)發(fā)不利。
          前兩批的開(kāi)發(fā)人員走后,這種很多靠默認(rèn)行為固定的邏輯誰(shuí)明白。
          做軟件最重要的是維護(hù)性好,換過(guò)幾批人以后,仍然結(jié)構(gòu)清晰,后來(lái)的人能快速上手  回復(fù)  更多評(píng)論   

          公告

          點(diǎn)擊這里給我發(fā)消息

          導(dǎo)航

          <2025年7月>
          293012345
          6789101112
          13141516171819
          20212223242526
          272829303112
          3456789

          統(tǒng)計(jì)

          常用鏈接

          留言簿(3)

          隨筆分類(lèi)(18)

          隨筆檔案(17)

          文章分類(lèi)

          相冊(cè)

          其他我的blog

          技術(shù)Blog

          最新隨筆

          搜索

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 潼南县| 应城市| 葫芦岛市| 英吉沙县| 旺苍县| 佛学| 夏邑县| 防城港市| 陈巴尔虎旗| 黄山市| 西华县| 竹北市| 寿光市| 安吉县| 紫阳县| 比如县| 岗巴县| 衡山县| 子洲县| 常宁市| 京山县| 根河市| 呼伦贝尔市| 黑山县| 渝北区| 宿州市| 通州区| 南阳市| 包头市| 南雄市| 额济纳旗| 扶风县| 新巴尔虎右旗| 石河子市| 海盐县| 招远市| 永德县| 托克逊县| 塔河县| 林口县| 简阳市|