Несколько динамических источников данных для контекста сервлета

StackOverflow https://stackoverflow.com/questions/932625

  •  06-09-2019
  •  | 
  •  

Вопрос

Я разрабатываю веб-приложение 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);

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

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

Это было полезно?

Решение

В конце концов я остановился на следующем решении, состоящем из SessionListener и сервлета, которые работают следующим образом.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>

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

Другие советы

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

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

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

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

ОБНОВЛЯТЬ:

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top