Tomcat部署WAR包后提交JSP表单出现NullPointerException求助
解决Tomcat部署WAR后表单提交的NullPointerException问题
从你给出的堆栈跟踪和代码来看,核心问题是PreparedStatement对象未正确初始化,导致调用其方法时抛出NullPointerException。下面我会逐一指出代码里的问题,并给出修复后的完整代码:
问题点分析
变量名不匹配导致
PreparedStatement未初始化
你在BondPay类里定义的PreparedStatement变量是selectActors,但在构造函数里却错误地使用了未定义的selectBond变量,这直接导致selectBond始终为null,后续调用selectBond.setString()时必然抛出空指针。代码笔误
在display方法里有一行selectBond多打了一个s:sselectBond.setString(3, currency);,这同样会引发错误。未处理参数为空的情况
如果表单提交的amount、serial或currency为空,直接传递给数据库查询可能出现异常,甚至导致空指针。数据库资源未关闭
使用完Connection、PreparedStatement和ResultSet后没有关闭,会造成数据库连接资源泄漏,长期运行会影响性能。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.




