Несколько динамических источников данных для контекста сервлета - PullRequest
0 голосов
/ 31 мая 2009

Я разрабатываю веб-приложение на основе Java-сервлета, которое управляет информацией из нескольких баз данных (все по структуре одинаковы), каждая из которых соответствует своему «бизнесу». Пользователь выбирает «текущий бизнес», который хранится в сеансе, и приложение может отображать или изменять этот «текущий бизнес».

Я бы хотел использовать ресурсы tomcat динамически, чтобы иметь доступ к этим предприятиям с помощью jndi. Таким образом, я могу использовать теги 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);

где я могу получить правильный источник данных для "текущего бизнеса".

Я экспериментировал с написанием своих собственных ObjectFactories, полученных из javax.naming.spi.ObjectFactory, но безуспешно. Любые указатели о том, как легко это сделать?

Ответы [ 3 ]

2 голосов
/ 31 июля 2009

Я наконец остановился на следующем решении, состоящем из 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); 

  }

}

Всякий раз, когда пользователь входит в систему и создает сеанс, список доступных источников данных и текущий помещаются в сеанс. Это делается на уровне сеанса, поскольку источники данных зависят от входа пользователя в систему. Теперь к ним можно получить доступ из приложения. Чтобы изменить текущий источник данных, я создал сервлет с этой упрощенной версией:

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>

Надеюсь, это поможет кому-то еще.

1 голос
/ 01 июня 2009

Создайте источники данных в ServletContextListener и поместите их в ServletContext .

0 голосов
/ 01 июня 2009

Этот подход, безусловно, будет «работать», но понятие отдельной, идентичной базы данных для каждого бизнеса мне кажется неверным. Конечно, возможность определить бизнес где-то в схеме кажется возможной. Для их разделения требуется новая база данных для каждой компании, где для схемы потребуется только новый бизнес-идентификатор.

Я бы также поспорил, что любая возможность интеллектуального анализа бизнес-данных теряется, если только вы не перенесете данные из отдельных баз данных в одномерный куб для специальных отчетов и запросов.

Теги

и JSTL следует использовать только в самых простых веб-приложениях. Вы отказываетесь от возможности атак с использованием SQL-инъекций, когда отказываетесь от проверки на среднем уровне.

UPDATE:

Вы должны объявить ресурсы в своем файле web.xml AFAIK, поэтому всякий раз, когда у вас появляется новая база данных, вам необходимо остановить приложение, настроить новый источник JNDI и перезапустить Tomcat. Я надеюсь, что вы кластеризованы, потому что все предыдущие клиенты будут зависеть от того, что приложение будет закрываться при каждом добавлении нового бизнеса / базы данных.

...