【问题标题】:How to redirect to an error page when database connection fails?数据库连接失败时如何重定向到错误页面?
【发布时间】:2014-02-20 21:25:56
【问题描述】:

我正在尝试在我的应用程序中实现一个功能,例如,在对容器的第一次请求时,如果数据库无法连接,它应该重定向到错误页面而不是显示 index.jsp

  1. 我有一个单例DBConnectionManager 类,它在构造函数中处理数据库连接,也是一个返回连接对象的方法。

  2. 我有一个 servlet 上下文侦听器。所以当上下文初始化时,它会调用DBConnectionManager构造函数并初始化数据库连接。我将在我的所有模型 DAO 中检索并使用相同的连接对象。

现在我的问题是如何处理连接错误并将其从DBConnectionManager 或servlet 上下文侦听器重定向到error.jsp 页面。我应该在哪里放置重定向条件。

供参考: DBConnectionManager.java=>

public DBConnectionManager(String url,String user,String pass)
{
//constructor called by servlet context listener.
this.DBURL=url;
this.user=user;
this.pass=pass;
try {
Class.forName("com.mysql.jdbc.Driver");
}
catch (ClassNotFoundException e) {
log.info("Class Not Found :"+e);
return;
}
try {
log.info("-------url recieved :"+url);
log.info("-------username received :"+user);
log.info("--------password received :"+pass);
con = DriverManager.getConnection(url,user,pass);
log.info("con initialised..");
} 
catch (SQLException e) {
//Exception caught here successfully.
log.info("Problem in connecting :"+e);
return;
}

if (con != null) {
log.info("Connected Successfully to database");
} else {
log.info("Mysql not connected.:<");
}

public Connection getConnection()
{
 //Method called in every DAOmodel to return the instance of the connection object.
 //Where DAO uses this connection object to query database.
return this.con;   
}

我的 Servlet 上下文监听器来了=>

public void contextInitialized(ServletContextEvent servletContextEvent) {
        ServletContext ctx=servletContextEvent.getServletContext();
        String url=ctx.getInitParameter("DBURL");
        String user=ctx.getInitParameter("DBUSER");
        String pass=ctx.getInitParameter("DBPWD");

        //Constructor called here
        DBConnectionManager dbManager= new DBConnectionManager(url,user,pass);
        log.info("printing db manager::"+dbManager);
        ctx.setAttribute("DBManager", dbManager);
        log.info("dbmanager Initialized");

        }

public void contextDestroyed(ServletContextEvent servletContextEvent) {
        ServletContext ctx=servletContextEvent.getServletContext();
        DBConnectionManager dbManager=      (DBConnectionManager)ctx.getAttribute("DBManager");
        dbManager.closeConnection();
        log.info("dbmanager destroyed and database connection closed");
}

如果您对我的问题有任何疑问,希望这可以解决。

【问题讨论】:

    标签: java jsp servlets dao


    【解决方案1】:

    您可以在web.xmllike 中抛出异常并为此类错误定义 500 页;

    <error-page>
        <error-code>500</error-code>
        <location>/error.html</location>
    </error-page>
    

    当您的系统出现错误时,error.html 将被渲染。对于其他类型的错误,你可以定义;

    <error-page>
        <!-- Missing login -->
        <error-code>401</error-code>
        <location>/error-401.html</location>
    </error-page>
    <error-page>
        <!-- Forbidden directory listing -->
        <error-code>403</error-code>
        <location>/error-403.html</location>
    </error-page>
    <error-page>
        <!-- Uncaught exception -->
        <error-code>500</error-code>
        <location>/error-500.html</location>
    </error-page>
    <error-page>
        <!-- Unsupported servlet method -->
        <error-code>503</error-code>
        <location>/error-503.html</location>
    </error-page>
    

    【讨论】:

    • 那将是基于 http 错误的错误。我的问题不同。
    • 你的问题也是基于http的重定向,如果连接时抛出异常,这个结构将重定向你错误页面而不是index.jsp
    • 如果我在 Servlet(Controller) 中有一个 dbconnection 和异常管理代码。我可以配置我的 web.xml 以重定向到某个错误页面。我在模型类下有这个。
    • 好的,您可能在控制器中使用了该模型。如果您在模型上抛出异常,它将被错误页面处理程序捕获。
    【解决方案2】:

    如果你想处理所有 db 异常,你需要把它作为一个 SomeDbException 抛出并添加到web.xml。也可以关注doc

    <error-page>
        <exception-type>SomeDbException</exception-type>
        <location>/error.html</location>
    </error-page>
    

    【讨论】:

    • 如果 servlet 抛出异常,容器会在 web.xml 中查找配置。这里不涉及servlet。 DBConnectionManager 只是一个 java 类(模型)。
    • OK,但是 DBConnectionManager 是从 servlet 调用的,不是吗?因此,您将在DBConnectionManager 中抛出异常,而不是捕获它 enywere 或捕获它并重新抛出另一个异常,结果 servlet 容器会自动将其重定向到配置的页面。
    • 我没有从任何 servlet 调用 DBConnectionManager。我从 ServletContextLister 调用它。
    • 因此您可以在ServletContextListener 中处理异常,将信息添加到ServletContext 属性并在Filter 或Servlet 中读取此信息。见here
    • 是的,但我认为最好在filter 中执行,不要将处理与servlet 逻辑合并。
    【解决方案3】:

    @Prithviraj:答案如下:假设您有Index.jsp 页面,其中连接失败并且您遇到一些异常。 所以在那个页面(Index.jsp)中,你需要使用&lt;%@ page %&gt;指令的errorPage属性。像这样:&lt;%@ page errorPage="Error.jsp %&gt; 而在Error.jsp 页面中,您需要使用&lt;%@ page %&gt; 指令的isErrorPage 属性。 像这样:&lt;%@ page isErrorPage="true" %&gt;。 现在当连接失败并出现异常时会发生什么,然后自动控制将重定向到Error.jsp页面,您不必编写重定向逻辑。

    相信会对你有所帮助。

    【讨论】:

    • 你能说得更具体一点吗?我需要从 index.jsp 页面重定向到 SQLException 上的 error.jsp 页面。如何让 index.jsp 监听 SQLException。
    • 你不必担心,如果出现异常,控制将重定向到error.jsp页面。在 error.jsp 页面上,您将拥有内置的异常对象,因此对于异常类型,您可以使用异常对象。
    【解决方案4】:

    无论哪种错误,您都可以随时重定向到任何其他页面:

    <%
    try {
        // do whatever you want (Connect to database ...)
    } catch(Exception ex) {
        // logging ...
    
        response.sendRedirect(..);
        return;
    }
    %>
    

    更新

    对不起,我对你的问题有点困惑。但是:

    • 如果在 servlet 初始化时发生错误并且您的单音类在其中,请留下此错误,因为应用程序无法启动,并且用户无论如何都应该修复它,您可以生成任何日志以帮助用户找出什么是问题所在!
    • 对于实用程序和一些特殊情况,Singleton 还不错,但对于 Web 应用程序,您应该尽可能避免使用它。如果它对每个用户都是唯一的,您可以创建一个实例并将其放在会话中,如果它在整个系统中是唯一的,则可以将它放在 servlet 上下文中。 getServletContext().setAttribute("my", sample); 希望对您有所帮助

    希望对你有帮助

    【讨论】:

    • 它不是一个 servlet 类。所以我没有使用响应或请求对象。它只是一个单例 java 类。那我怎么能使用 response.sendRedirect();
    猜你喜欢
    • 2013-02-04
    • 2011-02-24
    • 2018-10-02
    • 2015-04-16
    • 2020-01-12
    • 1970-01-01
    • 1970-01-01
    • 2019-10-01
    • 1970-01-01
    相关资源
    最近更新 更多