一個老邁企業應用的自述
我是一個上個世紀末開發的企業應用,年紀一大把了,不像那些年輕的系統,用著很多又酷又炫的新技術,什么前后端分離了,什么React了,響應式設計了, 我這里都沒有, 不怕你笑話,我這里只有老掉牙的JSP。
但是我也有一些年輕的系統所沒有的東西, 比如EJB 。
這個被大家拋棄的家伙還在我這里勤勤勉勉、任勞任怨地工作, 它住在應用服務器中, 用Session Bean來處理我們的業務邏輯, 用Entity Bean 來實現我們的O/R Mapping。
提到應用服務器,Websphere, Weblogic 可是鼎鼎大名,當年很多公司為了展示自己使用了***最熱門的技術(也可能是為了政績),紛紛掏腰包花大價錢購買。
我挺羨慕隔壁公司的Weblogic, 每天生活極其悠閑,整天就是處理一下Servlet和JSP, 和他那超級強悍的硬件和軟件完全不匹配,我常常帶著羨慕的口吻酸酸地評價: 你干的可都是Tomcat的活啊。
對比之下,我們公司還算是比較良心的, 至少把EJB這個應用服務器的核心功能給使用起來了, 我們還把4臺機器組成了一個集群做負載均衡, 每個EJB都會部署4份, 完全不用擔心一個機器掛掉了怎么辦。
各位看官, 那可真是分布式計算啊! 這些EJB對象分布在不同的機器上,時不時地被激活,被調用。
你可以想象一下, HTTP請求到達一個機器, 經過簡單的處理以后發現需要執行業務邏輯,于是這個機器就發起對EJB的調用 , 這個EJB可能在本機, 也可能在另外一個機器上, 跨越網絡的訪問此起彼伏,序列化和反序列化源源不斷,場面蔚為壯觀 。
有人可能要問了:這些EJB對象是分布式的, 你都不知道他們在哪個機器上, 你怎么去調用他們呢?
這是個好問題, 當時我也很發愁,想了很久,終于找到了一個辦法: 把鍋甩給Websphere, Weblogic這樣的應用服務器 , 誰讓他們這么貴呢!
具體的方法其實很簡單:我會給每個EJB都起個名,比如"order/OrderBean", Websphere/Weblogic需要把這個名字和實際的EJB對象給綁定起來 -- 很明顯這個工作很困難但是極為重要-- 這樣當我需要使用EJB的時候, 我就可以簡單地通過這個名字去查找一下,獲得EJB對象了。
- OrderBean orderBean = (OrderBean) context.lookup("order/OrderBean");
至于這個OrderBean是從哪個機器來的,作為應用層的我根本不關心,只要我能找到一個這樣的EJB對象, 我就可以工作了。
你可能還會問: 難道真的要把OrderBean對象從另外一個機器Copy的你的機器上嗎?
No No, 根本不是, 這背后的魔法其實是遠程方法調用(RMI),當我去查找對象的時候,看起來應用服務器給我返回了一個OrderBean, 實際上這只是一個存根(Stub),一個假對象而已!但是通過“假對象”,方法調用的參數可以被發送給遠程機器上的真正對象,去執行業務邏輯。 對了,這不就是你們常說的遠程代理模式嗎?
通過名稱來查找對象這種方法讓我的日常工作變得極為便利,應用服務器則怨聲載道,畢竟這是一件費心費力的事情, 但是為了占領市場,他們也不得不這么做。 我暗地里把這種工作方式叫Java Naming Service (Java 命名服務)
后來我發現,JDBC訪問數據庫也可以這么辦啊。 我為什么要在代碼中寫下數據庫的IP,端口,數據庫名,用戶名、密碼 ? 使用命名服務, 也可以把這個鍋扔給應用服務器: 我只知道數據源的名稱jdbc/OrderDB,至于它在什么地方,就不要來煩我了:
看看,通過名稱拿到一個叫做DataSource的對象,直接就可以獲得數據庫連接了。
再接再厲,把消息隊列相關的也給改了, 通過名稱(jms/OrderConnFactory)來獲取一個消息隊列的對象, 然后發送消息:
給大家畫個圖看看這個命名服務吧,客戶端可以通過lookup 的方式查找, 查找出的可能是直接的對象,也有可能是一個引用,指向了數據源,消息隊列,EJB等。
仔細想一想, 我這個命名服務和文件系統還有幾分相像, 都是給定一個名稱(如 C:\Users\admin\Documents\Test.java) , 然后獲得一個對象的引用(如File對象) , 看來這個世界在底層思想上都是相通的啊。
【本文為51CTO專欄作者“劉欣”的原創稿件,轉載請通過作者微信公眾號coderising獲取授權】