记录实现ervlet中出现的错误解决方案。
问题描述 在IDEA中使用内置MAVEN插件创建JAVA WEB项目,使用pom.xml配置了 mysql-connector-java、druid、mybatis、servlet、junit4、I/O工具类 commons-io、日志 org.slf4j。
为测试环境配置情况,我写了一个简单的ServletDemo,通过HTTPServlet的 Request 对象获取用户在浏览器页面输入信息并在本地数据库查询验证,通过 Response 对象写入查询结果,作为响应。
在启动Tomcat服务器运行之前,我写了一个测试类,自定义用户输入,直接通过MyBatis查询数据。运行正常且结果符合预期。
然后我启动Tomcat服务器,成功通过浏览器访问自定义的静态登录页面。输入用户名和密码后,单击提交按钮,页面出现如下报错信息。
主要信息:
1 2 3 4 5 6 org.apache.ibatis.exceptions.PersistenceException: ### Error querying database. Cause: java.sql.SQLException: Error setting driver on UnpooledDataSource. Cause: java.lang.ClassNotFoundException: Cannot find class : com .mysql .jdbc .Driver ### The error may exist in com /anthonycj /javaweb2021 /requestdemo /mapper /UserMapper .xml ### The error may involve com .anthonycj .javaweb2021 .requestdemo .mapper .UserMapper .select ### The error occurred while executing a query ### Cause : java .sql .SQLException : Error setting driver on UnpooledDataSource . Cause : java .lang .ClassNotFoundException : Cannot find class : com .mysql .jdbc .Driver
问题分析 注意到异常 java.lang.ClassNotFoundException: Cannot find class: com.mysql.jdbc.Driver,明显是数据库连接出了问题。这里我从以下几个角度开始排查:
MAVEN的 pom.xml 是否配置了正确的依赖
<dependency> 的格式
mysql-connector-java 的版本
mybatis-config.xml 的配置信息是否正确
包映射是否正确
环境配置 <environments> 标签的内容是否正确
连接数据库的参数是否正确、是否要指定时区 useSSL=false&serverTimezone=UTC
注意参数要用转义字符 &,&符号在xml页面有其它语义
参数前后是否有空格
驱动名称、值的名称 <property name="driver" value="com.mysql.jdbc.Driver"/>
登录数据库的用户名、密码是否正确
Java代码是否存在问题
com路径下的mapper接口是否编写正确
resources路径下的Mapper.xml映射文件是否编写正确
Servlet代码是否编写正确
解决方案 最终确定是 mysql-connector-java 的版本问题。需要为MySQL数据库选择匹配版本 的数据库连接驱动。我的MySQL是 8.0.25 版本,最初在 pom.xml 中引入5.1.46版本的连接依赖出现问题,最终引入 8.0.25 版本的依赖坐标后问题解决。引入坐标如下:
1 2 3 4 5 6 7 <dependency > <groupId > mysql</groupId > <artifactId > mysql-connector-java</artifactId > <version > 8.0.25</version > </dependency >
总结-碎碎念 解决这个小bug花费了我14个小时的时间,让我很崩溃。
首先,我在出现问题的第一时间就联想到了mysql连接驱动的版本问题,也在第一时间就做了修改,使用了 mysql 8.0.15 版本的驱动进行连接,但还是连接失败,服务器返回 Status 500,经过短暂分析:“这个驱动的向后兼容性不可能做的这么差,8.0.15版本都不行,那 8.0.25 版本肯定也不行,所以应该不是驱动版本的问题”,这让我直接排除了这个正确的错误原因,导致我在debug的路上一去不复返!!!
然后,我检查代码,检查配置,编写测试类测试连接…
离谱的是我在测试类里可以正常连接数据库、但一使用Tomcat就无法连接数据库,和出错的状态只差没启动Tomcat服务器、没在Servlet中运行同样的代码 。
其次,我开始怀疑是IDEA或者MAVEN插件的问题,我在各种位置 导入本地的 mysql-connector jar包,分别在项目、模块、包下创建lib目录,仍然连接失败。
再次,我以为是拼写问题,所以我重写了所有的代码 ,包括xml配置文件、依赖坐标、Servlet类… 仍然是测试类能跑,服务器连接失败。
我在Google 搜索解决方案,在StackOverflow 搜索解决方案,基本上都是一些低级错误(如配置文件拼写错误、前后有空格等),与我的情况不一致。
最后,我没办法了,在CSDN【狗都不看】上找到了一条好几个赞 解决方案,说什么要把 连接驱动jar包 扔到Tomcat的lib目录下 ,我一想这不是手动造异常呢?但我看这么多个赞 ,下面还有评论说亲测有用 ,走投无路的我只能试一下,果然不出所料,这个模块(就是我重写的项目模块)直接在密密麻麻的日志异常中彻底崩溃 ,再也无法启动 。(那几个在下面点赞评论说有用的,我……)
我只能再次新建了一个模块,把环境重搭了一遍,那时候天都快亮了。
已经不能再往后了,我已经一点办法都没有了,所以准备重新过一遍之前的错误选项,更换连接驱动版本至 8.0.25,莫名其妙地解决问题。这时候我很懵,因为我记得昨天第一步尝试的就是更换驱动版本,而且记忆犹新——解决失败,然后我很不信邪地切换版本至 8.0.15,居然能跑?!
所以本次debug的过程就是南辕北辙【且思路清晰、意志坚定】,中间还有好心的CSDN网友提供热心帮助,万幸的是最终问题解决。
……
附:正确的配置文件
pom.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 <?xml version="1.0" encoding="UTF-8"?> <project xmlns ="http://maven.apache.org/POM/4.0.0" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" > <modelVersion > 4.0.0</modelVersion > <groupId > org.example</groupId > <artifactId > request-demo</artifactId > <version > 1.0-SNAPSHOT</version > <packaging > war</packaging > <properties > <maven.compiler.source > 8</maven.compiler.source > <maven.compiler.target > 8</maven.compiler.target > </properties > <dependencies > <dependency > <groupId > mysql</groupId > <artifactId > mysql-connector-java</artifactId > <version > 8.0.25</version > </dependency > <dependency > <groupId > com.alibaba</groupId > <artifactId > druid</artifactId > <version > 1.1.12</version > </dependency > <dependency > <groupId > org.mybatis</groupId > <artifactId > mybatis</artifactId > <version > 3.5.5</version > </dependency > <dependency > <groupId > junit</groupId > <artifactId > junit</artifactId > <version > 4.13</version > <scope > test</scope > </dependency > <dependency > <groupId > org.apache.tomcat.maven</groupId > <artifactId > tomcat7-maven-plugin</artifactId > <version > 2.2</version > </dependency > <dependency > <groupId > javax.servlet</groupId > <artifactId > javax.servlet-api</artifactId > <version > 3.1.0</version > <scope > provided</scope > </dependency > <dependency > <groupId > commons-io</groupId > <artifactId > commons-io</artifactId > <version > 2.6</version > </dependency > <dependency > <groupId > org.slf4j</groupId > <artifactId > slf4j-simple</artifactId > <version > 1.6.6</version > </dependency > </dependencies > <build > <resources > <resource > <directory > src/main/resource</directory > <includes > <include > **/*.properties</include > <include > **/*.xml</include > </includes > <filtering > true</filtering > </resource > <resource > <directory > src/main/java</directory > <includes > <include > **/*.properties</include > <include > **/*.xml</include > </includes > <filtering > true</filtering > </resource > </resources > </build > </project >
mybatis-config.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd" > <configuration > <typeAliases > <package name ="com.anthonycj.javaweb2021.requestdemo.pojo" /> </typeAliases > <environments default ="development" > <environment id ="development" > <transactionManager type ="JDBC" /> <dataSource type ="POOLED" > <property name ="driver" value ="com.mysql.jdbc.Driver" /> <property name ="url" value ="jdbc:mysql://localhost:3306/db1?useSSL=false& useServerPrepStmts=true" /> <property name ="username" value ="root" /> <property name ="password" value ="123456" /> </dataSource > </environment > </environments > <mappers > <package name ="com.anthonycj.javaweb2021.requestdemo.mapper" /> </mappers > </configuration >