0

私は、それぞれが異なる「ビジネス」に対応する複数のデータベース (すべて構造的に同じ) からの情報を管理する Java サーブレット Web アプリケーションを開発しています。ユーザーはセッションに保存されている「現在のビジネス」を選択し、アプリケーションはその「現在のビジネス」を表示または変更できます。

jndi を使用してこれらのビジネスにアクセスできるように、Tomcat リソースを動的な方法で使用したいと考えています。このようにして、サーブレットで jstl sql タグまたはコンテキスト ルックアップを使用できます。リソースは SQL テーブルに格納されているため、web.xml ファイルで各リソースを定義することはできません。最終結果は、次のような行を持つ単純な 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 から派生した独自の ObjectFactory を作成してみましたが、成功しませんでした。これを簡単に行う方法についての指針はありますか?

4

3 に答える 3

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); 

  }

}

ユーザーがログインしてセッションが作成されるたびに、使用可能な DataSource のリストと現在のデータソースがセッションに配置されます。DataSource はユーザーのログインに依存するため、これはセッション レベルで行われます。アプリケーション内から DataSource にアクセスできるようになりました。現在の DataSource を変更するために、この単純化されたバージョンでサーブレットを作成しました。

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

  }

}

この実装により、次の jsps を作成できるようになりました。

<%@ 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>

それが他の誰かに役立つことを願っています。

于 2009-07-31T15:24:37.343 に答える
1

ServletContextListenerでデータ ソースを作成し、それらをServletContextに配置します。

于 2009-05-31T20:15:48.823 に答える
0

このアプローチは確かに「機能する」でしょうが、各ビジネスに個別の同一のデータベースを使用するという考えは、私には間違っているように思えます。確かに、スキーマのどこかでビジネスを描写することは可能だと思われます。このようにそれらを分離するには、ビジネスごとに新しいデータベースが必要です。スキーマには新しいビジネス ID のみが必要です。

また、別のデータベースの ETL データをアドホックなレポート作成とクエリのためにディメンション キューブに変換しない限り、複数のビジネスにまたがるデータ マイニングの可能性は失われると主張したいと思います。

また、JSTL <sql> タグは、最も単純な Web アプリでのみ使用する必要があります。中間層での検証を無視すると、SQL インジェクション攻撃の可能性にさらされます。

アップデート:

知る限り web.xml でリソースを宣言する必要があるため、新しいデータベースを作成するたびに、アプリケーションを停止し、新しい JNDI ソースを構成して、Tomcat を再起動する必要があります。新しいビジネス/データベースを追加するたびに、以前のすべてのクライアントがアプリのダウンの影響を受けるため、クラスター化されていることを願っています。

于 2009-05-31T20:47:47.403 に答える