一 问题综述
首先自己写了一个网站页面
<form action="add" method="post"> 名称:<input type="text" name="fname"/><br/> 价格:<input type="text" name="price"/><br/> 库存:<input type="text" name="fcount"/><br/> 备注:<input type="text" name="remark"/><br/> <input type="submit" value="添加"> </form>
就是很简单的填写表单然后提交
后台会收到提交的数据,new一个Fruits类出来并打印
打印结果如下
说明servlet接收数据正常
接着写了一个FruitsDAOImpl 在本地经过FruitsDAOImplTest测试后正常,于是准备把这个数据写进数据库
但是在这里遇到了问题 问题为描述为:无法将数据写进数据库,并且在try-catch中打印异常轨迹时发现空指针异常,开始排查问题
二 解决过程
经过一番sout+断点测试,发现是
Connection conn = JDBCUtills.getConnection();
获取连接出现问题,这里并没有返回该有的连接,而是返回null
接着看getConnection方法中的问题
经过sout测试,发现
InputStream resourceAsStream = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties");
这里的resourceAsStream打印出来是null,得结论获取inputstream流失败,
经过搜索在https://blog.csdn.net/qq_32661351/article/details/107843220得到解决
将上述代码改为
InputStream resourceAsStream = JDBCUtills.class.getClassLoader().getResourceAsStream("jdbc.properties");
其中JDBCUtills是自己定义的工具类
public class JDBCUtills { public static Connection getConnection() { Connection conn = null; PreparedStatement ps = null; try { InputStream resourceAsStream = JDBCUtills.class.getClassLoader().getResourceAsStream("jdbc.properties"); System.out.println(resourceAsStream); Properties prop = new Properties(); prop.load(resourceAsStream); String user = prop.getProperty("user"); String password = prop.getProperty("password"); String url = prop.getProperty("url"); String driver = prop.getProperty("driver"); Class.forName(driver); conn = DriverManager.getConnection(url, user, password); } catch (Exception e) { e.printStackTrace(); } return conn; } public static void closeResource(Connection conn, Statement ps) { try { if(ps != null) ps.close(); } catch (SQLException throwables) { throwables.printStackTrace(); } try { if(conn != null) conn.close(); } catch (SQLException throwables) { throwables.printStackTrace(); } } public static void closeResource(Connection conn, Statement ps,ResultSet rs) { try { if(ps != null) ps.close(); } catch (SQLException throwables) { throwables.printStackTrace(); } try { if(conn != null) conn.close(); } catch (SQLException throwables) { throwables.printStackTrace(); } try { if(rs != null) rs.close(); } catch (SQLException throwables) { throwables.printStackTrace(); } } }View Code
再打印resourceAsStream,结果正常输出为java.io.ByteArrayInputStream@440b815d的流
本以为问题已经结束了,返回到servlet中重新将数据插入数据库,发现还是失败,
于是继续排错,发现还是获取connection的时候失败
异常报错为:空指针异常和java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
同样搜索在https://blog.csdn.net/qq_20916555/article/details/49614621后解决
解决方法是把mysql-connector-java-8.0.11.jar的jar包放到:web(你的web项目文件夹名)/WEB-INF/lib下
注意:如果WEB-INF下没有lib文件夹,需要自己创建
三 问题分析
因为是第一次部署在服务器上,所以本地测试环境和tomcat构造的容器环境不同的问题没有考虑到,这里一共有两个问题:
1、当使用ClassLoader.getSystemClassLoader().getResourceAsStream(“jdbc.properties“);时报空指针异常
原因:这个问题是因为ClassLoader.getSystemClassLoader() 获得是AppClassLoader,但是tomcat 用的是WebappClassLoader(打破双亲委派),你想从appClassLoader 实例上获取WebappClassLoader 上的资源是获取不到的(来自https://blog.csdn.net/qq_32661351/article/details/107843220的评论)
2、java.lang.ClassNotFoundException: com.mysql.jdbc.Driver异常
原因:这个问题是因为服务器端Web容器在构建servlet的时候找不到数据库的驱动类,导致服务器连接失败(来自https://blog.csdn.net/qq_20916555/article/details/49614621)