2014-11-02 52 views
0

我試圖圍繞從JSF Web應用程序建立到數據庫的JDBC連接的正確方法。我通常的方法是在應用程序服務器中創建一個數據源,並通過我的代碼中的JNDI名稱連接到它。實質上,所有用戶都將在整個會話期間通過池共享相同的數據庫用戶帳戶。來自Web應用程序的數據庫連接沒有連接池

不幸的是,我正在處理的一個新項目的要求阻止了我這樣做。連接到應用程序的每個用戶都必須使用唯一憑證登錄到RDBMS。我有一個如何實現與此相關的代碼的草圖,但我並未完全清楚整體架構。 應用程序服務器(Tomcat,Glassfish,WebLogic)是否具有支持此功能的功能?

現在,我似乎可以完成這一任務的唯一方法是讓每個用戶會話直接創建一個JDBC連接回數據庫。雖然我相信這會起作用,但它感覺不對。

我錯過了什麼嗎?

+0

您可能想要檢查從['DataSource.getConnection(username,password)'](http://docs.oracle.com/javase/8/docs/api/javax/sql/DataSource.html #getConnection-java.lang.String-java.lang.String-)根本就是共享的(我見過的池和沒有的池)。 – 2014-11-02 08:06:01

回答

1

你錯過了什麼 - 我非常想:合理的系統設計。 ;)使用數據庫憑證管理用戶的整個想法恰好適用於管理數據庫的一個用例。對於其他所有問題,它會帶來更多的問題,因爲它會帶來更多的問題......所以讓我們開始吧......)

BOT:有一個兩難的問題。您基本上必須爲每個用戶創建一個連接池,因爲否則每次數據源在連接超時運行時都必須創建與數據庫的連接。三次握手加認證不是一件便宜的事情 - 延遲會導致你的表現。雖然有些驅動程序可以進行相應的配置,但總的來說這是一個糟糕的主意,而且大多數驅動程序由於所謂的「關注點分離」而不善於自己管理連接。另一方面,每個連接「池」只需要大約5個連接,因爲同一用戶不太可能並行執行多個操作。

注意:我知道的唯一一個驅動程序管理連接和池的驅動程序是體面的。

現在問題在於:您無法將連接池附加到會話。不是沒有走幾英里,我懷疑這是完全可能的。

解決此問題的一個想法是,當用戶登錄並使用JNDI動態註冊時,爲用戶創建連接池。問題是這不是很有伸縮性(假設你有幾百個用戶)。因此,當會話終止時(無論是通過註銷還是超時),您都必須確保刪除該池。另外,代碼必須保留。

另一個想法是使用Apache Shiro並編寫一個自定義Realm,它只是試圖登錄數據庫來檢查憑據,如果失敗則拋出AuthenticationExcepion。這裏的折衷是你每次都必須初始化連接,這有一些延遲。您的領域甚至可能使用應用程序範圍的連接池,並檢查數據庫元數據以獲取身份驗證和授權數據。當然,這將使得有必要以特權用戶的身份訪問數據庫 - 這是一個可怕的想法。底線:不管你用哪種方式來看待它,通過數據庫管理應用程序認證和授權需求可能會消除應用程序中的認證和授權層,但是反過來需要一個額外的抽象層(你不需要'如果某些數據庫機制發生了變化,是否需要更改服務的代碼?),當我們看到並將代碼綁定到一個數據庫時,會產生可伸縮性問題(當然,除非您需要細粒度的權限並且可以與「工作,沒有工作」的結果)。

+0

非常感謝您的回覆!這些與我在提出要求時所擔心的完全一樣。我目前的想法(再一次,我意識到這不是理想..)將配置一個非常小的池,在RDBMS中讀取用戶創建的一組表來檢查憑據(不是例如Oracle中的dba_users視圖) 。一旦選中了信用卡,應用程序就會創建一個會話。從那裏,將爲他/她自己的RDBMS憑證創建另一個連接。 – Naitouk 2014-11-02 15:21:17

+0

我認爲這是太多的代碼來維護。我寧願去與Shiro和一個自定義領域,這是很容易實現。 – 2014-11-02 18:48:26

0

我不確定空連接池的開銷是多少,也不知道有多少用戶參與,但我建議保留連接池的全局列表,配置爲低最大連接數(2?)和侵略性空閒超時一直返回到零池連接。然後,當用戶登錄時,檢查他們是否已經有一個由他們的用戶名引用的池,如果沒有,則創建一個新池並將其保存在池中,然後爲該用戶的連接使用該池。

這樣你就可以以最小的開銷獲得池的好處。這是否可行取決於您的用戶數量。

我當然希望找到最適合您的最低開銷池實現 - 有幾種可供選擇。 c3p0對我自己來說非常棒。

+0

有趣的做法。由於每個用戶都將保證擁有100%的唯一用戶名,因此我可能需要在註銷時銷燬池。謝謝你的建議! – Naitouk 2014-11-02 06:16:20