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/NewTopic和logic.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ā)方式。