getParameter()接收参数报错NullPointerException

在使用getParameter()接收前端表单数据时遭遇NPE错误,经排查发现是由于参数名后多了一个空格,导致匹配失败。本文详细记录了从问题初现到最终解决的心路历程。

一个空格引发的“惨案”

前期(我明明在表单里填数据了,为啥会是NPE呢)

在用getParameter()接收前端表单传过来的数据时报错NPE,刚好这个报错的地方是BigDecimal类型,我是第一次用这个类型,第一感觉是没用过这个类型,可能是String转BigDecimal时出错了,然后尝试强制转换,各种谷歌,连stackover的英文我都忍着看了!but,大约花了1h都没有解决,然后又搜索前端页面,怀疑是不是因为这个number类型的锅,然后导致了在各种String,BigDecimal,number转换的时候出了问题。尝试着找了一下里面到底是什么类型,但是又没有搞明白(其实前端我也是渣渣,哈哈哈)。

总之就是前期把重点放在了各种类型,以及类型转换上面,因为我在测试的时候前端的表单里我确实是填数据了,而且还尝试了int,double等各种类型,因为我填了数据,所以就忽略了数据是否真的传过来了的问题。而且报错是NPE,所以我就很不理解,我明明填数据了,为啥会是NPE呢。

中期(发现问题所在)

后来一位群友发现了我在接收参数的时候后面多了一个空格!附上聊天截图,对我而言简直就是段“艰辛的奋斗史”
代码
在这里插入图片描述
经过测试之后发现,确实为空了
在这里插入图片描述

后期(探索问题本质)

好吧,这下找到问题了,但是为啥会为空呢,字符串后面加个空格就变为null了吗,我还特地测试了一下
在这里插入图片描述
发现,就算是字符串后面加个空格也是原样输出啊,为啥这里就算空呢?一番搜索无果后决定去看一下getParameter的官方api文档
在这里插入图片描述
连英文带翻译的看了一下,似乎没有我想要的答案,官方api都没有找到答案,难不成我要去看一下源码?看一下底层是怎么实现的?emmm,怎么有种我是大神的感觉,手动笑哭。后来还是万能的群友,一语惊醒梦中人!

在这里插入图片描述
在这里插入图片描述
我一直以为它会接收的值会是 “参数+空格”,没想到是去匹配“参数+空格”了,没有这个值,所以结果为空,终于搞懂了这个问题。
总之,还是要多动手,多写,遇到问题了多思考,我以前刷视频不少,但是没有咋动手写过,还是要多动手写才行。

后续

好奇心又让我把前端里的名称后面加了一个空格,这样看看能不能匹配到,第一次重启tomcat后还是Null,群友提示看了一下网页源代码,名称后面并没有空格,又重启了一次后可以匹配到数据了。网页源代码名称后面也多了一个空格。
在这里插入图片描述

结合报错原因异常报告 消息 在 [45] 行处理 [/living/edit.jsp] 时发生异常 描述 服务器遇到一个意外的情况,阻止它完成请求。 例外情况 org.apache.jasper.JasperException: 在 [45] 行处理 [/living/edit.jsp] 时发生异常 42: disabled:绂佺敤鍏冪礌锛堟暟鎹笉浼犺緭锛� 43: readonly:鍙锛堜笉鑳界紪杈戯紝鍙互浼犺緭锛� 44: --%> 45: <input disabled value="<%=rs.getString("appliance_type")%>" id="appliance_type" name="appliance_type" type="text"> 46: </div> 47: <div class="form-item"> 48: <label for="password">瀵嗙爜锛�</label> Stacktrace: org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:610) org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:489) org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:376) org.apache.jasper.servlet.JspServlet.service(JspServlet.java:324) javax.servlet.http.HttpServlet.service(HttpServlet.java:623) org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) 根本原因。 javax.servlet.ServletException: java.sql.SQLException: Illegal operation on empty result set. org.apache.jasper.runtime.PageContextImpl.handlePageException(PageContextImpl.java:654) org.apache.jsp.living.edit_jsp._jspService(edit_jsp.java:228) org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:67) javax.servlet.http.HttpServlet.service(HttpServlet.java:623) org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:466) org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:376) org.apache.jasper.servlet.JspServlet.service(JspServlet.java:324) javax.servlet.http.HttpServlet.service(HttpServlet.java:623) org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) 根本原因。 java.sql.SQLException: Illegal operation on empty result set. com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:130) com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:98) com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:90) com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:64) com.mysql.cj.jdbc.result.ResultSetImpl.checkRowPos(ResultSetImpl.java:528) com.mysql.cj.jdbc.result.ResultSetImpl.getString(ResultSetImpl.java:874) com.mysql.cj.jdbc.result.ResultSetImpl.getString(ResultSetImpl.java:892) org.apache.jsp.living.edit_jsp._jspService(edit_jsp.java:156) org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:67) javax.servlet.http.HttpServlet.service(HttpServlet.java:623) org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:466) org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:376) org.apache.jasper.servlet.JspServlet.service(JspServlet.java:324) javax.servlet.http.HttpServlet.service(HttpServlet.java:623) org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)修改<%@ page import="util.DbConnet" %> <%@ page import="java.sql.ResultSet" %> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <% //功能:通过编号获取用户要编辑的具体数据 //1.接收传过来的编号 String id = request.getParameter("appliance_id"); //通过编号执行查询 String sql = "select * from `living_room_appliances` where `appliance_id`=?;"; Object[] params = new Object[]{ id }; ResultSet rs = DbConnet.select(sql, params);//真正执行查询,获得查询结果的数据集 //验证查询结果是否有数据(处理的是无数据情况) if(!rs.next()) response.sendRedirect("list.jsp"); %> <html> <head> <title>编辑用户</title> <link rel="stylesheet" href="../css/common.css"> <link rel="stylesheet" href="../css/add.css"> </head> <body> <%--编辑: 1.点击编辑按钮,打开一个页面 2.新编辑页面需要包含: (1)表单 (2)输入框:账号、密码、确认密码、姓名 (3)按钮:保存(提交)、重置、返回 3.功能: 保存(提交):无刷新提交表单中的所有数据 重置:还原表单中的内容为初始状态 返回:重新打开列表页面(list.jsp) --%> <header> <div class="title">编辑用户</div> </header> <div class="main"> <form id="editForm"> <input type="hidden" name="appliance_id" value="<%=id%>"> <div class="form-item"> <label for="appliance_type">账号:</label> <%-- disabled:禁用元素(数据不传输) readonly:只读(不能编辑,可以传输) --%> <input disabled value="<%=rs.getString("appliance_type")%>" id="appliance_type" name="appliance_type" type="text"> </div> <div class="form-item"> <label for="password">密码:</label> <input value="<%=rs.getString("password")%>" id="password" name="password" type="password"> </div> <div class="form-item"> <label for="cmfPsw">确认密码:</label> <input value="<%=rs.getString("password")%>" id="cmfPsw" name="cmfPsw" type="password"> </div> <div class="form-item"> <label for="appliance_name">姓名:</label> <input value="<%=rs.getString("appliance_name")%>" id="appliance_name" name="appliance_name" type="text"> </div> <div class="form-item"> <button class="primary" id="btnSubmit" type="button">保存</button> <button type="reset">重置</button> <button id="btnBack" type="button">返回</button> </div> </form> </div> <script src="../js/jquery-3.5.1.min.js"></script> <script src="../js/common.js"></script> <script> //绑定保存按钮的点击事件 $('#btnSubmit').on('click', function () { //1.验证不能为空:账号、密码、姓名 if(!checkInputIsNull('#appliance_type','账号')) return false; if(!checkInputIsNull('#password','密码')) return false; //比较两次输入的密码是否一致 let cmfPswObj = $('#cmfPsw'); if($('#password').val() !== cmfPswObj.val()){ alert("两次输入的密码不一致");//提示 cmfPswObj.val('').focus();//清空确认密码的内容,并设置确认密码输入框获得焦点 return false;//停止往下执行 } if(!checkInputIsNull('#appliance_name','姓名')) return false; //2.无刷新提交数据 postAction("/living/edit", $('#editForm').serialize(),function (res) { //1.弹出提示信息 alert(res.msg); //2.成功后返回列表页面(list.jsp) if(res.result) window.location.href = res.url; }); }); //绑定返回按钮的点击事件 $('#btnBack').on('click', function () { if(confirm("确定要返回吗?")){ window.location.href='list.jsp'; } }); </script> </body> </html>
07-06
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值