使用Servlet执行展示类JSP页面时出现NullPointerException问题求助
问题根因
你遇到的NullPointerException(空指针异常)有直接触发原因,同时代码中还存在多处其他语法和逻辑错误,汇总如下:
- 直接触发空指针的问题:Servlet第20行代码
if(a.equals("view"))中,变量a是从请求参数ac获取的值,如果请求没有携带ac参数,a就会为null,调用null的equals方法直接抛出空指针。 - 数据库连接URL语法错误:
DriverManager.getConnection的第一个参数URL写错,多了引号和逗号,正确格式为jdbc:mysql://ip:端口/库名,你写的"jdbc:mysql://75.20.205.173:3306/,"contact"属于语法错误,会导致连接创建失败。 - PreparedStatement参数索引错误:你的查询SQL
select * from user where username=?只有1个占位符,参数索引从1开始计数,你写的ps.setString(13,username)填了索引13,会直接抛出参数越界异常。 - JSP页面语法不规范:头标签结束后重复写了一次
<html>标签,同时字符集配置为ISO-8859-1,会导致中文显示和传参乱码。 - 数据库资源未释放:Connection、PreparedStatement、ResultSet使用后没有关闭,会造成数据库连接泄漏。
修复代码
1. 修复后JSP代码
<%@ page language="java" contentType="text/html; charset=UTF-8" isELIgnored="false" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>View Profile</title> </head> <body> <form action="ProfileServlet" method="get"> <input type="hidden" name="ac" value="view"> Enter your username:<input type="text" name="username"><br/> <input type="submit" value="Submit"> </form> </body> </html>
说明:修正了重复的html标签,字符集换成UTF-8,把ac参数放到hidden表单里更规范,避免URL拼接错误。
2. 修复后Servlet代码
package com.Webhtml.controller; import java.io.IOException; import java.io.PrintWriter; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class ProfileServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); String a = request.getParameter("ac"); // 常量放equals前面,避免空指针 if(!"view".equals(a)) { out.print("请求参数错误"); out.close(); return; } String username = request.getParameter("username"); if(username == null || username.trim().isEmpty()) { out.print("用户名不能为空"); out.close(); return; } Connection con = null; PreparedStatement ps = null; ResultSet rs = null; try{ Class.forName("com.mysql.jdbc.Driver"); // 修正数据库连接URL con = DriverManager.getConnection("jdbc:mysql://75.20.205.173:3306/contact","root","root"); ps = con.prepareStatement("select * from user where username=?"); // 修正参数索引为1 ps.setString(1, username); rs = ps.executeQuery(); out.print("<table width=50% border=1>"); out.print("<caption>Result:</caption>"); ResultSetMetaData rsmd = rs.getMetaData(); int total = rsmd.getColumnCount(); out.print("<tr>"); for(int i=1;i<=total;i++) { out.print("<th>"+rsmd.getColumnName(i)+"</th>"); } out.print("</tr>"); while(rs.next()) { out.print("<tr>"); for(int i=1;i<=total;i++) { out.print("<td>"+rs.getObject(i)+"</td>"); } out.print("</tr>"); } out.print("</table>"); } catch (Exception e2) { e2.printStackTrace(out); } finally { // 依次关闭资源,避免泄漏 try {if(rs!=null) rs.close();} catch (Exception e) {} try {if(ps!=null) ps.close();} catch (Exception e) {} try {if(con!=null) con.close();} catch (Exception e) {} out.close(); } } }
说明:
- 把equals的常量放前面,彻底避免空指针
- 增加了参数非空校验,提前拦截非法请求
- 修正了数据库连接URL、PreparedStatement参数索引
- 增加了数据库资源的关闭逻辑
- 遍历结果集用循环代替硬编码索引,避免表结构变更导致报错
- 统一设置请求响应的字符集为UTF-8,避免乱码
内容的提问来源于stack exchange,提问作者iika-
相关产品推荐
相关产品推荐

