【问题标题】:What to do when ServletContextListener#contextInitialized() failsServletContextListener#contextInitialized() 失败时该怎么办
【发布时间】:2014-10-28 15:59:35
【问题描述】:

如果假设我将 ServletContextListener#contextInitialized() 中的数据源初始化为:

package com.myapp.listeners;

import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.sql.DataSource;

public class MyAppListener implements ServletContextListener {
    @Override
    public void contextDestroyed(ServletContextEvent event) {
    }

    @Override
    public void contextInitialized(ServletContextEvent event) {
        try{
            InitialContext initialContext = new InitialContext();

            DataSource dataSource = (DataSource) initialContext.lookup("jdbc/myDB");

            event.getServletContext().setAttribute("datasource", dataSource);
        }catch(NamingException ne){
            // TODO WHAT TO DO HERE?
        }
    }
}

那么,如果初始化数据源失败了怎么办?我怎样才能阻止Tomcat部署这个应用程序,因为没有数据源我没有部署应用程序的意义。

【问题讨论】:

标签: java jsp tomcat servlets


【解决方案1】:

数据源应该可以从 JNDI 查找中获得,而不是像这样。我建议您将此代码包装在一个方法中,而不是从 ServletContext 中检索它。

问题:如果初始化数据源失败怎么办?如何防止 Tomcat 部署此应用程序?

contextInitialized 中抛出自定义RuntimeException,应用程序将不会被部署。


从您的数据源检索连接:

//no need to extend from this class
public final class ConnectionProvider {
    private static final String DEFAULT_DS = "jdbc/myDB";
    //no need to initialize this class
    private ConnectionProvider() {
    }
    //retrieve the connection
    public static Connection getConnection() {
        Connection con = null;
        try {
            InitialContext initialContext = new InitialContext();
            DataSource dataSource = (DataSource) initialContext.lookup(DEFAULT_DS);
            con = dataSource.getConnection();
        } catch (Exception e) {
            //handle exception
            //basic handling, you should at least use a logger
            e.printStackTrace();
        }
        return con;
    }
}

然后在你的 Service 类中调用这个静态方法(不是在 Servlets 中,不是在 Dao 中)。

【讨论】:

  • 我不是在为数据源做 JNDI 查找吗?您能否更详细地解释一下,如何从包装代码中检索?
  • 为每个数据库连接需要的数据源进行命名查找不是很昂贵吗?我们不能一次初始化数据源并永远将其用于新的数据库连接吗?
  • @Meraman 这并不昂贵。如果您的应用程序中的成本是 0.005 毫秒,那么是的,它的成本很高,我可以承担风险。
  • 如果它不在毫秒之内怎么办,如果 DB 是 Internet 上的远程服务器,例如 100 毫秒往返时间怎么办?为什么我们不初始化一次数据源,并将其用于所有连接需求?为什么我们要为每个连接查找数据源?
  • @Meraman 我猜你误解了这一点。应用服务器初始化DataSource 并使您能够通过JNDI 访问它。您可以将 JNDI 视为应用程序的小型缓存,其中查找是内存中这个大 Map<String, Object> 的关键。多次调用initialContext.lookup("jdbc/myDB") 不会启动多个DataSource,它将检索1,如果未初始化,它将创建一个并为您提供。你谈论它的时间不是真正的时间。如果您的数据库远离您的网络应用程序,那么您应该考虑另一种架构
猜你喜欢
  • 1970-01-01
  • 2010-09-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多