2008年6月10日
#
java在桌面軟件的失利,很大程度上取決與她運(yùn)行環(huán)境的陪著復(fù)雜度,還有隨時(shí)帶的一個(gè)龐大的jre環(huán)境。有時(shí)候我們并不需要jre中全部的類庫支持,我們只需要一些對我們項(xiàng)目有用的類庫,能否有一種通用的方法來抽取jre中的這些對我們有用的部分呢?google了下找到了幾篇文章介紹這個(gè)的。主要就是用verbose參數(shù)運(yùn)行jar,然后觀察java載入了多少java類,然后手動(dòng)或者寫個(gè)程序自動(dòng)的吧這些類打包和jvm打包為一個(gè)全新的jre環(huán)境。這種方法是可行的,但是卻是不通用,而且這種方法還有一個(gè)很大的弊端,當(dāng)有些類導(dǎo)入到我們項(xiàng)目中,但是在verbose的時(shí)候沒有用到(比如一些異常類),我們就不會(huì)導(dǎo)入,最終可能在發(fā)布運(yùn)行的時(shí)候就用到了,這樣可不妙。那么是否還有其他方法來瘦身jre環(huán)境呢,然后通過隨身附帶jre發(fā)布java程序?答案一定是有的,我已經(jīng)著手在開發(fā)這個(gè)應(yīng)用,我把她起名為BuildJre。
一,可行性分析(我們加上在win系統(tǒng)下):
java.exe是java運(yùn)行的一個(gè)入口程序,當(dāng)我們鍵入明了 java className的時(shí)候,首先啟動(dòng)都是這個(gè)程序,然后這個(gè)程序回去查找可用的jre庫,一般是先搜索本目錄和父親目錄,如果接著搜索環(huán)境變量,判斷是否為jre的依據(jù)是,首先java.exe查找懷疑目錄(比如父目錄)的bin下有沒有java.dll,如果找到,那么他就判定這個(gè)是jre目錄然后查找lib\i386下的jvm.cfg,最后更具這里面的參數(shù)去啟動(dòng)bin\client或者bin\server下的jvm.dll,這個(gè)才是真正的java虛擬機(jī),到這里,java.exe把控制權(quán)全部交給jvm,然后jvm就初始化,分配內(nèi)存等,運(yùn)行程序了,運(yùn)行程序期間導(dǎo)入的jdk包,都在jre目錄下的lib\rt.jar下。
說道這里,我們發(fā)現(xiàn),其實(shí)不用環(huán)境變量,只要有jre環(huán)境就能運(yùn)行java程序,這使得我們更加堅(jiān)定java程序也可以桌面化,因?yàn)樗彩强梢圆挥门渲媚敲绰闊┑沫h(huán)境變量直接運(yùn)行的。再回到瘦身來,剛才說了,jdk中所有的以來包全部位于jre\lib\rt.jar下,我們要廋的就是這個(gè),40多M的rt,我們通過類依賴抽取,對于一個(gè)普通的java程序,預(yù)計(jì)可以廋到小于10M,然后配合java.exe,java.dll,等幾個(gè)小的程序,預(yù)計(jì)目標(biāo)是平均廋身到15M以內(nèi)。
二,實(shí)施思路,用verbose方法不通用,不能在程序內(nèi)部抽取jre,而且還有可能遺漏依賴項(xiàng),不足提倡。我們架設(shè)有一個(gè)標(biāo)志的依賴說明庫,比如ArrayList這個(gè)類依賴的所有包都一一對應(yīng),那么我們?nèi)绻诔绦蚶飅mport ArrayList的話,那么我們可以迅速抽取相關(guān)的依賴包,然后在整個(gè)項(xiàng)目的所有import中去重復(fù),不就ok了?現(xiàn)在的問題在于:
1,不是所有的jdk包都需要import的,比如java.lang下就不用import
2,有些jdk內(nèi)部類在同一個(gè)包下不用寫import也一樣依賴。
3,計(jì)算jdk內(nèi)部依賴估計(jì)要很長實(shí)踐,因?yàn)槲募芏啵蕾嚭軓?fù)雜。
這些問題基本上都有解決方法,我已經(jīng)開始著手解決。
希望有一天,我們的java項(xiàng)目發(fā)布,只要帶上10M的小型環(huán)境,也不用配置環(huán)境變量,雙擊,ok。。哈哈
這年頭,webgame一個(gè)一個(gè)的冒出來,令我們應(yīng)接不暇,有人說webgame是一場新的泡沫,也有人說是互聯(lián)網(wǎng)新的機(jī)會(huì),有人說webgame是小公司叫板游戲行業(yè)的機(jī)會(huì),也有資深游戲人士說小公司做webgmae沒戲(盛大高管說,因?yàn)闆]有品牌和玩家資源)。不管怎么樣,webgame的興起已經(jīng)無法阻擋,包括我們公司,也是眾進(jìn)軍者中的一個(gè)。
webgame游戲商進(jìn)軍的主要兩個(gè)領(lǐng)域是 策略類游戲(往往以js,ajax技術(shù)和純通的web技術(shù)為基礎(chǔ)),和flash休閑社區(qū)游戲(以flash as3等技術(shù)為基礎(chǔ))。策略類游戲很早就有了,甚至比現(xiàn)在的門戶網(wǎng)站還早,只是那個(gè)時(shí)候沒有現(xiàn)在這么興起,時(shí)下具有代表性的主要是一些三國,戰(zhàn)爭類游戲,像盛大這種大游戲公司也介入不少,連baidu這種重來不碰游戲的公司都開始進(jìn)入了。而flash游戲相對來說比較少,比如夢境家園(純休閑娛樂,可以k歌),比如熱舞街(勁舞團(tuán)的web版),天空左岸 和 富豪街 等都不錯(cuò)。還有兩個(gè)我本人比較期待的還沒有公測的flash網(wǎng)游,一個(gè)是昆侖online,一個(gè)是和熱舞街,富豪街同一個(gè)公司的 口袋寵物。看他們的游戲截圖已經(jīng)非常類似傳統(tǒng)的大型游戲了。當(dāng)然,更期待的是我們在開發(fā)的flash網(wǎng)游,哈,內(nèi)容和名字現(xiàn)在還不能透露(小小透露下,我們的網(wǎng)游pk模式和現(xiàn)在任何一種網(wǎng)游的pk模式都不同,挺好玩的哦)。
。。。。不想說了。。想起來一本書上的一句話“真正有想法的人,已經(jīng)埋頭在實(shí)現(xiàn)自己的想法了,不會(huì)把自己的想法寫出來,在網(wǎng)上瞎扯淡的,都是沒事干的。”
游戲前臺(tái)主要以flash as3 為主,后臺(tái)用java,目前已經(jīng)初步做出一個(gè)原型,包括用戶行走,多用戶移動(dòng)同步,地圖場景與主程序分離,場景加載等等功能,地圖編輯器也已經(jīng)做的差不多了,計(jì)劃今天能完成,如果完成的話,就可以直接拿給美工去做地圖場景了,最終導(dǎo)出一個(gè)xml文件和相關(guān)的資源(圖片等),主程序通過這個(gè)xml文件加載場景。
這幾天主要的任務(wù)包括 客戶端UI統(tǒng)一界面設(shè)計(jì),需要做到高耦合,讓ui界面通過xml文件配置,服務(wù)器端數(shù)據(jù)庫的設(shè)計(jì),主程序調(diào)用外部swf模塊的企業(yè)級(jí)設(shè)計(jì),游戲任務(wù)腳本語言的初步設(shè)計(jì),等等。
以后開始正式要做網(wǎng)絡(luò)游戲啦,flash前臺(tái),java后臺(tái)。嘿嘿
還沒有整理出完整的api,里面有一個(gè)簡單的例子。
下載
IMVC對ajax有了很好的支持。主要體現(xiàn)在兩方面。
一 ajax View類型支持。Imvc的視同是通過一個(gè)View類來返回的,在action中通過return new View("/xxx.html")返回一個(gè)視圖,然后IMVC會(huì)通過Value中的數(shù)據(jù)渲染這個(gè)視圖。這是一般的流程,有些特殊的流程可以返回其他類型的View,我們先來看看View類的代碼:
public final class View implements Cloneable{
/**
* 屬性介紹:普通的view,通過模板轉(zhuǎn)換
*/
public static final int TYPE_VIEW=1;
/**
* 屬性介紹:轉(zhuǎn)向,不改變url
*/
public static final int TYPE_REDIRECT=2;
/**
* 屬性介紹:專心 ,改變url
*/
public static final int TYPE_REDIRECT2=3;
/**
* 屬性介紹:直接返回string,path的值
*/
public static final int TYPE_AJAX=4;
public static final int TYPE_EXCEPTION=5;
private String path;
private int type=1;
public View(String path){
this.path=path;
}
public View(String path,int type){
this.path=path;
this.type=type;
}
public View(Map map){
JSONObject jsono=JSONObject.fromObject(map);
path=jsono.toString();
type=TYPE_AJAX;
}
public View(List array){
JSONArray jsona=JSONArray.fromObject(array);
path=jsona.toString();
type=TYPE_AJAX;
}
public View(Object bean){
JSONObject jsono=JSONObject.fromObject(bean);
path=jsono.toString();
type=TYPE_AJAX;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public View clone(String path){
View v=cloneBase();
v.path=path;
return v;
}
public View clone(String path,int type){
View v=cloneBase();
v.path=path;
v.type=type;
return v;
}
public View clone(Map map){
View v=cloneBase();
JSONObject jsono=JSONObject.fromObject(map);
v.path=jsono.toString();
v.type=TYPE_AJAX;
return v;
}
public View clone(List array){
View v=cloneBase();
JSONArray jsona=JSONArray.fromObject(array);
v.path=jsona.toString();
v.type=TYPE_AJAX;
return v;
}
public View clone(Object bean){
View v=cloneBase();
JSONObject jsono=JSONObject.fromObject(bean);
v.path=jsono.toString();
v.type=TYPE_AJAX;
return v;
}
private View cloneBase(){
View v=null;
try {
v = (View) super.clone();
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return v;
}
}
我們主要關(guān)注以下幾個(gè)變量:
/**
* 屬性介紹:普通的view,通過模板轉(zhuǎn)換
*/
public static final int TYPE_VIEW=1;
/**
* 屬性介紹:轉(zhuǎn)向,不改變url
*/
public static final int TYPE_REDIRECT=2;
/**
* 屬性介紹:專心 ,改變url
*/
public static final int TYPE_REDIRECT2=3;
/**
* 屬性介紹:直接返回string,path的值
*/
public static final int TYPE_AJAX=4;
public static final int TYPE_EXCEPTION=5;
第一個(gè)是普通的View,通過ViewFactory.getView("/tt.html")這個(gè)方法返回的是普通的view,也就是可以通過IMVC渲染的視圖,而TYPE_REDIRECT則是返回一個(gè)跳轉(zhuǎn)view,可以跳轉(zhuǎn)到下一個(gè)action,TYPE_REDIRECT2也是一個(gè)跳轉(zhuǎn)view,不過是改變URL地址的view。TYPE_AJAX就是ajax試圖了,也是今天要講的主角了,至于最后一個(gè)TYPE_EXCEPTION,是把異常返回到客戶端瀏覽器到view,這里暫時(shí)不考慮。我們可以通過這樣一個(gè)構(gòu)造函數(shù)創(chuàng)造出ajax試圖,比如new View("這是ajax信息",View.TYPE_AJAX),或者通過ViewFactory.getView("這是ajax信息",View.TYPE_AJAX)也是一樣,不過用factory創(chuàng)建的對象是通過對象的clone創(chuàng)建的,能節(jié)省一定的性能開銷。當(dāng)返回的是一個(gè)ajax View的時(shí)候,信息就會(huì)直接返回,而不是通過渲染試圖,比如上面的就直接返回“這是ajax信息”給客戶端,如果這個(gè)action是由客戶端ajax請求的話,直接返回?cái)?shù)據(jù),是不是很方便呢?
接下來的ajx特性也許會(huì)讓你覺得更方便,比如以下代碼:
....action前面的內(nèi)如.....
User u=new User();
u.setAge(1);
u.setName("汪汪汪");
return ViewFactory.getView(u);
這樣的返回會(huì)直接在客戶端打印出 {"age":1,"name":"汪汪汪"};也就是IMVC把對象映射成立JSON(一種js對象的String形式),這個(gè)返回?cái)?shù)據(jù)在客戶端直接可以調(diào)用,比如data.name就直接調(diào)用出“汪汪汪”,是不是很方便?而且IMVC還支持把List,數(shù)組,Map,還有對象相互無限級(jí)嵌套返回成JSON數(shù)據(jù),這將大大增加AJAX開發(fā)的敏捷性和清晰性。
二 ajax Chain支持。我們假設(shè)有一個(gè)全部ajax的網(wǎng)頁,里面有幾個(gè)div中的數(shù)據(jù)都是通過ajax的方式向服務(wù)器請求的,那么每個(gè)div都會(huì)請求一次ajax action,這樣就導(dǎo)致了請求次數(shù)頻繁,資源的浪費(fèi),IMVC提供了一種ajaxChain的概念,可以通過一個(gè)url請求多個(gè)action,然后把數(shù)據(jù)自動(dòng)合并,比如下面的url
http://xxx.com/ajaxChain.x?id=|one,two?id=1|
這個(gè)url請請求了兩個(gè)action,然后把a(bǔ)ction數(shù)據(jù)合并,比如本來one.x返回的數(shù)據(jù)是{"name":"111"},而two返回的數(shù)據(jù)是 {"name":"2222"};則現(xiàn)在應(yīng)該返回的是{"one":{"name":"111"},"two?id=1",{"name":"2222"}},這樣,ajaxChain支持無數(shù)個(gè)action的連接。這樣以后可以將多個(gè)ajax合并為一個(gè)ajax,節(jié)省服務(wù)器資源。
好了,IMVC的ajax支持就講到這里。
這里所謂的非侵入性,是指一定程度上的耦合性,比如IMVC和待開發(fā)項(xiàng)目的耦合性,servlet容器和IMVC的耦合性,IMVC內(nèi)部處理的耦合性等等。
1.action非繼承。由于java語言不允許多重繼承,如果action被框架所迫需要繼承類的話,那么這個(gè)action的擴(kuò)展性將受到一定的限制,比如struts的繼承性就設(shè)計(jì)的比較失敗。
2.formBean的無侵入,IMVC中的formBean不需要繼承人和類,甚至不需要實(shí)現(xiàn)任何接口,完全的一個(gè)pojo實(shí)體就能勝任。
3.半servlet容器相關(guān)性,之所以說是半,因?yàn)镮MVC的容器無關(guān)性是間于struts和webwork之間的,struts的action接受 httpServletRequest和HttpServletResponse類實(shí)例作為參數(shù),另測試變得避免麻煩(雖然有工具可以輔助測試),這種 servlet完全相關(guān)性的設(shè)計(jì),讓action中獲取servlet數(shù)據(jù)變得容易,但是卻帶來了測試痛苦的后果。而反過來,webwork的 action中不需要傳入任何servlet相關(guān)部件,webwork通過一個(gè)轉(zhuǎn)回去把servlet中的數(shù)據(jù)拷貝到一個(gè)容器無關(guān)類。非常有利于測試,但是對于在action中獲取servlet數(shù)據(jù)變得不夠直觀(可以獲取的),而且,每次請求都拷貝數(shù)據(jù)也有礙于性能的提升。IMVC的設(shè)計(jì)則介于兩者之間。在IMVC的action中沒有傳入servlet任何部件,但是可以通過InstantContext獲得request和response(注意不是獲取request的數(shù)據(jù),而是request,不用花費(fèi)拷貝到性能)。但是,在攔截器設(shè)計(jì)中,傳入的卻是 servlet部件,因?yàn)閿r截器一般不會(huì)用于action單元測試,而且如果你對上面的action半容器無關(guān)性對于單元測試和獲取cookies的數(shù)據(jù)有疑惑,那么可以在攔截器中獲取你想要的cookie,然后傳入攔截器的另一個(gè)參數(shù)Value,action通過Value獲取cookie,這樣一來,明明半容器無關(guān)性的action測試,卻可以通過攔截器來實(shí)現(xiàn)完全容器無關(guān)的action,這樣一來,既滿足性能需求,又滿足測試需求。
4 攔截器的天下。和webwork一樣,IMVC中的攔截器是相當(dāng)重要的組成部分。可以配置全局?jǐn)r截器,路徑攔截器,ajax鏈(這個(gè)以后會(huì)詳解)攔截器,有趣的是,我們還有一個(gè)文件上傳攔截器,IMVC是集成文件上傳到,可以通過在action幾行代碼實(shí)現(xiàn)一個(gè)文件上傳,而一般我們要更具自己的特性來處理上傳完后的文件或者自定義的取名字,在或者做自己的縮略圖等等。IMVC設(shè)計(jì)了一個(gè)文件上傳攔截器,可以通過實(shí)例一個(gè)攔截器來實(shí)現(xiàn)這些功能,非常方便。
IMVC(InstantMVC簡稱)有幾個(gè)比較核心的接口,通過對這幾個(gè)接口的了解,可以更深入的了解IMVC到核心機(jī)制。
1.IAction接口
action是整個(gè)MVC的核心,如果了解struts或者webwork等MVC框架的朋友應(yīng)該
知道,action是一個(gè)用戶處理模塊,當(dāng)MVC容器接受到一個(gè)請求的時(shí)候,他會(huì)通過一定的方法獲得一個(gè)相應(yīng)的action類,然后執(zhí)行action類中
相應(yīng)的方法,最后返回一個(gè)視圖給客戶端,這就是最普通的mvc框架的流程。和其他框架的action類似,IMVC的action接口也有一個(gè)核心方法,
如下
public interface IAction {
/**
* 屬性介紹:驗(yàn)證器,放入Map value 的key
*/
public static final String MVC_STATIC_validation="__validation";
/**
* 屬性介紹:文件上傳 Map value中的key
*/
public static final String MVC_STATIC_createUpload="__createUpload";
/**
* 屬性介紹:這是編輯器
*/
public static final String MVC_STATIC_editor="__editor";
/**
* 方法說明:action的核心方法
&
nbsp; * <
span style="color: #808080;">@param object 如果是post方法,object就
是該action對應(yīng)的form,如果是get方法并且配置get方法沒有form
* 那么這里就是null,如果配置get方法也是有form的,這里也是form
*
&
nbsp; * <
span style="color: #808080;">@param value 一個(gè)map,在
action中添加內(nèi)容到view都往這里添加
* @return
* String
*/
public View execute(Object object,Value value);
}
前
面三個(gè)變量這里暫時(shí)不說,我們來關(guān)注最后一個(gè)方法,execute,任何action都需要實(shí)現(xiàn)這個(gè)接口,同時(shí)也就是說必須在action中有這個(gè)方法。
這個(gè)方法有兩個(gè)傳入變量Object和Value,第一個(gè)是想要的formBean,如果是get方法并且沒有配置get方法設(shè)置form,那么這個(gè)時(shí)候
就是null,如果是非get方法,而且還傳入了參數(shù),那么IMVC會(huì)自動(dòng)封裝相應(yīng)的form傳入到這個(gè)。第二個(gè)Value參數(shù),Value也是一個(gè)很核
心的接口。在IMVC中有ValueImpl類來實(shí)現(xiàn)。
Value 接口:
public interface Value {
public String getString(String key);
public String[] getArray(String key);
public void setObject(String key,Object value);
public Object getObject(String key);
}
ValueImpl 類:
public final class ValueImpl extends HashMap implements Map,Value,InstantValue{
//InstantValue
public void setArray(String key ,String[] arr){
super.put(key, arr);
}
//user Value
public String[] getArray(String key) {
return (String[])super.get(key);
}
public Object getObject(String key) {
return super.get(key);
}
public String getString(String key) {
Object o=super.get(key);
if(o==null){
return null;
}
if(o instanceof String[]){
return ((String[])o)[0];
}else{
return null;
}
}
public void setObject(String key, Object value) {
super.put(key, value);
}
//
以下實(shí)現(xiàn)clone。。提供性能
private ValueImpl cloneBase(){
ValueImpl vimpl=(ValueImpl) super.clone();
vimpl.clear();
return vimpl;
}
public static ValueImpl valueImpl=new ValueImpl();
public static ValueImpl cloneSelf(){
return valueImpl.cloneBase();
}
}
這個(gè)類也相當(dāng)簡單,我們看第一句:
public final class ValueImpl extends HashMap implements Map,Value,InstantValue
說
明這個(gè)類 繼承了HashMap,實(shí)現(xiàn)了Map,Value,InstantValue 三個(gè)接口。這三個(gè)接口其實(shí)就是三個(gè)權(quán)限版本,比如Value是用
戶操作權(quán)限,我們看到在action中傳入的是Value,但是在IMVC內(nèi)部操作的時(shí)候是把ValueImpl類轉(zhuǎn)換為InstantValue借口的
InstantValue 接口:
public interface InstantValue {
public void setArray(String key,String[] value);
}
這個(gè)幾口只有一個(gè)方法,這個(gè)方法是不會(huì)暴露給用戶的,是提供IMVC內(nèi)部設(shè)值用的。
下面還有一個(gè)攔截器接口
IInerceptor 攔截器接口:
public interface IInterceptor {
public void execute(HttpServletRequest request,HttpServletResponse response,Value value);
}
這個(gè)接口也相當(dāng)簡單,只有一個(gè)方法,傳入request和response參數(shù),同時(shí)還有一個(gè)Value參數(shù),這個(gè)Value上面已經(jīng)說過,是一個(gè)用戶操作的數(shù)據(jù)接口。
整個(gè)IMVC流程圖簡單來說如下:
首先,請求來了后,IMVC會(huì)創(chuàng)建一個(gè)ValueImp轉(zhuǎn)換為Value傳給前攔截器(如果沒有設(shè)
置就不用),攔截器操作完畢,在把這個(gè)ValueImp轉(zhuǎn)換為InstantValue接口傳給IMVC內(nèi)部操作,操作完畢接著把它轉(zhuǎn)化為Value接口
供用戶Action操作,最后執(zhí)行后攔截器,執(zhí)行完畢轉(zhuǎn)換為Map借口供模板引擎渲染試圖。
一個(gè)ValueImp要轉(zhuǎn)換為三種權(quán)限接口,所以他的實(shí)現(xiàn)就要implements 三個(gè)接口。
InstantMVC框架的基本功能基本上已經(jīng)完成,框架的接口設(shè)計(jì)(抽象層)也已經(jīng)完
工,以后修改大概不會(huì)有很大的接口變動(dòng),這里就貼出一個(gè)比較簡單的hello world程序。
&
nbsp; 首先導(dǎo)入InstantMVC(一下簡稱IMVC)的包,和相應(yīng)的依賴包(主要一些開源的包,比如
commons等)
然后再eclipse中新建一個(gè)web項(xiàng)目。。這個(gè)就不用說了吧。
然后在classPath下創(chuàng)建一個(gè)配置文件 mvcConfig.xml(名字任意起),內(nèi)如大概如下:
<baseConfig
actionPackageBasePath="test.action"
formPackageBasePath="test.form"
templateBasePath="/template"
resourceBasePath="/re"
urlPostfix=".x"
webUrl="yao.com:8282"
/>
<optionalConfig
isOpenActionCache="false"
isOpenValidationCache="false"
isGetMethodHasForm="false"
isOpenAjaxIdentityValidate="false"
fileUploadBasePath="/upload"
fileUploadMax="1974592963"
fileUploadFormat="pdf,jpg,gif"
printOutCharacter="UTF-8"
templateCharacter="UTF-8"
uploadCharacter="UTF-8"
isOpenFreemarkerCache="false"
/>
前面那個(gè) baseConfig是必須設(shè)置,后面optionalConfig是可選,可以不設(shè)置,IMVC有默認(rèn)設(shè)置。具體的配置如下:
必填:
actionPackageBasePath :基礎(chǔ)action包根目錄
formPackageBasePath:基礎(chǔ)form包根目錄
templateBasePath:基礎(chǔ)模板文件根目錄
resourceBasePath:InstantMVC自帶的資源文件目錄
urlPostfix:action請求后綴
webUrl:網(wǎng)站域名,比如yao.com主要用于ajaxView的權(quán)限檢測
可選:
isOpenActionCache="false" :是否開啟action的緩存,也就是是否設(shè)置action為單例
isOpenValidationCache="false":是否開啟檢驗(yàn)框架的緩存
isGetMethodHasForm="false":是否為get方法也設(shè)置form填充
isOpenAjaxIdentityValidate="false":是否開啟ajaxView的權(quán)限驗(yàn)證(不能跨域調(diào)用)
fileUploadBasePath="/upload":文件上傳根目錄,默認(rèn)是/upload
fileUploadMax="1974592963":上傳文件最大 ,可選,默認(rèn)1048576=1024×1024 b
fileUploadFormat="pdf,jpg,gif":上傳允許默認(rèn)的格式,可選,默認(rèn)為 pdf,jpg,gif,txt
printOutCharacter="UTF-8" : #可選,默認(rèn)為UTF-8,表示通過action直接打印到客戶端字符的編碼,一般用到ajax發(fā)生
templateCharacter="UTF-8" :#可選,默認(rèn)為UTF-8 ,表示通過模板方式顯示到客戶端的編碼,一般用到直接的請求
isOpenFreemarkerCache="false":#是否開啟freemarker模板緩存
最基礎(chǔ)的配置就這些了,后面那個(gè)可選其實(shí)也可以去掉。
然后我們在項(xiàng)目中新建立一個(gè)包
test.action.test
然后在包下新舊一個(gè)java類:Hello:
public class Hello implements IAction{
public View execute(Object object, Value value) {
&
nbsp;
value.setObject("<
/span>hello",
"hello,歡迎來到
InstantMVC的世界。。。
");
return ViewFactory.getView("/test.html");
}
}
ok,然后我們在 web項(xiàng)目根目錄下創(chuàng)建一個(gè)模板文件夾 template
在template下創(chuàng)建一個(gè)html文件 :test.html:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>test.html</title>
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="this is my page">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body>
${hello}<br />
</body>
</html>
很
簡單的Html,里面只有一個(gè)地方需要主意的就是 ${hello}這個(gè)東西,還記得上面Hello.java中的
value.setObject("
hello"
, "hello,歡迎來到InstantMVC的世界。。。");
嗎?其實(shí)這就是取出hello中的值。好一切配置都完成。額。好像還缺點(diǎn)什么,對,沒有配置web.xml,下面是基本的 配置:<
br />
<servlet>
<servlet-name>instantMVCController</servlet-name>
<servlet-class>yao.instant.mvc.sevlet.InstantFrontController</servlet-class>
<init-param>
<param-name>mvc_config</param-name>
<param-value>/mvcConfig.xml</param-value>
</init-param>
<init-param>
<param-name>single_config</param-name>
<param-value>/instant.single</param-value>
</init-param>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>instantMVCController</servlet-name>
<url-pattern>*.x</url-pattern>
</servlet-mapping>
其
中
yao.instant.mvc.sevlet.InstantFrontController
是IMVC的前端攔截器,有兩個(gè)參數(shù),第一個(gè)是剛剛寫的配置文件mvcConfig.xml相對于classPath的路徑,第二個(gè)是IMVC內(nèi)建的一個(gè)
對象管理容器的配置,這里可以先不寫(或則在classPath下新建一個(gè)空的文件Instant.single,內(nèi)容不用寫)。下面那個(gè)是url映射,
把.x的后綴映射到IMVC框架。好了,一切的搞定,下面就運(yùn)行
啟動(dòng)tomcat,在瀏覽器中輸入http://localhost:8080/test/hello.x 就會(huì)看到一下結(jié)果:

看,一個(gè)簡單的helloworld程序就完成了。下面我們回顧一下這個(gè)過程是怎么進(jìn)行的。
首先,我們先回顧下我們的配置文件中有一個(gè)配置選項(xiàng):
actionPackageBasePath="test.action"
這
個(gè)選項(xiàng)表示IMVC將會(huì)首先通過這個(gè)路徑去尋找相應(yīng)的匹配url的action,比如我們上面的url是:/test/hello.x 那么IMVC會(huì)首
先尋找 test.action.test包下的Hello類,如果沒有存在,會(huì)報(bào)異常,如果存在,就執(zhí)行Hello類的execute方法。在
execute方法最后返回了一個(gè)View,其中一個(gè)參數(shù)是模板位置,比如本例中是View("/test.html"),那么這個(gè)文件在哪呢?IMVC
又是怎么去尋找的呢,再回來看配置文件,其中的一個(gè)參數(shù):
templateBasePath="/template"
這
個(gè)參數(shù)的意識(shí)就是吧web目錄下的template作為主要的模板文件的根目錄,此例中/test.html就是尋找的
/template/test.html文件,然后渲染模板,會(huì)把其中的${hello}參數(shù)渲染為 action中通過value這個(gè)對象設(shè)置的值,比
如本例中是:value.setObject("hello", "hello,歡迎來到InstantMVC的世界。。。");<
br />
至此,一個(gè)簡單的get方法的IMVC流程結(jié)束。
這里其他的功能沒有說道,比如View中有一種專門的返回ajax的View類型,比如還有攔截器,比如還有form填充和參數(shù)獲取等都沒說,下次再詳細(xì)說明。
ps:InstantMVC目前還在內(nèi)部修改完善,還不能提供版本下載。
InstantMVC是我最近開發(fā)的一個(gè)j2ee輕量級(jí)MVC框架,寫這個(gè)框架前剛好做完一個(gè)webwork+spring+InstantORM的項(xiàng)
目,對于開發(fā)過程中的一些不舒服的地方,就像要改進(jìn)著試試寫一個(gè)框架,于是就開始寫了,寫這個(gè)框架的沖動(dòng)主要有以下幾點(diǎn):
1.討厭的action配置,無論是strtus還是webwork,都有一大堆的action配置文件,strtus加上bean就更多,如果
webwork配合spring,那么一個(gè)action就要配置一個(gè)spring Bean,一個(gè)webwork
action映射,隨著項(xiàng)目的擴(kuò)大,后來實(shí)在是讓人有些受不了,再則,隨著項(xiàng)目的擴(kuò)大,action數(shù)目的增加,每次改動(dòng)重新啟動(dòng)服務(wù)器的時(shí)間浪費(fèi)就更
大,所以項(xiàng)目越來越大,感覺越來越痛苦,雖然配置型的action,對于項(xiàng)目的移植有一定的好處,但是一般的項(xiàng)目是很少回過頭去修改action映射,就
算修改,在java文件中修改也是可以接受的。
2.關(guān)于驗(yàn)證,struts和webwork的驗(yàn)證都是基于xml配置的,就我個(gè)人而言,是比較討厭xml配置這個(gè)東西的,所以我一直用不慣他們的驗(yàn)證框
架,而且一旦用到驗(yàn)證框架,必須用到UI組件,在webwork中用freemarker作為模板的時(shí)候,UI組件是比較費(fèi)資源的(可能成為潛在的性能瓶
頸),如果有一個(gè)不用UI組件而且外面封裝客戶端和服務(wù)器端驗(yàn)證的MVC框架,我想會(huì)比較爽。
3.關(guān)于view,我比較喜歡springMVC中的那種直接在action中return的形式,webwork和struts的配置方式我也很不喜歡。
4.應(yīng)該是性能考慮,webwork的action非單利可能導(dǎo)致性能問題(雖然沒有被充分證明),struts2也走了這條路。
基于這些考慮,我打算開發(fā)自己的MVC框架,而且現(xiàn)在已經(jīng)小有所成,基本功能已經(jīng)完成,下面簡單講下InstantMVC框架的主要特征
1.零配置,零配置不是說沒有配置,而是說不用配置action和result view,整個(gè)mvc框架只有一個(gè)整體的配置文件,所有映射關(guān)系都是通過默認(rèn)規(guī)則來建立的。
2.類似action/form
形式,這里說是類似,因?yàn)镮nstantMVC可以配置讓get方法是否支持form,也就是get方法可以不用form,直接通過一個(gè)Map獲得請求參
數(shù),也可以配置get填充form形式,InstantMVC的action可以配置為是單利或者非單利,不過一般在action中不推薦存放非線程安全
的變量,所以建議配置為單利。
3.action中兩個(gè)參數(shù)一個(gè)是Form的Object,一個(gè)是Map,容易單元測試,不需要引入Servlet部件,但是對于一些session等操
作可以通過InstantContext獲得HttpSerlvetrequest操作,可以說InstantMVC對于容器無關(guān)性是介于webwork
和struts之間的。
4.最簡單的驗(yàn)證集成方式,所有驗(yàn)證代碼寫到action中,在view中不用配置UI組件,支持客戶端和服務(wù)器端雙重驗(yàn)證,可以單獨(dú)開啟一方關(guān)閉一方。
5.ajax
View的集成,這里的集成不像dwr那樣完全集成,而是一種半集成方式,客戶端用到ajax框架還是需要用戶自己選擇,這樣提供了很大的靈活性。
InstantMVC的View有好幾種形式,比如挑戰(zhàn)到另一個(gè)action的view,直接返回的view,ajax的view等,
InstantMVC的ajax是和普通的action一樣的,只不過返回一個(gè)ajax的View就成了ajax了。ajax的view可以返回任何對象
的json。在客戶端很方便的獲得,這一點(diǎn)有點(diǎn)像dwr的返回結(jié)果,不過dwr需要配置,InstantMVC不用。而且我們可以設(shè)置開啟ajax的安全
驗(yàn)證,開啟后將不允許其他域方法ajax的action。
6.支持AOP攔截器,模仿webwork那樣,可以自定義攔截器。
7.集成了上傳組件,和驗(yàn)證一樣,可以在action中配置。
大概就是這些特性,這些特性都很讓我著迷。現(xiàn)在這些特性基本上都能工作,不過穩(wěn)定性兼容性方面還有待提升,同時(shí)還需要大量的性能方面考慮(雖然現(xiàn)在的性能比其他MVC只會(huì)高不會(huì)低)。今天剛把blog搬到這里來,以后這里會(huì)主要寫關(guān)于我的框架的一些問題等。