我正在开发一个java servlet Web应用程序,它管理来自多个数据库的信息(所有结构都相同),每个数据库对应一个不同的“业务”。用户选择存储在会话中的“当前业务”,并且应用程序可以显示或修改该“当前业务”。
我想以动态的方式使用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>
或可以包含这些行的servlet
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的ObjectFactories但没有成功。关于如何轻松做到这一点的任何指示?
答案 0 :(得分: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列表和当前的列表都会被放入会话中。这是在会话级别完成的,因为DataSources依赖于用户登录。现在可以从应用程序中访问它们。要更改当前的DataSource,我使用这个简化版本创建了一个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
}
}
通过此实现,现在可以创建以下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 :(得分:1)
在ServletContextListener中创建数据源并将其放在ServletContext。
中答案 2 :(得分:0)
这种方法肯定会“有效”,但对于每个企业来说,单独的,相同的数据库的概念对我来说似乎是错误的。当然,能够在架构中的某个地方划分业务似乎是可能的。以这种方式分离它们需要每个企业使用一个新的数据库,其中模式只需要一个新的业务标识符。
我还认为,除非您将来自不同数据库的ETL数据转换为用于临时报告和查询的维度多维数据集,否则任何跨业务数据挖掘的可能性都将丢失。
和JSTL&lt; sql&gt;标签只应在最简单的Web应用程序中使用。当你放弃在中间层进行验证时,你会对SQL注入攻击的可能性持开放态度。
更新:
您必须在web.xml AFAIK中声明资源,因此每当您拥有一个新数据库时,您必须停止该应用程序,配置新的JNDI源,然后重新启动Tomcat。我希望你是集群的,因为每次添加新的业务/数据库时,所有以前的客户都会受到应用程序关闭的影响。