熬了整整3天,靠着不解决不罢休的精神,终于把这个问题解决了。期间看了很多资料,网上的资料大部分抄来抄去,有用的太少,真正用到的就那么几篇文章,本想把这几篇文章链接贴上来,但一看浏览的历史记录太多了,懒得一个个去找了。归根到底还是自己太水,基本功不扎实。希望能帮到你。
问题背景:一个项目(WEB-INF目录下有lib文件夹,存放一部分第三方jar包【后面出的问题之一与这个有关】)在我本机(window7+JDK1.8+Tomcat8)上运行正常,部署到一台阿里云服务器(centos7.4+JDK1.8+Tomcat8)上后,访问项目地址报404错误,查看日志显示如下警告(重要的三个地方已标红):
WARNING [localhost-startStop-1] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesJdbc The web application [] registered the JDBC driver [com.alibaba.druid.proxy.DruidDriver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.
WARNING [localhost-startStop-1] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesJdbc The web application [] registered the JDBC driver [com.mysql.jdbc.Driver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.
WARNING [localhost-startStop-1] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [] appears to have started a thread named [Abandoned connection cleanup thread] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
意思网上解释的很清楚:就是上一次程序结束的时候,没有注销数据库驱动,重新启动后,为防止内存泄露,不允许重复注册驱动。
回想第一次上传war包时,忘记关闭Tomcat了,应该就是这样的热部署导致Tomcat关闭时,未能正确注销数据库驱动。为验证这个想法,我把war包上传到了另一台阿里云服务器(centos7.4+JDK1.8+Tomcat8),这次记得上传之前把Tomcat关了,上传完毕再启动,果然可以正常访问了。心想这种问题很简单啊,直接重启系统就行,然而重启之后问题依旧;懒得仔细查原因了,直接简单粗暴重装系统,这下总算可以了吧。费了好大的劲重装系统,配置环境,装数据库,当我信心满满等待着浏览器里出现项目首页的美丽脸庞时,又一个 404 砸来,充满期待的表情立马变得一脸懵逼。这都不行??这是要闹哪样???看来不是系统的问题,但是为啥另一台服务器就可以正常访问呢?系统都是一样的呀。阿里这么牛逼的公司,服务器有问题的可能性不大,还是静静的寻找一下项目的问题吧。
第一:实现监听器并注册
把前两段警告放到网上搜,大多数都是说把 lib 下的数据库驱动 jar 包放到 Tomcat 目录下就好了,照做后无效。痛苦的煎熬中~~~。我以为后面的报错都是前面的报错引起,就只想着搜前两条警告了。绝望之中试着搜一下第三条警告,看到了一丝希望,需要自己写一个注销数据库驱动的监听器:
监听器类:
public class WebAppContextListener implements ServletContextListener {
@Override
public void contextDestroyed(ServletContextEvent event) {
System.out.println("webService stop");
try {
while(DriverManager.getDrivers().hasMoreElements()) {
DriverManager.deregisterDriver(DriverManager.getDrivers().nextElement());
}
System.out.println("jdbc Driver close");
AbandonedConnectionCleanupThread.shutdown();
System.out.println("clean thread success");
} catch (SQLException e) {
e.printStackTrace();
}catch (InterruptedException e){
e.printStackTrace();
}
}
@Override
public void contextInitialized(ServletContextEvent event) {
Const.WEB_APP_CONTEXT = WebApplicationContextUtils.getWebApplicationContext(event.getServletContext());
}
}
将这个类注册到 web.xml :
你的监听类所在的包名.WebAppContextListener
第二;升级 Druid 驱动版本
好了,这下应该没问题了吧。但还是报404 ,稍微感到一点安慰的是,错误日志的第三条警告变了:
The web application [] appears to have started a thread named [Druid-ConnectionPool-Create-155769601] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
继续搜,说是 Druid 驱动版本的问题,我看了一下项目中的 Druid 版本是 1.0.9,换成 1.0.20 后,这条警告消失了,但是前两警告依然坚挺的直立在那里,任由狂风暴雨,纹丝不动。我又陷入了绝望~~~。
第三:清理 lib 目录
之前搜问题时,有答案说要把 lib 目录下的数据库驱动 jar 放到 Tomcat 下,虽然尝试之后无效,但给了一个找问题的思路。推测应该是 lib 下的 jar 包 和 Tomcat 的 jar 包冲突,索性把 lib 目录下的 jar 包全删了(当然删之前要做备份,留下几个maven仓库里没有的第三方 jar 包),这次提示缺少数据库驱动,加入 jar 包:mysql-connector-java-5.1.34.jar 。功夫不负有心人,冰冻的心灵终于迎来了春天,终于看到了娇羞动人的首页。【最终 Tomcat 下 lib 文件夹内的 jar 保持安装 Tomcat 后的初始状态不变 】
第四:设置数据库表名大小写敏感属性
煎熬到此应该结束了吧,正准备被自己的努力感动得流泪时,点击首页的登录按钮,却一点反应都没有,赶紧把喷出的泪水塞回眼睛,继续看日志:
Error querying database. Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'SYS_USER' doesn't exist
什么?明明一大张表摆在那里,竟然说找不到?? 原来 MySQL表名 默认 大小写敏感,要来点印度神油让它不敏感。
参考这位童鞋:https://blog.csdn.net/she_lock/article/details/82143031
/etc/my.cnf
[mysqld]
节点下,加入一行: lower_case_table_names=1
MySQL
即可。 (service mysqld restart)
==========================================分割线===============================================
终于可以长驱直入项目页面了,这是一种前所未有的快感!《完》