我在 Tomcat 6 上在 context.xml 中将 DataSource 配置为 MyDataSource。我通过以下方式获取它:
DataSource dataSource;
try {
dataSource = (DataSource) new InitialContext().lookup("java:comp/env/MyDataSource");
} catch (NamingException e) {
throw new DaoConfigurationException(
"DataSource '" + url + "' is missing in JNDI.", e);
}
一切正常。现在我将此代码导出到 Jboss AP 6。我将我的数据源及其连接池配置为同名的本地 tx 数据源。
当我执行上面的代码时,我收到 NamingException 异常。经过一番调查,我发现在 Jboss 下调用我的 DataSource 的正确方法是
dataSource = (DataSource) new InitialContext().lookup("java:/MyDataSource");
谁能解释一下为什么我应该在 Jboss 下的 JNDI 路径中省略“comp/env”?
定义数据源的可移植方法是使用资源引用。资源引用使您能够相对于应用程序命名上下文 (
java:comp/env
)定义数据源的 JNDI 名称,然后将该逻辑引用映射到应用程序服务器中定义的物理资源,其 JNDI 名称是应用程序服务器供应商专有的。这种方法使您的代码和程序集可以移植到任何兼容的应用程序服务器。步骤 1:声明和查找资源引用
选项1
这可以通过
resource-ref
在 Web 部署描述符 (WEB-INF/web.xml
) 中声明 a 来完成:在您的代码中,您可以使用 JNDI 名称查找此资源
java:comp/env/jdbc/MyDataSource
:dataSource = (DataSource) new InitialContext().lookup("java:comp/env/jdbc/MyDataSource");
无论应用程序部署在哪个服务器上,此 JNDI 名称都不会更改。
选项 2
或者,从 Java EE 5 (Servlet 2.5) 开始,可以使用
@Resource
注释在您的代码中更轻松地完成此操作。这消除了在 Web 部署描述符 (web.xml) 中配置资源引用的需要,并防止需要执行显式 JNDI 查找:public class MyServlet extends HttpServlet { @Resource(name = "jdbc/MyDataSource") private DataSource dataSource; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // dataSource may be accessed directly here since the container will automatically // inject an instance of the data source when the servlet is initialized }
此方法具有与前一个选项相同的结果,但减少了程序集中的样板代码和配置。
步骤 2:将资源引用映射到数据源
然后,您需要使用应用程序服务器的专有方法将资源引用映射到您在服务器上创建的物理数据源,例如,使用 JBoss 的自定义部署描述符 (
WEB-INF/jboss-web.xml
):<?xml version="1.0" encoding="UTF-8"?> <jboss-web> <resource-ref> <res-ref-name>jdbc/MyDataSource</res-ref-name> <res-type>javax.sql.DataSource</res-type> <jndi-name>java:/MyDataSource</jndi-name> </resource-ref> </jboss-web>
或者,例如,使用 Tomcat 的
context.xml
:<Resource name="jdbc/MyDataSource" . . . />