如何轻松调用java类(查询数据库)并将可用结果返回给JSP?

doc*_*ale 3 java jsp servlets

我是学习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;
    }
}
Run Code Online (Sandbox Code Playgroud)

调用上述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>
Run Code Online (Sandbox Code Playgroud)

产生的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)
Run Code Online (Sandbox Code Playgroud)

duf*_*ymo 5

该异常会告诉您在哪里查看:

edu.XXXX.ais.userapp.DBQueries.getStatesList(Unknown Source)
Run Code Online (Sandbox Code Playgroud)

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

你没有关闭你的StatementResultSet.这将导致悲伤.按照与创建相反的顺序关闭它们Connection.

首先,请停止在JSP中添加scriptlet代码.这是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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

编写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);
    }
}
Run Code Online (Sandbox Code Playgroud)