2009-05-31 92 views
0

我正在開發一個java servlet web應用程序,它管理來自多個數據庫(所有結構相同)的信息,每個數據庫對應不同的「業務」。用戶選擇存儲在會話中的「當前業務」,並且應用可以顯示或修改「當前業務」。一個servlet上下文的多個動態數據源

我想動態地使用tomcat資源來使用jndi訪問這些業務。通過這種方式,我可以在servlet中使用jstl sql標記或上下文查找。我無法在web.xml文件中定義每個資源,因爲它們存儲在SQL表中。最終的結果是要能夠編寫簡單的JSP中有這樣的詩句:

<%@ taglib uri="http://java.sun.com/jstl/sql" prefix="sql" %> 

<sql:query var = "users" dataSource="sources/${sessionScope.currentBusiness}"> 
    select id, firstName, lastName FROM user 
</sql:query> 

或小服務程序,可以有這樣的

String request.getSession().getAttribute("currentBusiness"); 

Context initial = new InitialContext(); 
Context context = (Context) initial.lookup("java:comp/env"); 
DataSource source = (DataSource) context.lookup("sources/" + currentBusiness); 

線在那裏我能得到正確的數據源爲「當前商業」。

我已經嘗試編寫自己的從javax.naming.spi.ObjectFactory派生的ObjectFactor而沒有成功。任何關於如何輕鬆做到這一點的指針?

回答

2

我最終解決了以下解決方案,它包含一個SessionListener和一個Servlet,它們的工作方式如下。該SessionListener具有下列形式:

public class SessionListener implements HttpSessionListener { 

    public void sessionCreated(HttpSessionEvent event) { 

    HttpSession session = event.getSession(); 

    // get list of possible data sources available to this session 
    List<DataSource> sources = new ArrayList<DataSource>(); 
    ... code to get the available sources 

    // get the current data source 
    DataSource source = null; 
    ... code to get the current source        
    source = sources.get(0); // for example 

    // setup the session attributes 
    session.setAttribute("availableSources", sources); 
    session.setAttribute("currentSource", source); 

    } 

} 

只要創建一個用戶登錄和會話,可用數據源的列表,以及當前一個,放入了會議。這是在會話級完成的,因爲DataSources依賴於用戶登錄。現在可以在應用程序中訪問它們。要改變當前的數據源我創建了這個簡化版本,一個Servlet:

public abstract class BoxletServlet extends HttpServlet { 

    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
    throws ServletException, IOException { 

    HttpSession session = request.getSession(true); 
    String s = request.getParameter("source"); 

    // based on 's' choose from the available DataSource 
    List<DataSource> sources = (List<DataSource>) session.getParameter("availableSources"); 
    Source source = chooseFrom(sources, s);              
    session.setParameter("currentSource", source);   

    // forward to a page saying that the DataSource changed 

    } 

}

使用這種實現,現在可以創建如下的JSP:

<%@ taglib uri="http://java.sun.com/jstl/sql" prefix="sql" %> 

<sql:query var = "users" dataSource="${sessionScope.currentSource}"> 
    select id, firstName, lastName FROM user 
</sql:query> 

希望它可以幫助別人其他。

1

ServletContextListener中創建數據源並將它們放置在ServletContext中。

+0

您將如何通過JNDI接口訪問它? – rmarimon 2009-05-31 20:45:20

+0

你不能這樣做。也許在同一個監聽器中,你可以使用context.bind(name,object)? – 2009-05-31 21:16:43

0

這種方法肯定會「有效」,但每個業務單獨的,相同的數據庫的概念對我來說似乎是錯誤的。當然能夠在架構中的某處描繪業務似乎是可能的。以這種方式分離它們需要每個業務都有一個新的數據庫,其中一個模式只需要一個新的業務標識符。

我還會爭辯說任何跨業務數據挖掘的可能性都會丟失,除非您將來自單獨數據庫的ETL數據轉換爲特定報告和查詢的維度多維數據集。

和JSTL <sql>標籤只能用於最簡單的網絡應用程序。當你放棄在中間層進行驗證時,你可能會面臨SQL注入攻擊的可能性。

UPDATE:

你必須AFAIK聲明在web.xml資源,所以只要你有一個新的數據庫,你必須停止該應用程序,配置新的JNDI源,並重新啓動Tomcat。我希望你是集羣的,因爲每次添加新的業務/數據庫時,所有以前的客戶端都會受到應用程序關閉的影響。