一. 业务场景
最近,杨哥的一个班级正在做基于JSP+JSTL/EL + Servlet + JavaBean +JDBC +MySQL技术方案的阶段项目。其中有一个需求是根据多条件动态搜索商品信息,最终分页显示出商品列表。这个功能可以在dao层采用多分支条件组合,显示页面使用JSTL/EL中的c:forEach标签 ,再配合EL表达式显示商品的属性信息。
结果在开发实践中,有个学生的商品列表页信息却无法显示出来,服务器控制台直接爆出了一个异常!但他又不知道这个异常该怎么解决,于是就跑来问杨哥。我们在学习的时候,有很多初学者因技术运用不熟练,都会导致一些令人头疼的问题,其实遇到了问题不要怕,我们解决掉就好啦。
那么接下来,杨哥就以此项目中的这个常见异常为例,来带着大家分析项目开发过程中出现异常之后,该如何快速地解决问题。这样以后再遇到类似的问题时,大家就知道该怎么解决了。
二. 异常信息
我们先来看看这个异常是什么。
严重: Servlet.service() for servlet jsp threw exception
javax.el.PropertyNotFoundException: Property 'gname' not readable on type com.qf.pojo.Goods
at javax.el.BeanELResolver$BeanProperty.read(BeanELResolver.java:297)
很多同学在项目开发时,可能都遇到过此类异常。有些同学一看到密密麻麻的英文单词,几乎都不认识,脑袋嗡一下子就炸了。到底哪里出错了?出了什么错?两眼一抹黑,啥也不知道,反正就知道报错了,一下子就不知所措了。
杨哥在这里告诉大家,遇到问题千万不要紧张。如果你的单词量不行,可以使用有道翻译对照查看错误,慢慢积累单词就记住了。其实Java里的常用单词就那么几个,天天看起码知道啥意思,我们也不需要你背写单词对吧。
上面的异常,咱们根据字面意思来理解,就是在使用EL表达式时没有发现Goods类的gname属性的getter方法.......既然现在已经知道了这个错误,那就继续往下看该怎么解决吧!
三.EL表达式使用基本规则
在解决异常之前,杨哥先带领小伙伴们复习一下EL的使用规则。
EL表达式的作用是为了使jsp写起来更加简单,使代码简化;
语法结构:${experssion};
EL表达式一般操作的都是域对象中的数据,但操作不了局部变量;
域对象在jsp中分别是:pageContent,requset,session,application,这可比用page、requset、session、application去获取对象简单太多了;
操作JavaBean对象:直接调用所定义类的方法和属性名,但要注意,必须在类中实现get方法。
四. 原因排查
1.常见原因分析
我们在上面复习了EL表达式的基本使用规则之后,尤其是明白了bean对象的使用要求,你现在是否已经知道上面异常的产生原因是什么了吗?其实控制台里的信息已经把异常原因说的很清楚了:
Property 'gname' not readable on type com.qf.pojo.Goods
这里表示Goods类中的’gname‘属性不能获取。所以杨哥的第一反应就是,这个小伙伴可能忘了给‘gname’属性加getter方法了。于是杨哥直接查看了他的Goods类代码,结果发现类里面setter、getter方法都有:
另外该学员在排查异常时还做了查询结果输出,控制台显示查询的数据也完全正确,没有一点问题。于是,杨哥又在debug模式下打断点运行,也验证了数据响应并没有异常发生。
2. 真正原因所在
那么问题到底出在哪里呢?
于是杨哥再次打开Goods类的源码,仔细阅读了起来。结果发现代码中的getGname方法名称颜色显示发灰。仔细一看,杨哥立刻就明白这家伙错在哪里了。原来,他在写实体时,方法都是手动编写的,在写这个getGname()方法时多设置一个形参。我们知道,getter()方法是不需要带参数的!导致在运行时,系统把这个方法当成了普通方法,也就是说,实际上他并没有真正地’gname‘属性实现其对应的getter()方法。而EL表达式在显示对象属性时,其本质就是要调用其getter方法!
就是这样一个很小的细节,因为学生的粗心导致了上面的绑定错误!
也就是说,上面的异常其实是由一个很小的失误引发的错误!是不是太不应该出现这种错误了呢?而我们很多人在刚开始学习编程时所犯的错误,绝大多数都是因为马虎造成的!
五. 解决办法
其实解决办法很简单,只需要将多余的形参去掉就好了!
六. 总结与反思
本案例中的异常,是因粗心大意导致类的属性没有getter方法引起的错误,这不仅仅引发了PropertyNotFoundException异常,同时也暴露了很多人在学习时存在的一些缺点:
1). 对封装的理解不够深入;2). EL表达式的本质理解较浅;3). debug能力需要提升。