免費ERP第二錘:架構簡單就好

上一錘提到了剛發佈的免費ERP系統(www.2bizbox.com)後,大家反響很熱烈,短短3天就被下載了2萬多次,服務器一度宕機,呵呵。大家討論也比較熱烈,紛紛提出不少問題和技術探討,感覺非常有意義。這次和大家分享一下關於這個免費ERP的架構設計。之前先回答一下大家比較關心的一些問題: * 網站只提供了windows的exe安裝版,大家詢問是否有適合linux跑的版本:這個可以有,不過還需要一點時間來發布,幾周後就會有下載,請大家耐心等待並及時關注。目前,官網上已經提供了exe和zip,不過都是針對windows平臺的。 * 下載後一些朋友無法解壓和運行,尤其使用迅雷等工具的朋友。這個原因還不知道,可能和多線程下載以及網絡有關,可以在下一次,或儘量不使用工具下載。由於服務器在國外,下載速度肯定不會特別好。不過一些熱心網友已經提供了國內的下載鏈接,官網較慢的可以試試這裏:E備是鏈接地址,輸入驗證碼即可下載。我家2M帶寬,用chrome 自帶的下載工具下載,大約用了8分鐘完成下載。另外還有JavaSwingChina、天極網下載、華軍軟件園、綠色軟件聯盟、旋風下載、中關村在線、豆豆軟件站、。。。似乎一夜之間遍地都是了,呵呵 * 還有朋友關心公司是國內的還是國外的:公司是美國的,不過我們上海這個小團隊負責一部分開發工作。在國內也有不少客戶,例如中石油、襄鑽股份、江漢三機、四機賽瓦等,我們負責本地客戶服務。 * 有朋友詢問是否開源:目前是軟件完全免費,源代碼開放的事情還沒有消息。不過個人判斷完全有開源的可能性,呵呵,這要看美國人是怎麼想的了。 * 很多朋友關心團隊協調,高手低手如何共同工作,一個人搭框架,另外人不滿意怎麼辦等等。我想這個並不是一個軟件團隊的特有問題。要說是問題的話,是咱們中國人特有的一種毛病還差不多。“不服氣”從來是咱們的特點,問題不是高手太少,而是“大明白”、“專家”、“牛人”太多了。我曾經去一個製造廠做實施,接我們的司機談起公司的管理來,那真是口若懸河、吐沫橫飛、頭頭是道,上至老總下至看大門的,都被分析的“體無完膚”,好像馬上換他去當老總一切問題立馬解決似地。所以我認爲這根本就不是一個問題。想想“奧迪R8”和“寶馬7”這樣的工業精品都有一個總設計師,你是在問,BMW的一個剛進去工作的學生如果認爲寶馬7系的總設計師設計有問題該怎麼辦? 還是來說說架構。先看這個圖就都明白了。 提到架構,我們用到的第三方的框架不是很多,總的原則就是儘量簡單、穩固。這樣,就會高效、好維護。這遠比一些烏七八糟的所謂新思想新技術更加重要,畢竟我們的軟件要維護幾十年的(實際上已經從DOS到現在開發了20年了)。後臺主要是JBoss和Hibernate,其他大部分部分都是自己封裝。前臺則基於Swing以及自己封裝的各種組件。中間通訊也沒有采用第三方的框架,而是自己封裝,主要採用HTTP協議,對交換的VO(包括VO集合)對象(如參數、返回值、Exception等)進行標準的Java二進制序列化、zip壓縮、傳輸。調用的方法通過一個統一的invoke進行傳遞,被調用的模塊、方法名、參數等,都被封裝在一個POJO中傳給後臺。後臺Façade層解壓後,根據具體模塊,通過反射的方法,調用Local的各個模塊 EJB,執行具體函數。每個函數先在Biz業務層進行業務邏輯分解處理,例如,如果要添加一個零件,要分解很多具體動作,先檢查零件號是否重複,再檢查零件號是否格式合法,數據是否完備,創建零件庫存初始信息、創建物料添加日誌、通知相關人員…等等。分解後,形成具體的DAO操作,然後交給DAO進行調用相應的底層API完成。無數的DAO對各個業務數據進行各種數據級別的操作封裝(增刪改查等),然後通過Hibernate層進入數據庫。 有朋友喜歡用Eclipse RCP來作爲前臺框架。坦白說,我個人對SWT一向不喜歡,也不看好,因爲他本質上和AWT的路線沒什麼不同,只是後臺老闆從SUN換成了IBM。當初以 “好看+效率高”的旗號,SWT曾經風靡一時,人人趨之若鶩。不過本質上說,SWT這種技術是打着“好看/速度快”幌子分裂JAVA的政治遊戲,我們程序員應當看清楚。當然不是說SWT技術不好不能做企業應用,實際上我認識的一些朋友已經用SWT搭建了好大好大的應用。不過SWT畢竟不是JAVA的官方技術。如果相信JAVA的未來的話,我覺着應當相信SWING纔是正道。SWING有不足,但是它會不停的發展。另外,千萬別總拿“醜”和“慢”來攻擊 Swing,說到底還是看你會不會用,吐口水實在無意+無聊。說道RCP框架,我倒更喜歡NetBeans。不過國內大家還是把Netbeans當做 IDE來用,實際上這個RCP平臺相當不簡單,質量很高而且國外應用很多,已經非常成熟,有空可以多看看Netbeans的Platform頻道(不是 IDE哦)。 HttpInvoker沒有用過,不知是不是和Spring綁的比較死,看上去和我們的通訊方式完全類似。其實java序列化再傳輸就是幾行代碼的事情,如果不用Spring等框架,完全沒必要用第三方的,自己封裝一下就好了。看看這個代碼就知道了: Java代碼 1. /** 2. * Here should be the unique access of FacadeWrapper.invoke! 3. */ 4. public static Object invokeImpl(ServerAction action) throws ServerActionException { 5. action = new ServerAction(action.getModuleName(), action.getMethod(), escapedStringParamsConvertor(action.getParams()), paramsTypeConvertor(action.getParamTypes())); 6. action.setOrderBy(getOrderBy()); 7. 8. try { 9. Object result = FacadeWrapper.getInstance().invoke(action); 10. //unzip, if need. 11. if (result instanceof ZippedByteArray) { 12. ZippedByteArray zippedData = (ZippedByteArray) result; 13. if (zippedData.getByteArray() != null) { 14. try { 15. result = BB2Util.unzipObject(zippedData.getByteArray()); 16. } catch (Exception ex) { 17. throw new ServerActionException(ex); 18. } 19. } 20. } 21. 22. return result; 23. } catch (Exception ex) { 24. ExceptionWorker worker = new ExceptionWorker(ex); 25. //... 26. throw new ServerActionException(ex, anotherServer); 27. } 28. } /** * Here should be the unique access of FacadeWrapper.invoke! */ public static Object invokeImpl(ServerAction action) throws ServerActionException { action = new ServerAction(action.getModuleName(), action.getMethod(), escapedStringParamsConvertor(action.getParams()), paramsTypeConvertor(action.getParamTypes())); action.setOrderBy(getOrderBy()); try { Object result = FacadeWrapper.getInstance().invoke(action); //unzip, if need. if (result instanceof ZippedByteArray) { ZippedByteArray zippedData = (ZippedByteArray) result; if (zippedData.getByteArray() != null) { try { result = BB2Util.unzipObject(zippedData.getByteArray()); } catch (Exception ex) { throw new ServerActionException(ex); } } } return result; } catch (Exception ex) { ExceptionWorker worker = new ExceptionWorker(ex); //... throw new ServerActionException(ex, anotherServer); } } Hessian基於WS還可以支持不同的客戶端,也很不錯。不過我們這種需求不大,沒有使用WS以及其他客戶端技術的需求,也沒有采用。還是覺着簡單的東西自己封裝更加的靈活和容易控制。我們的思路是儘量少的引進第三方的框架。過多的異構框架導致的穩定性和靈活性的代價也是很大的。 其他一些類似MQ之類的異步框架就更比較謹慎使用。前後臺調用需要實時性,肯定是同步調用爲主。異步的情況不多,即使有,在基於HTTP的結構下(例如只開放80端口)也比較難實現。我們採用了JBOSS的JMS機制,實現一些後臺主動發送業務消息、上傳圖紙等功能。當然如果後臺禁止了相應端口,客戶端就自動放棄JMS連接,工作在純“主動模式”下,相當於一個“瀏覽器”。 對於非桌面客戶端,例如手機、數據採集器、PDA等,我們在後臺的Façade層上面再包裝一個又一個簡單的“協議適配”就行了,也就是把Java 的對象簡單的封裝到XML或HTML,負責與這類終端通訊。這樣,身後的安全啊、日誌啊、業務啊等就完全複用,開發速度是很快的。對於大多手機,使用 XHTML進行瀏覽即可;對於iPhone等則開發native的終端,對於PDA和數據採集器,由於有條形碼、收料發料、盤點等複雜應用,所以用本地的環境進行創建GUI(一般都是Windows CE,可用C#進行)。這樣,我們的架構可以簡單快速的支持各種不同的終端接入: 有朋友擔心一個Servlet提供所有API太變態,其實不必擔心。沒錯,我們的模塊API至少上萬,但是這個後臺的Façade Servlet其實只有不超過10個方法。最主要的一個是invoke,方法都是通過一個對象封裝了模塊、方法名、參數序列等來通過反射機制完成的,所以,無論後臺模塊API有多少,只要通過這一個唯一的業務入口出入就行了。至於前臺使用不太方便的問題,可以通過前臺再次封裝展開來解決。 最後在透漏一下這套免費ERP的下一步進度:目前正在緊張漢化工作,預計在本月內會發布全中文版本。Linux打包文件也在進行中,有望很快可以下載。其他還有很多很好的模塊,會陸續推出,期待大家支持和反饋。如果你身邊有人在研究或選型ERP,不放推薦一下這個全免費的、高質量的、專注機械製造業的大型ERP:2BizBox。 套用一句劉儀偉的說法:現在誰還花錢用ERP啊?! 最後送Swing界面:設置會計年度

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章