You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Tomcat部署WAR包后提交JSP表单出现NullPointerException求助

解决Tomcat部署WAR后表单提交的NullPointerException问题

从你给出的堆栈跟踪和代码来看,核心问题是PreparedStatement对象未正确初始化,导致调用其方法时抛出NullPointerException。下面我会逐一指出代码里的问题,并给出修复后的完整代码:

问题点分析

  1. 变量名不匹配导致PreparedStatement未初始化
    你在BondPay类里定义的PreparedStatement变量是selectActors,但在构造函数里却错误地使用了未定义的selectBond变量,这直接导致selectBond始终为null,后续调用selectBond.setString()时必然抛出空指针。

  2. 代码笔误
    display方法里有一行selectBond多打了一个ssselectBond.setString(3, currency);,这同样会引发错误。

  3. 未处理参数为空的情况
    如果表单提交的amountserialcurrency为空,直接传递给数据库查询可能出现异常,甚至导致空指针。

  4. 数据库资源未关闭
    使用完ConnectionPreparedStatementResultSet后没有关闭,会造成数据库连接资源泄漏,长期运行会影响性能。

  5. ResultSet空指针风险
    如果数据库查询返回null,直接调用res.isBeforeFirst()会再次抛出空指针,需要先做非空判断。


修复后的完整代码

<%@page import="java.sql.*" %>
<%Class.forName("com.mysql.jdbc.Driver") ; %>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>JSP Page</title>
<link href="My Resources/font-awesome/css/fontawesome.css" rel="stylesheet" type="text/css"/>
<link href="My Resources/bootstrap/css/bootstrap.min.css" rel="stylesheet" type="text/css"/>
<script src="My Resources/jquery/jquery-3.4.1.min.js" type="text/javascript"></script>
</head>
<body>
<%! 
public class BondPay {
    private static final String URL = "jdbc:mysql://localhost:3306/bondrepayments?useSSL=false&serverTimezone=UTC";
    private static final String USERNAME = "root";
    private static final String PASSWORD = "root";
    
    private Connection connection;
    private PreparedStatement selectBond;
    private ResultSet resultSet;

    public BondPay(){
        try {
            connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);
            // 修正变量名,与类中定义的selectBond一致
            selectBond = connection.prepareStatement("SELECT * FROM repayments WHERE bond_value= ? AND bond_serial= ? AND currency=?");
        } catch(SQLException e) {
            e.printStackTrace();
        }
    }

    public ResultSet display(String amount, String serial, String currency){
        // 先判断参数是否为空,避免传递null给数据库
        if(amount == null || serial == null || currency == null) {
            return null;
        }
        try {
            selectBond.setString(1, amount);
            selectBond.setString(2, serial);
            // 修正笔误,去掉多余的s
            selectBond.setString(3, currency);
            resultSet = selectBond.executeQuery();
        } catch(SQLException e) {
            e.printStackTrace();
        }
        return resultSet;
    }

    // 添加资源关闭方法,避免资源泄漏
    public void closeResources() {
        try {
            if(resultSet != null) resultSet.close();
            if(selectBond != null) selectBond.close();
            if(connection != null) connection.close();
        } catch(SQLException e) {
            e.printStackTrace();
        }
    }
} 
%>
<%
String currency = request.getParameter("currency");
String serial = request.getParameter("serial");
String amount = request.getParameter("amount");

BondPay bondPaid = new BondPay();
ResultSet res = bondPaid.display(amount, serial, currency); 
%>
<div class="table-responsive">
<table class="table table-striped table-bordered">
<thead>
<tr>
<th><h3>Result</h3></th>
</tr>
</thead>
<tbody>
<tr>
<td><h4>Place of Issue</h4></td>
<td><h4>Bond Serial</h4></td>
<td><h4>Bond Holder Name</h4></td>
<td><h4>Bond Value</h4></td>
<td><h4>Currency</h4></td>
<td><h4>Days</h4></td>
<td><h4>Interest</h4></td>
<td><h4>Principal</h4></td>
<td><h4>Total</h4></td>
<td><h4>Letter Reference</h4></td>
</tr>
<% 
// 先判断ResultSet是否为null,避免空指针
if(res == null || !res.isBeforeFirst()) { 
%>
<div class="alert alert-danger" >
<strong>No records found !</strong>
</div>
<% 
} else {
    while(res.next()) {
%>
<tr>
<td><%= res.getString("location")%></td>
<td><%= res.getString("bond_serial")%></td>
<td><%= res.getString("bond_holder_name")%></td>
<td><%= res.getString("bond_value")%></td>
<td><%= res.getString("currency")%></td>
<td><%= res.getString("days")%></td>
<td><%= res.getString("interest")%></td>
<td><%= res.getString("principal")%></td>
<td><%= res.getString("total")%></td>
<td><%= res.getString("reference")%></td>
</tr>
<% 
    }
}
// 关闭数据库资源
bondPaid.closeResources();
%>
</tbody>
</table>
</div>

额外说明

  • 我在数据库URL里添加了useSSL=false&serverTimezone=UTC,避免MySQL 8.0+版本可能出现的时区和SSL连接问题。
  • 把类中的变量改成了private,并使用static final定义常量,符合Java编码规范。
  • 添加了closeResources()方法,在查询结束后关闭所有数据库资源,避免泄漏。

内容的提问来源于stack exchange,提问作者Daniel W.

火山引擎 最新活动