我的評論
re: HtmlParser疑似Bug stone2083 2011-04-09 19:31
@penngo
收到,有空的時候,我去學習下jsoup。
收到,有空的時候,我去學習下jsoup。
re: 語言雜談(shell/python/java) stone2083 2010-11-16 11:44
@問題
每種語言都是自身的特點(優勢和弊端),以及背后的設計理念。我們要用合適的技術解決對應的需求,使用正確的思想去使用該技術。
(在我周圍遇到有太多的同學,面對10來個頁面的需求,也要使用java,還要使用mvc,orm framework,三,四層架構,之后再來抱怨java的復雜。)
這促使我站在自己的理解上,總結了三門具有代表性的語言特點和其適用的場景(還少一種函數式編程語言)。
之所以發到blog:
1.在目前能力范圍下,總結對這些事物的理解
2.找到志同道合的人員,可以一起交流
就事論事的討論,才能讓你,我,彼此都得到成長;
沒有任何理論說明的,純屬發自內心的主觀性批判語言,相信對我的幫助幾乎沒有。
不妨說說沒有毛用的理由,這有助我們進一步討論。
每種語言都是自身的特點(優勢和弊端),以及背后的設計理念。我們要用合適的技術解決對應的需求,使用正確的思想去使用該技術。
(在我周圍遇到有太多的同學,面對10來個頁面的需求,也要使用java,還要使用mvc,orm framework,三,四層架構,之后再來抱怨java的復雜。)
這促使我站在自己的理解上,總結了三門具有代表性的語言特點和其適用的場景(還少一種函數式編程語言)。
之所以發到blog:
1.在目前能力范圍下,總結對這些事物的理解
2.找到志同道合的人員,可以一起交流
就事論事的討論,才能讓你,我,彼此都得到成長;
沒有任何理論說明的,純屬發自內心的主觀性批判語言,相信對我的幫助幾乎沒有。
不妨說說沒有毛用的理由,這有助我們進一步討論。
re: CGlib簡單介紹 stone2083 2010-11-03 13:31
@pyzhu
得到同事指點,還有一種更好的方法:
system.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "指定輸出目錄");
詳見:http://www.javaeye.com/topic/799827
得到同事指點,還有一種更好的方法:
system.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "指定輸出目錄");
詳見:http://www.javaeye.com/topic/799827
re: 爬取交通違章信息的腳本 stone2083 2010-10-29 18:46
@wuzhengju
唉,我這個土人。。。
之前思維一直停留在如何破解驗證碼上了。直到寫完這個東東,在寫腳本的時候:
curl -A "$AGENT" -e $TRAFFIC_URL -b "ASP.NET_SessionId=$SESSION_ID;isLoginedWeb=T;ImageV=$code" -d "$QUERY_PARAM" "$TRAFFIC_URL" -o $TMP_CONTENT_BASE
才發現在cookie中已經存在這個ImageV了。
不過為時已晚,米已城粥。。。 :)
================================================
好久不見了,最近工作還順利嗎?
唉,我這個土人。。。
之前思維一直停留在如何破解驗證碼上了。直到寫完這個東東,在寫腳本的時候:
curl -A "$AGENT" -e $TRAFFIC_URL -b "ASP.NET_SessionId=$SESSION_ID;isLoginedWeb=T;ImageV=$code" -d "$QUERY_PARAM" "$TRAFFIC_URL" -o $TMP_CONTENT_BASE
才發現在cookie中已經存在這個ImageV了。
不過為時已晚,米已城粥。。。 :)
================================================
好久不見了,最近工作還順利嗎?
re: 爬取交通違章信息的腳本 stone2083 2010-10-15 18:18
@阿風
其實是周末下午沒事情干,弄著玩的。
之前沒有涉及過圖片相關的,趁機也稍微學習下。 :)
其實是周末下午沒事情干,弄著玩的。
之前沒有涉及過圖片相關的,趁機也稍微學習下。 :)
re: CGlib簡單介紹 stone2083 2010-10-09 09:27
@pyzhu
修改源碼也是一種方法 :)
我是在debug的時候,Variables窗體中,編寫java代碼,拿到class變量信息做自己的處理
修改源碼也是一種方法 :)
我是在debug的時候,Variables窗體中,編寫java代碼,拿到class變量信息做自己的處理
re: CGlib簡單介紹 stone2083 2010-09-29 09:18
@pyzhu
用了比較猥瑣的辦法,
debug,將動態生成class的字節碼 輸入到文件中,然后反編譯得到的.
用了比較猥瑣的辦法,
debug,將動態生成class的字節碼 輸入到文件中,然后反編譯得到的.
re: java反射效率 stone2083 2010-09-16 12:57
@Unmi
我上面的例子,僅僅是想說明反射調用方法的開銷(不局限在get/set上).
如果是對java bean getters/setters的操作,可以考慮使用cglib的BulkBean類.
cglib下的fastclass和fastmethod,確實有一定的優勢,但是優先并不明顯(在jdk1.6上)
我上面的例子,僅僅是想說明反射調用方法的開銷(不局限在get/set上).
如果是對java bean getters/setters的操作,可以考慮使用cglib的BulkBean類.
cglib下的fastclass和fastmethod,確實有一定的優勢,但是優先并不明顯(在jdk1.6上)
re: java反射效率 stone2083 2010-09-15 20:21
@王衛華
你是指spring aop中cglib proxy的實現?
你是指spring aop中cglib proxy的實現?
re: IBatis下DAO單元測試另類思路 stone2083 2010-08-13 11:54
@kylin
明白你們這邊的情況了.
Service層的測試相對還是容易的,我們這邊也有一套測試框架(類似DDSteps,也是對一些業界測試工具的整合加改進).并且對Service依賴的外部環境,都做了隔離,主要包括:
1.Mock Dao impl
2.Mock Core Service impl (外部核心業務服務)
3.Mock Search Engine impl
4.Mock Cach impl
....
測試重心,主要集中在Service內部邏輯的測試上.
而公司使用的測試框架很好的支持了這些需求.
難點還在DAO的測試上.
數據準備的復雜度,取決于表設計的復雜度和sql的復雜度.尤其在ibatis支持dynamic語句下,要準備覆蓋測試sql語句的數據.挺繁瑣的.
這并不是說使用excel,還是wiki等的問題.而是數據內容的準備上.
每個測試數據的準備,都是為了一個特定的testcase設計目的的.而當字段多,并且表設計相對復雜的時候,這個準備意圖,挺難被傳承下去的.
隨著項目,小需求的進行,我們這邊,差不多幾十人,都有可能修改同一個sql代碼 :(
明白你們這邊的情況了.
Service層的測試相對還是容易的,我們這邊也有一套測試框架(類似DDSteps,也是對一些業界測試工具的整合加改進).并且對Service依賴的外部環境,都做了隔離,主要包括:
1.Mock Dao impl
2.Mock Core Service impl (外部核心業務服務)
3.Mock Search Engine impl
4.Mock Cach impl
....
測試重心,主要集中在Service內部邏輯的測試上.
而公司使用的測試框架很好的支持了這些需求.
難點還在DAO的測試上.
數據準備的復雜度,取決于表設計的復雜度和sql的復雜度.尤其在ibatis支持dynamic語句下,要準備覆蓋測試sql語句的數據.挺繁瑣的.
這并不是說使用excel,還是wiki等的問題.而是數據內容的準備上.
每個測試數據的準備,都是為了一個特定的testcase設計目的的.而當字段多,并且表設計相對復雜的時候,這個準備意圖,挺難被傳承下去的.
隨著項目,小需求的進行,我們這邊,差不多幾十人,都有可能修改同一個sql代碼 :(
re: Java Exception性能問題 stone2083 2010-08-13 09:08
@啊寶
控制流程用Exception(try..catch)也好,還是ResultModel(if..else)也罷.只是不同的設計理念而已.
都可以,都對
至于提到異常煩,如果是為性能問題.我以為大可不必.
1.異常的性能沒那么差.在上面的測試中,一個異常的產生,0.02ms而已
2.大多數的應用,對性能要求并非很高
3.引起性能瓶頸的,往往是不合理的設計,錯誤的使用同步等業務代碼產生的.
4.實在不行,就是用改進后的異常
如果再不行,那么只好拋棄業務異常吧
如果再不行,那么只好拋棄java改用c等語言吧.
選擇一種語言也好,選擇一種設計也罷,只是為了更好的處理需求而已.
至于上文,只是為了描述異常的本質.在了解原理的基礎上,讓業務異常的使用不出現性能的浪費而已.
絕不是表明,異常性能真得對系統產生了影響 :)
控制流程用Exception(try..catch)也好,還是ResultModel(if..else)也罷.只是不同的設計理念而已.
都可以,都對
至于提到異常煩,如果是為性能問題.我以為大可不必.
1.異常的性能沒那么差.在上面的測試中,一個異常的產生,0.02ms而已
2.大多數的應用,對性能要求并非很高
3.引起性能瓶頸的,往往是不合理的設計,錯誤的使用同步等業務代碼產生的.
4.實在不行,就是用改進后的異常
如果再不行,那么只好拋棄業務異常吧
如果再不行,那么只好拋棄java改用c等語言吧.
選擇一種語言也好,選擇一種設計也罷,只是為了更好的處理需求而已.
至于上文,只是為了描述異常的本質.在了解原理的基礎上,讓業務異常的使用不出現性能的浪費而已.
絕不是表明,異常性能真得對系統產生了影響 :)
re: IBatis下DAO單元測試另類思路 stone2083 2010-08-13 08:46
提供這個思路,并不是說替代之前的方案,更不是對傳統測試方案的否定. 僅僅是為了多一種選擇.
re: IBatis下DAO單元測試另類思路 stone2083 2010-08-13 08:31
@藍劍
DAO業務邏輯不復雜只指:在DAO方法中,不會有復雜的分支流程,往往只會調用一條SqlID執行sql.但是這不意味sql不復雜.
打個比方,報表的生成,業務邏輯非常簡單(根據什么樣的條件,能看到什么樣的數據),但是sql絕對的復雜. :)
dao方法,也只會有一句 getSqlMapClientTemplate.queryForList("....",param); // 簡單吧 :)
數據準備的工作量低嗎?維護成本低嗎?至少在我實踐的項目中,沒有像sample那樣低(dbfit,dbunit,dbutil等sample,都是單表的說明,單表字段往往少于5個字段). 實際情況是:
1.字段多
2.表關聯 (尤其在tree結構的表,父節點的依賴,光是這樣的準備,都非常容易寫錯)
3.對于查詢的語句(尤其是分頁),需要根據動態條件,準備好需要的數據
4.數據準備意圖需要被傳承
在我看來,并且實踐過來,挺不容易的.
sql的assert,只要根據條件參數的不同,做不同預計sql的assert,成本絕對比結果數據校驗,來得低.
至于最后一點.
是用ibatis,還是jdbc;不是單元測試成本(方案)決定的;而是需求,應用,架構設計,部門崗位情況等決定的.
我們有專業的dba,對所有sql要做review,總不能給一堆jdbc的文件給他們吧.ibatis就挺好了.
再說了,對于ibatis下dao編碼,錯誤率是sql寫錯的高呢?還是row mapper錯誤高呢?所以如果因為這點,來否決全部,挺不公平的.
DAO業務邏輯不復雜只指:在DAO方法中,不會有復雜的分支流程,往往只會調用一條SqlID執行sql.但是這不意味sql不復雜.
打個比方,報表的生成,業務邏輯非常簡單(根據什么樣的條件,能看到什么樣的數據),但是sql絕對的復雜. :)
dao方法,也只會有一句 getSqlMapClientTemplate.queryForList("....",param); // 簡單吧 :)
數據準備的工作量低嗎?維護成本低嗎?至少在我實踐的項目中,沒有像sample那樣低(dbfit,dbunit,dbutil等sample,都是單表的說明,單表字段往往少于5個字段). 實際情況是:
1.字段多
2.表關聯 (尤其在tree結構的表,父節點的依賴,光是這樣的準備,都非常容易寫錯)
3.對于查詢的語句(尤其是分頁),需要根據動態條件,準備好需要的數據
4.數據準備意圖需要被傳承
在我看來,并且實踐過來,挺不容易的.
sql的assert,只要根據條件參數的不同,做不同預計sql的assert,成本絕對比結果數據校驗,來得低.
至于最后一點.
是用ibatis,還是jdbc;不是單元測試成本(方案)決定的;而是需求,應用,架構設計,部門崗位情況等決定的.
我們有專業的dba,對所有sql要做review,總不能給一堆jdbc的文件給他們吧.ibatis就挺好了.
再說了,對于ibatis下dao編碼,錯誤率是sql寫錯的高呢?還是row mapper錯誤高呢?所以如果因為這點,來否決全部,挺不公平的.
re: IBatis下DAO單元測試另類思路 stone2083 2010-08-12 17:02
@sgz
大多數時候,想法是被現實逼出來的 :)
在我們這邊,dao幾乎沒有復雜的業務邏輯,僅僅是對SqlMapClientTemplate的使用而已.
但是在針對DB的單元測試時,代價又是如此的巨大(主要還是在數據準備上).
成本,收益比,不劃算,開發們抱怨多.
分析現狀和開發們實際需求(寫dao,主要是擔心sql寫錯)后,才萌生了這個想法.
大多數時候,想法是被現實逼出來的 :)
在我們這邊,dao幾乎沒有復雜的業務邏輯,僅僅是對SqlMapClientTemplate的使用而已.
但是在針對DB的單元測試時,代價又是如此的巨大(主要還是在數據準備上).
成本,收益比,不劃算,開發們抱怨多.
分析現狀和開發們實際需求(寫dao,主要是擔心sql寫錯)后,才萌生了這個想法.
re: IBatis下DAO單元測試另類思路 stone2083 2010-08-12 16:58
@kylin
簡單地看了下ddsteps,它是一套集成測試工具.主要包括:
dbunit,selenium,mock web(http) server,easymock和spring.
它對DB的支持,也是采用傳統的方式.(沒猜錯的話,是使用了,最多封裝了dbunit)
并不能解決我現在遇到的問題:
1.背負數據庫環境
2.準備測試數據
3.準備預計結果數據
這些麻煩的工作量.
而且在公司中,也已經有一套測試框架,我們要做的,并不是選擇框架(替換框架),而是選擇一種合適敏捷單元測試的思路和方案. 讓框架支持敏捷的方案而已.
簡單地看了下ddsteps,它是一套集成測試工具.主要包括:
dbunit,selenium,mock web(http) server,easymock和spring.
它對DB的支持,也是采用傳統的方式.(沒猜錯的話,是使用了,最多封裝了dbunit)
并不能解決我現在遇到的問題:
1.背負數據庫環境
2.準備測試數據
3.準備預計結果數據
這些麻煩的工作量.
而且在公司中,也已經有一套測試框架,我們要做的,并不是選擇框架(替換框架),而是選擇一種合適敏捷單元測試的思路和方案. 讓框架支持敏捷的方案而已.
re: 誰能幫忙解釋一下為什么這個程序會死鎖? stone2083 2010-08-04 21:30
re: 誰能幫忙解釋一下為什么這個程序會死鎖? stone2083 2010-08-04 20:07
"Thread-1" prio=6 tid=0x00c70bd8 nid=0x914 runnable
兩個線程都是runnable狀態.
這程序,理論上,不應該出現死鎖的.
兩個線程都是runnable狀態.
這程序,理論上,不應該出現死鎖的.
re: 記一復雜頁面的前端優化(1) - 不一樣的延遲加載 stone2083 2010-07-14 12:31
@BearRui(AK-47)
Sorry,Sorry.
你底下的幾個button做的不錯,發覺挺有意思的,就多點了幾下.沒想到居然是發評論用的. :)
Sorry,Sorry.
你底下的幾個button做的不錯,發覺挺有意思的,就多點了幾下.沒想到居然是發評論用的. :)
re: 單元測試下簡易性能測試工具 stone2083 2010-06-21 19:10
@TestThug
1.要看公司政策了;
2.要看JTester作者意愿了;
從目前看,開源的可能并不大 :(
1.要看公司政策了;
2.要看JTester作者意愿了;
從目前看,開源的可能并不大 :(
re: 編程方式實現SpringBean LazyInit stone2083 2010-06-19 01:11
今天又細看了代碼,發現覆寫
AbstractXmlApplicationContext.initBeanDefinitionReader(XmlBeanDefinitionReader beanDefinitionReader) 方法更為合理.
AbstractXmlApplicationContext.initBeanDefinitionReader(XmlBeanDefinitionReader beanDefinitionReader) 方法更為合理.
re: ubuntu如何用adsl上網 stone2083 2010-06-18 08:36
@周
理論上說,源上肯定存在著兩個package的.是否是你自己設置了其他源導致的?
不過沒關系,手工下載包,再安裝好了.
http://packages.ubuntu.com/
找到你ubuntu版本,點擊所有產品包(例如:http://packages.ubuntu.com/lucid/allpackages),查找pppoe和pppoeconf.手工下載,安裝即可.
當然,ubuntu cd自帶也有.插入ubuntu cd.使用apt安裝也可.
有一份詳細的文檔,不妨看看:https://help.ubuntu.com/community/ADSLPPPoE
理論上說,源上肯定存在著兩個package的.是否是你自己設置了其他源導致的?
不過沒關系,手工下載包,再安裝好了.
http://packages.ubuntu.com/
找到你ubuntu版本,點擊所有產品包(例如:http://packages.ubuntu.com/lucid/allpackages),查找pppoe和pppoeconf.手工下載,安裝即可.
當然,ubuntu cd自帶也有.插入ubuntu cd.使用apt安裝也可.
有一份詳細的文檔,不妨看看:https://help.ubuntu.com/community/ADSLPPPoE
re: Tomcat(6.0.14) Session創建機制簡介 stone2083 2010-06-11 20:23
@小菜花
理論上來說,傳遞jsessionid,只要value是一致的,服務端不會創建多份session.
可以在測試環境下通過debug 或者 監控工具,跟蹤下創建多份session的情況.
理論上來說,傳遞jsessionid,只要value是一致的,服務端不會創建多份session.
可以在測試環境下通過debug 或者 監控工具,跟蹤下創建多份session的情況.
re: 單元測試下簡易性能測試工具 stone2083 2010-06-11 08:51
@BeanSoft
接受觀點.
之所以考慮使用毫秒,是因為不同的開發機性能參差不齊,對性能的影響遠遠大于本身計算的精確性.
而這個簡易工具,本意只是提供感性的性能數據.所以提供的數據并不精確(當然,之后會隨著項目開發中提出的需求做完善),而是相對于程序員更友好的單位.
接受觀點.
之所以考慮使用毫秒,是因為不同的開發機性能參差不齊,對性能的影響遠遠大于本身計算的精確性.
而這個簡易工具,本意只是提供感性的性能數據.所以提供的數據并不精確(當然,之后會隨著項目開發中提出的需求做完善),而是相對于程序員更友好的單位.
re: J2EE壓力測試的性能問題 stone2083 2010-04-17 22:09
為什么不考慮使用JSESSIONID,來模擬更真實的用戶并發情況?
re: 支付寶接口demo代碼讀后感 stone2083 2010-03-17 10:15
@出錯
比較遺憾.我第一時間和支付寶工程師聯系反饋了這個問題.沒想到他們到現在還沒有跟進...
比較遺憾.我第一時間和支付寶工程師聯系反饋了這個問題.沒想到他們到現在還沒有跟進...
re: Tomcat(6.0.14) Session創建機制簡介 stone2083 2010-03-07 15:30
@小菜花
準確地講,除非你的應用完全不需要保存狀態(無狀態應用),不然地話,只要有一個新的連接過來,web容器都需要創建Session概念,維護狀態信息.
但是Session是什么?Session僅僅是一個概念:"Provides a way to identify a user across more than one page request or visit to a Web site and to store information about that user."--簡單地講,保存用戶狀態信息.
所以說,我們完全可以根據應用的需求,定制Session的實現:
a. Session保存到JVM內容中--Tomcat默認的實現
b. Session保存到Cookie中--Cookie-Based Session
c. Session保存到本地文件--Tomcat提供的非默認實現之一
d. Session保存到Cache Store中--比如常見的Memcached
e. Session保存到數據庫中--比如保存到mysql數據庫session表,中間對于活躍的Session 緩存到cached中.
......
那么,假如一個應用有大量一次性不同用戶的請求(僅僅是一次性的,比如上述文章描述的場景),那么選擇c,d,e方案都能有效解決文中所描述的問題.
準確地講,除非你的應用完全不需要保存狀態(無狀態應用),不然地話,只要有一個新的連接過來,web容器都需要創建Session概念,維護狀態信息.
但是Session是什么?Session僅僅是一個概念:"Provides a way to identify a user across more than one page request or visit to a Web site and to store information about that user."--簡單地講,保存用戶狀態信息.
所以說,我們完全可以根據應用的需求,定制Session的實現:
a. Session保存到JVM內容中--Tomcat默認的實現
b. Session保存到Cookie中--Cookie-Based Session
c. Session保存到本地文件--Tomcat提供的非默認實現之一
d. Session保存到Cache Store中--比如常見的Memcached
e. Session保存到數據庫中--比如保存到mysql數據庫session表,中間對于活躍的Session 緩存到cached中.
......
那么,假如一個應用有大量一次性不同用戶的請求(僅僅是一次性的,比如上述文章描述的場景),那么選擇c,d,e方案都能有效解決文中所描述的問題.
re: “業務比技術重要”一條企業開發中經典的謬論 stone2083 2009-12-07 18:07
"業務比技術重要“看怎么去理解了,要理解業務的邊界;技術的邊界
我雖然比較看重技術,但是也認可”業務比技術重要“。
我所理解這句話的含義:業務是本,技術為業務服務。
問題是什么?
業務包含哪些范圍(邊界),我認為的業務,不僅僅是原始需求,包括:
*原始業務需求
*需求分析
*業務建模
這些都屬于業務規劃(或者是產品規劃)的一部分。
技術包含哪些范圍(邊界),我認為:
*選用技術語言
*技術架構
*實現模型
*實現編碼
只是現在,很多需求分析,業務建模(或者說領域建模)都是技術團隊在做,會誤以為這些都是屬于技術的范圍。
真正能做好業務規劃的團隊和單位,真的是太少了,往往只提供原始需求,就讓技術去實現罷了。
我雖然比較看重技術,但是也認可”業務比技術重要“。
我所理解這句話的含義:業務是本,技術為業務服務。
問題是什么?
業務包含哪些范圍(邊界),我認為的業務,不僅僅是原始需求,包括:
*原始業務需求
*需求分析
*業務建模
這些都屬于業務規劃(或者是產品規劃)的一部分。
技術包含哪些范圍(邊界),我認為:
*選用技術語言
*技術架構
*實現模型
*實現編碼
只是現在,很多需求分析,業務建模(或者說領域建模)都是技術團隊在做,會誤以為這些都是屬于技術的范圍。
真正能做好業務規劃的團隊和單位,真的是太少了,往往只提供原始需求,就讓技術去實現罷了。
re: CGlib簡單介紹 stone2083 2009-10-10 10:38
@名揚/六耶子
cglib底層依賴了asm,它主要是在“動態代理”場景下增加易用性。
如果要動態生成字段,方法,那么asm或者javassist這兩個技術,更合適你。
cglib底層依賴了asm,它主要是在“動態代理”場景下增加易用性。
如果要動態生成字段,方法,那么asm或者javassist這兩個技術,更合適你。
re: Struts2.1.6--想用通配符,不容易 stone2083 2009-09-27 19:44
剛去struts官方網站溜達了下:
http://issues.apache.org/struts/browse/WW-3024
已經有人提交了bug,在struts2.1.8中,修復。
查看了xwork trunk的代碼,發現修復方式,跟我原文的一樣。先這么用一段時間吧。 :)
trunk代碼:
http://svn.opensymphony.com/svn/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/validator/AnnotationActionValidatorManager.java
http://issues.apache.org/struts/browse/WW-3024
已經有人提交了bug,在struts2.1.8中,修復。
查看了xwork trunk的代碼,發現修復方式,跟我原文的一樣。先這么用一段時間吧。 :)
trunk代碼:
http://svn.opensymphony.com/svn/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/validator/AnnotationActionValidatorManager.java
re: Struts2.1.6--想用通配符,不容易 stone2083 2009-09-27 19:09
@Simon
沒有放之四海而皆準的技術,任何技術,總是有利弊的,關鍵是看怎么權衡了。
用通配符也好,zero config plugin也好,都可以,我只有一個要求,就是COC。
做為程序員,封裝變化,抽取共性,減少一切可以減少的重復勞動力。
在我看來,一個一個配置action,就是重復勞動力。至少在80%的場景下,配置都是差不多的。
試想一下,當一個應用,有上千個action時,光是action的配置文件,就是幾千甚至上萬行。這個維護工作量,不敢想象。
至于攔截器,同理,我以為,80%的情況下,action配置的攔截器都是同樣的。所以就算使用通配符,我可以用其他的方案解決特殊(20%)的需求。
Annotation,額,這個玩意,我不敢濫用。只有20%的需求才有的特殊需求場景下,我還會考慮(僅僅是考慮)使用Annotation。
Struts2中,Action上的annotation設計,我一直不敢恭維。所以我絕對不會使用annotation的。
其實從我原文中,一直在描述如何尋找Validatior文件的方法,沒有說我用了annotaion。在很多場景下,我一直是xml的擁護者,當然最擁護的,是Convertion。 :)
沒有放之四海而皆準的技術,任何技術,總是有利弊的,關鍵是看怎么權衡了。
用通配符也好,zero config plugin也好,都可以,我只有一個要求,就是COC。
做為程序員,封裝變化,抽取共性,減少一切可以減少的重復勞動力。
在我看來,一個一個配置action,就是重復勞動力。至少在80%的場景下,配置都是差不多的。
試想一下,當一個應用,有上千個action時,光是action的配置文件,就是幾千甚至上萬行。這個維護工作量,不敢想象。
至于攔截器,同理,我以為,80%的情況下,action配置的攔截器都是同樣的。所以就算使用通配符,我可以用其他的方案解決特殊(20%)的需求。
Annotation,額,這個玩意,我不敢濫用。只有20%的需求才有的特殊需求場景下,我還會考慮(僅僅是考慮)使用Annotation。
Struts2中,Action上的annotation設計,我一直不敢恭維。所以我絕對不會使用annotation的。
其實從我原文中,一直在描述如何尋找Validatior文件的方法,沒有說我用了annotaion。在很多場景下,我一直是xml的擁護者,當然最擁護的,是Convertion。 :)
re: Struts2.1.6--想用通配符,不容易 stone2083 2009-09-27 12:39
@梁章坪
沒錯,最正宗的格式是ActionName--validation.xml。
請看,AnnotationActionValidatorManager中的buildValidatorConfigs方法片段:
validatorConfigs.addAll(buildClassValidatorConfigs(clazz, checkFile));
在buildClassValidatorConfigs方法中,
String fileName = aClass.getName().replace('.', '/') + VALIDATION_CONFIG_SUFFIX;
就是你說的ActionName--validation.xml格式。
在一個Action只有一個方法(execute)的時候,這樣是夠用的。
但是Struts2為了支持一個Action有多個方法(CRUD)的時候,那么怎么為不同的方法尋找它需要的校驗文件呢?
于是乎,繼續看AnnotationActionValidatorManager中的buildValidatorConfigs方法片段:
if (context != null) {
validatorConfigs.addAll(buildAliasValidatorConfigs(clazz, context, checkFile));
}
將Action名和context做組合,作為校驗文件的別名(alias)。
至于context是什么?我一開始以為是method名,結果看了代碼,發現不是。struts2是傳了${配置中的action name=""}中的名字
看來它的本意是希望同一個action的方法,在不同使用場景下,也允許不同的校驗規則。
所以就有了這樣的格式定義。 :)
沒錯,最正宗的格式是ActionName--validation.xml。
請看,AnnotationActionValidatorManager中的buildValidatorConfigs方法片段:
validatorConfigs.addAll(buildClassValidatorConfigs(clazz, checkFile));
在buildClassValidatorConfigs方法中,
String fileName = aClass.getName().replace('.', '/') + VALIDATION_CONFIG_SUFFIX;
就是你說的ActionName--validation.xml格式。
在一個Action只有一個方法(execute)的時候,這樣是夠用的。
但是Struts2為了支持一個Action有多個方法(CRUD)的時候,那么怎么為不同的方法尋找它需要的校驗文件呢?
于是乎,繼續看AnnotationActionValidatorManager中的buildValidatorConfigs方法片段:
if (context != null) {
validatorConfigs.addAll(buildAliasValidatorConfigs(clazz, context, checkFile));
}
將Action名和context做組合,作為校驗文件的別名(alias)。
至于context是什么?我一開始以為是method名,結果看了代碼,發現不是。struts2是傳了${配置中的action name=""}中的名字
看來它的本意是希望同一個action的方法,在不同使用場景下,也允許不同的校驗規則。
所以就有了這樣的格式定義。 :)
re: 支付寶接口demo代碼讀后感 stone2083 2009-09-21 13:10
其實本身并沒有非常強制的標準,比如一定得:3<參數<類 用map
原則只有一個,方便客戶端的調用。
比如上面舉的例子,一共有19個參數,調用者能方便的調用嗎?哪個參數在哪個位置,能方便找到嗎?
所以,自定義map(定義了key常量的map)或者parameter Class,更合適上面的場景。
原則只有一個,方便客戶端的調用。
比如上面舉的例子,一共有19個參數,調用者能方便的調用嗎?哪個參數在哪個位置,能方便找到嗎?
所以,自定義map(定義了key常量的map)或者parameter Class,更合適上面的場景。
re: Lightning--thunderbird下的日歷議程工具 stone2083 2009-08-19 12:30
@林茂
能兼容outlook的事件邀請。至于是否100%,不敢保證,從我使用情況看,outlook 2003,2007的事件邀請,都能兼容。
但是不兼容發送的實踐邀請,我使用lightning發送的邀請,在outlook上查看,只能顯示一堆源碼。
能兼容outlook的事件邀請。至于是否100%,不敢保證,從我使用情況看,outlook 2003,2007的事件邀請,都能兼容。
但是不兼容發送的實踐邀請,我使用lightning發送的邀請,在outlook上查看,只能顯示一堆源碼。
re: Struts2.1.6 StrutsPrepareAndExecuteFilter bug stone2083 2009-06-13 11:02
個人不希望僅僅因為猥瑣解決這個bug,而引入對spring-web的依賴。
手寫一個CharacterEncodingFilter也是比較方便的事情。
當然,切會org.apache.struts2.dispatcher.FilterDispatcher,也是一個可選方案。
當時自己不選擇FilterDispatcher的原因是:
在應用測試的時候,順帶測試struts2 StrutsPrepareAndExecuteFilter(官方推薦)方案.免得等2.1.7發布后,在換回StrutsPrepareAndExecuteFilter時,又發現其他問題。
相對來說,刪除一個Filter的風險更小一些 :)
手寫一個CharacterEncodingFilter也是比較方便的事情。
當然,切會org.apache.struts2.dispatcher.FilterDispatcher,也是一個可選方案。
當時自己不選擇FilterDispatcher的原因是:
在應用測試的時候,順帶測試struts2 StrutsPrepareAndExecuteFilter(官方推薦)方案.免得等2.1.7發布后,在換回StrutsPrepareAndExecuteFilter時,又發現其他問題。
相對來說,刪除一個Filter的風險更小一些 :)
re: Tomcat重定向傳中文 stone2083 2009-06-11 12:44
url參數中帶中文的應用場景還是很多的。
關鍵是采用某種技術手段去實現的問題了。
url encoder就是用來做這樣的事情的:
java.net.URLEncoder.encode(urlParams, encoding);
關鍵是采用某種技術手段去實現的問題了。
url encoder就是用來做這樣的事情的:
java.net.URLEncoder.encode(urlParams, encoding);
re: 區分Action, Service 和 Dao功能 stone2083 2009-05-21 13:25
比喻很形象,也比較能說明問題。站在技術角度上,我非常認同你說的觀點。
對于一家長期發展的公司,系統演變會越來越復雜,前期為了貪圖方便的設計,總有一天,會帶來無窮的痛楚。這些俺都明白。目前也在經歷這些痛楚。
但是,確實也存在很多系統,本身業務并不復雜(比如外包公司接手的一次性的小項目),并且也很難看到未來的發展方向(比如針對一些創業型公司的項目),之后重寫+數據遷移的方案代價遠遠小于系統重構的代價,那么我,決不會采用復雜的架構,把簡單問題復雜化。
PHP,ROR(使用action+model,沒有過多分層)的項目,在中小型項目中,比較流行的,也能說明一些問題。
很多的系統,如果能標標準準按照action->biz->dao的結構寫,已經是相當不錯了(通過一些應用拋出的錯誤異常看,很多甚至在jsp上書寫大量的業務邏輯,或者在action屬性大量的業務邏輯)。要在biz層抽象出biz->service的概念的系統,并不是太多。(至少是中型公司及以上,才需要考慮的)
我說這些,不是為了否決樓上的說辭--其實我是非常認同的觀點。
我只是想表明,任何的架構設計,都是需要根據需求以及未來的發展,來決定的。
對于一家長期發展的公司,系統演變會越來越復雜,前期為了貪圖方便的設計,總有一天,會帶來無窮的痛楚。這些俺都明白。目前也在經歷這些痛楚。
但是,確實也存在很多系統,本身業務并不復雜(比如外包公司接手的一次性的小項目),并且也很難看到未來的發展方向(比如針對一些創業型公司的項目),之后重寫+數據遷移的方案代價遠遠小于系統重構的代價,那么我,決不會采用復雜的架構,把簡單問題復雜化。
PHP,ROR(使用action+model,沒有過多分層)的項目,在中小型項目中,比較流行的,也能說明一些問題。
很多的系統,如果能標標準準按照action->biz->dao的結構寫,已經是相當不錯了(通過一些應用拋出的錯誤異常看,很多甚至在jsp上書寫大量的業務邏輯,或者在action屬性大量的業務邏輯)。要在biz層抽象出biz->service的概念的系統,并不是太多。(至少是中型公司及以上,才需要考慮的)
我說這些,不是為了否決樓上的說辭--其實我是非常認同的觀點。
我只是想表明,任何的架構設計,都是需要根據需求以及未來的發展,來決定的。
re: 區分Action, Service 和 Dao功能 stone2083 2009-05-15 12:23
一般應用中,biz層和service層的概念就是同一個,硬做分層,是脫了褲子放屁 ,自找麻煩。 :)
當公司規模大了,應用龐大了,復雜了:
比如,當web應用有幾十,上百個;task應用幾十,上百個。。。
該如何控制和維護業務人員編寫的biz和dao呢?
于是乎,就需要抽象出service層(核心組件服務/核心產品服務),service依賴dao api,search engine api,dw api等等,并且通過某些協議,暴露自己的service api
前臺應用(web應用,task應用等),通過biz層,調用不同service api(不再涉及dao等底層服務)
如此一來,底層實現發生變化,比如數據庫重構等,只要維持service api不變,不會涉及前臺應用的變動。
如同上面說的,要不要biz,service,還是根據應用規模來決定的。
當公司規模大了,應用龐大了,復雜了:
比如,當web應用有幾十,上百個;task應用幾十,上百個。。。
該如何控制和維護業務人員編寫的biz和dao呢?
于是乎,就需要抽象出service層(核心組件服務/核心產品服務),service依賴dao api,search engine api,dw api等等,并且通過某些協議,暴露自己的service api
前臺應用(web應用,task應用等),通過biz層,調用不同service api(不再涉及dao等底層服務)
如此一來,底層實現發生變化,比如數據庫重構等,只要維持service api不變,不會涉及前臺應用的變動。
如同上面說的,要不要biz,service,還是根據應用規模來決定的。
re: 區分Action, Service 和 Dao功能 stone2083 2009-05-14 20:49
根據需求來決定的。
系統分層,和公司設立部門的概念是同樣的。
一個創業型公司,很可能整個公司就一個人:即是老板,又是程序員,同時還是業務員,等等,
如同一個系統中,一個action做了所有的業務;
一個中型公司,有一個老板,有一個技術人員,有一個業務人員,有一個運營人員,等等,
如同一個系統中,有action層,biz層,service層,dao層等,通過jar包依賴調用;
一個大型公司,有CEO,有技術部們,有業務部門,有運營部門,等等,
如同系統模型中,每個模塊存在獨立service系統服務,依賴dao api,依賴search engine api,依賴DW api等;
前臺又有不同的業務系統,有自己的action,依賴biz層,biz層又依賴獨立模塊的service api;
系統之間的依賴,采用SOA架構等
不同的企業規模,決定不同的公司組織架構;
不同的產品需求,決定不同的系統架構;
系統分層,和公司設立部門的概念是同樣的。
一個創業型公司,很可能整個公司就一個人:即是老板,又是程序員,同時還是業務員,等等,
如同一個系統中,一個action做了所有的業務;
一個中型公司,有一個老板,有一個技術人員,有一個業務人員,有一個運營人員,等等,
如同一個系統中,有action層,biz層,service層,dao層等,通過jar包依賴調用;
一個大型公司,有CEO,有技術部們,有業務部門,有運營部門,等等,
如同系統模型中,每個模塊存在獨立service系統服務,依賴dao api,依賴search engine api,依賴DW api等;
前臺又有不同的業務系統,有自己的action,依賴biz層,biz層又依賴獨立模塊的service api;
系統之間的依賴,采用SOA架構等
不同的企業規模,決定不同的公司組織架構;
不同的產品需求,決定不同的系統架構;
re: 事件消息通知系統 stone2083 2009-05-11 20:29
多謝指點。細節部分,確實沒有仔細思考過。
平時忙于項目,太少有空余時間,來思考這些技術性問題。 :(
平時忙于項目,太少有空余時間,來思考這些技術性問題。 :(
re: JAXB vs XStream stone2083 2009-03-16 19:25
我還有一個問題不明白:
如果需要捆綁Object,類似RPC調用,那為什么不選擇hessian等二進制序列化方式的組件。
畢竟二進制序列化/反序列化效率比xml轉化高多了。
當然hessian不同版本在協議上的不兼容,是一件很頭疼的事情 :(
如果需要捆綁Object,類似RPC調用,那為什么不選擇hessian等二進制序列化方式的組件。
畢竟二進制序列化/反序列化效率比xml轉化高多了。
當然hessian不同版本在協議上的不兼容,是一件很頭疼的事情 :(
re: SLF4J+logBack, 日志領域中的新秀 stone2083 2009-03-14 13:16
第二次看到SLF4J的介紹了。有了感性的認識。不免有些心動。等有空閑的時候,深入了解下這東東。
re: 收集整理的java筆試面試題目 1.0版本…… stone2083 2009-03-13 23:14
心態要擺正,如果純粹為了面試而去看面試題,是沒多少意義的。
真正在面試過程中,對于一些僅僅看過面試題卻沒有深入掌握的人,只要多問幾個為什么,往往就回答不上來了。
真正在面試過程中,對于一些僅僅看過面試題卻沒有深入掌握的人,只要多問幾個為什么,往往就回答不上來了。
re: 基于java實現的多層目錄結構 stone2083 2009-03-07 11:08
其實這玩意,也是臨時之作,有很多不完善的地方。
主要是提供一個思路,供大家一起討論。
主要是提供一個思路,供大家一起討論。
re: JAXB vs XStream stone2083 2009-03-07 10:42
@叱咤紅人
我不太明白,在遠程通信上,使用xml作為中間傳輸內容,就是為了做系統(甚至是異構系統)之間的解耦。
如果xml內容上,還捆綁了類信息,那么既要求兩個系統為同語言系統,又將兩個系統都捆綁到具體的一個model上。未必是一件好事。
我不太明白,在遠程通信上,使用xml作為中間傳輸內容,就是為了做系統(甚至是異構系統)之間的解耦。
如果xml內容上,還捆綁了類信息,那么既要求兩個系統為同語言系統,又將兩個系統都捆綁到具體的一個model上。未必是一件好事。
re: tomcat下 共享session (摘自網上,沒有具體驗證,如果哪位驗證了,請告知一下謝謝) stone2083 2009-03-07 10:27
不推薦使用tomcat默認的session機制。
基于內存的session,無可避免GC帶來的問題,何況在集群環境下,同步開銷太大。
推薦使用基于memcached,或者database的session。
基于內存的session,無可避免GC帶來的問題,何況在集群環境下,同步開銷太大。
推薦使用基于memcached,或者database的session。
re: Ubuntu的速度這么快? stone2083 2009-02-28 23:32
這套桌面主題看上去不錯 :)
re: 推薦Java編碼工具:FindBugs stone2083 2009-02-16 12:41
一直在用,性價比超高的一款工具。
re: XIbatis 發布-對ibatis的分頁查詢進行了擴展和功能增強 stone2083 2008-12-02 14:06
想法是好的,做法是不可取的。
任何對第三方組件的擴展,需要遵循開放-封閉原則:只能尋找組件的擴展點進行功能擴展,不允許直接修改源碼。
試想一下,你修改了源代碼,以后如何解決與官方網站版本升級的同步問題?
沒有團隊敢使用你的包。
很早之間,我就有這個想法。但是發覺MappedStatement,SqlMapExecutorDelegate都是面向實現編程;
并且SqlMapClient也是通過:
public SqlMapConfiguration() {
errorContext = new ErrorContext();
delegate = new SqlMapExecutorDelegate();
typeHandlerFactory = delegate.getTypeHandlerFactory();
client = new SqlMapClientImpl(delegate);
registerDefaultTypeAliases();
}
直接new出來的。
所以,似乎找不到擴展的地方來實現“分頁”的需求。
不知道大家是否有更好的方案,歡迎討論。
任何對第三方組件的擴展,需要遵循開放-封閉原則:只能尋找組件的擴展點進行功能擴展,不允許直接修改源碼。
試想一下,你修改了源代碼,以后如何解決與官方網站版本升級的同步問題?
沒有團隊敢使用你的包。
很早之間,我就有這個想法。但是發覺MappedStatement,SqlMapExecutorDelegate都是面向實現編程;
并且SqlMapClient也是通過:
public SqlMapConfiguration() {
errorContext = new ErrorContext();
delegate = new SqlMapExecutorDelegate();
typeHandlerFactory = delegate.getTypeHandlerFactory();
client = new SqlMapClientImpl(delegate);
registerDefaultTypeAliases();
}
直接new出來的。
所以,似乎找不到擴展的地方來實現“分頁”的需求。
不知道大家是否有更好的方案,歡迎討論。
re: What is Spring? stone2083 2008-12-02 09:49
現在,對spring是越來越難下定義了。
通過mvnrepository看看spring的范圍:
http://mvnrepository.com/search.html?query=spring
做的是越來越龐大了。
想想早幾年的時候,對Spring的概念,還停留在ioc容器上。接下來又出現了AOP的概念。
如今呢?感覺spring對任何第三方組件,都要插一手。不過,話又說回來,spring對第三方組件的封裝,確實提高了開發效率。
關鍵看,你要用spring什么了?
通過mvnrepository看看spring的范圍:
http://mvnrepository.com/search.html?query=spring
做的是越來越龐大了。
想想早幾年的時候,對Spring的概念,還停留在ioc容器上。接下來又出現了AOP的概念。
如今呢?感覺spring對任何第三方組件,都要插一手。不過,話又說回來,spring對第三方組件的封裝,確實提高了開發效率。
關鍵看,你要用spring什么了?
re: 學習Common BeanUtils stone2083 2008-09-28 23:06
推薦使用cglib的beancopier替代beanutil做copy工作。