3

我是学习 JSP 和 Servlet 的新手。我有一个 Java 类,它调用一个存储过程并从数据库返回一个状态列表(这是我学习时的测试用例,其他更复杂的操作稍后会出现)。状态列表应该返回到 JSP 以在表单中显示/使用,等等。现在,我很高兴通过 JSP 页面打印数据以知道它在那里。

但是,当我从 JSP 调用 Java 代码时,结果对象似乎返回为 null,因此无法访问任何数据。我也尝试将数据作为 ResultSet 对象返回,但结果是一样的。我确实知道从 SQL 调用存储过程时有效。此外,我将 Java 代码作为响应 doPost 请求的 servlet 并且工作正常......

我可能会错过/无法理解什么?这可能吗?

package edu.XXXX.ais.userapp;

import java.sql.*;
import java.util.*;

public class DBQueries {

    public static Vector<String> getStatesList() {
        Vector<String> results = new Vector<String>();
        Connection con = null;  
        try {

            // Example of executing a stored procedure
            Class.forName("com.mysql.jdbc.Driver");
            con = DriverManager.getConnection ("jdbc:mysql://hostname:3306/dbName","username","password");
            CallableStatement cs = con.prepareCall("{call getStatesList()}");
            ResultSet rs = cs.getResultSet();

            while (rs.next()) {
                results.add(rs.getString(1));
            }
        } catch (SQLException e) {
            System.err.println("Servlet could not display records." + e);

        } catch (ClassNotFoundException e) {
            System.err.println("JDBC driver not found." + e);

        } finally {
            try {
                if (con != null) {
                    con.close();
                    con = null;
                }

            } catch (SQLException e) {
                System.err.println(e);
            }
        }
        return results;
    }
}

调用上述Java代码的JSP页面(期望能收到结果...)

<html>
<head>
<title>Foo</title>
</head>

<body>
<h3>List of states via a servlet call to the database</h3>
<%@ page import="java.util.*" %>
<%@ page import="edu.XXXX.ais.userapp.DBQueries" %>

<%
    Vector rs = DBQueries.getStatesList();
    if (rs != null)
        for (int index = 0; index < rs.size(); index++) {
            out.println("Name : " + (String) rs.get(index));
        }
%>

</body>
</html>

产生的Tomcat错误如下:

org.apache.jasper.JasperException: An exception occurred processing JSP page /states.jsp at line 12

9: <%@ page import="edu.XXXX.ais.userapp.DBQueries" %>
10: 
11: <%
12:     Vector rs = DBQueries.getStatesList();
13:     if (rs != null)
14:         for (int index = 0; index < rs.size(); index++) {
15:             out.println("Name : " + (String) rs.get(index));


Stacktrace:
    org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:568)
    org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:470)
    org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:390)
    org.apache.jasper.servlet.JspServlet.service(JspServlet.java:334)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
root cause

java.lang.NullPointerException
    edu.XXXX.ais.userapp.DBQueries.getStatesList(Unknown Source)
    org.apache.jsp.states_jsp._jspService(states_jsp.java:75)
    org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
    org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:432)
    org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:390)
    org.apache.jasper.servlet.JspServlet.service(JspServlet.java:334)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
4

4 回答 4

5

异常告诉您在哪里查看:

edu.XXXX.ais.userapp.DBQueries.getStatesList(Unknown Source)

该方法中有一个空引用。我建议在没有 JSP 的情况下进行测试并使用调试器。

你没有关闭你的Statementor ResultSet。那会导致悲伤。以相反的创建顺序关闭它们,就像你做Connection.

对于初学者,请停止将 scriptlet 代码放入您的 JSP 中。那是 1999 年的风格;不要这样做。

正确的做法是学习 JSTL,只让你的 JSP 做显示任务。

让 JSP 与代表它与数据库进行调解的 servlet 对话。

使用应用服务器设置数据源。您的代码中不应包含连接信息。

暂时忘记 servlet 和 JSP。从数据层开始。

使用 POJO 编写,测试它,让它工作,然后把它放在一边。

然后编写一个接收 HTTP 请求的 servlet,验证并绑定参数,使用您的数据访问层与数据库通信,然后将响应放入请求或会话范围以显示页面。

它被称为 Model-2 MVC。这就是编写 Java Web 应用程序的方式。

我会写 DBUtils 类的东西更像这样:

package edu.XXXX.ais.userapp;

import java.sql.*;
import java.util.*;

public class DBQueries {

    public static List<String> getStates(Connection connection) throws SQLException {
        List<String> states = new ArrayList<String>();
        CallableStatement cs = null;
        ResultSet rs = null;
        try {
            cs = connection.prepareCall("{call getStatesList()}");
            boolean hasResultSet = cs.execute();
            rs = cs.getResultSet();    
            while (rs.next()) {
                states.add(rs.getString(1));
            }
        } finally {
            close(rs);
            close(cs);
        }
        return states;
    }

    public static void close(ResultSet rs) {
        try {
            if (rs != null) {
                rs.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public static void close(Statement st) {
        try {
            if (st != null) {
                st.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public static void close(Connection conn) {
        try {
            if (conn != null) {
                conn.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

编写一个 JUnit 测试来证明您的 DBQueries 有效:

package edu.XXX.ais.userapp;

public class DBQueriesTest {

    // You have to initialize this; I'm deliberately leaving out some details.
    private Connection connection;

    @Test
    public void testGetStates() {
        List<String> actual = DbQueries.getStates(this.connection);
        List<String> expected = { "CT", "NY" };  // whatever
        Assert.assertEquals(expected, actual);
    }
}
于 2012-06-19T23:53:56.717 回答
2

在您的示例代码中,CallableStatement之前未执行cs.getResultSet(),因此rs将为空,然后NullPointerException将在执行时发生rs.next()

CallableStatement cs = con.prepareCall("{call getStatesList()}");
boolean bIsResultSetOrNot = cs.execute (); // <-- missed
ResultSet rs = cs.getResultSet(); 

确保语句被执行,并确保执行结果ResultSet不是更新计数。

于 2012-06-20T00:58:39.257 回答
0

异常堆栈跟踪显示您在方法 DBQueries.getStatesList() 中有一个空指针。用 Exception 包围方法中的 try 块,并尝试查看是哪一行抛出它。我的猜测是 Connection 对象为空。

如果这是真的,请检查您在获取连接时传递的“主机名”的值。

于 2012-06-19T23:57:14.250 回答
0

您正在尝试将字符串向量传递给向量。你的方法是Vector<String> getStatesList()你正在参考一个NULL.

进入 ../Apache Tomcat/webapps/work 找到你编译的 JSP 类。看看那些 JSP 行中的错误。

请使用 Spring Core JDBCTemplate 类建立与数据库的连接,对于那些忘记关闭连接的人来说,这是一个非常好的类。:) 好的

于 2012-06-20T00:04:23.543 回答