很多人都使用tomcat来作为java web项目的服务器,特别是在开发阶段,选择的人更多。本文所说的问题针对tomcat的开发环境,在正式环境中不会出现这个问题。
前段时间,在进行项目运行的时候出现了一件怪事:一个类明明就有,但是tomcat在启动的时候就是要反复报“java.lang.ClassNotFoundException”,经过不断检查,上网查询,终于找到了原因并解决之,下面做一些说明,希望对其他人有所帮助。
要重现这个问题,需要满足一些条件:在开发的IDE中进行部署(如eclipse,这是很常见的),项目中有用户登录的操作,连续的直接重启服务器(这在开发中也是很常见的)。
这个问题并不是每次都会出现,只不过出现的概率也是挺大的,出现的时候报的错误就是说的用于在session中保存用户登录的那个类找不到,服务器也启动成功,但是看到有异常总感觉不舒坦,就想解决了她。
出现这个问题的原因就是tomcat在关闭的时候会保存当前存在的session对象,然后在启动的时候恢复,这个的具体过程没有去研究过,不过关于这个的例子大家可以试一试——就是在正式环境(不是在IDE中部署)中,用户登录之后不关闭浏览器,使用tomcat的shutdown脚本关闭服务器,然后在启动服务器,就可以看到浏览器的session还是有效的。
这个功能默认都是开启的,但是在开发环境中服务器关闭的时候保存的用户对象对应的类有可能已经改变了(部署的时候重新编译有可能会造成这种情况),等到服务器启动的时候恢复session就找不到类了,所以就报了那个错误。
再出现这个错误之后我们就会去找,发现这个类真真正正是存在的,然后就会很疑惑,不知所以。
下面就来解决这个问题。
既然前面已经说过,这个问题的原因是因为tomcat要试图恢复关闭时保存的session造成成的,那么我们就关闭这个功能吧,这样服务器启动还会快速一些呢。
说干就干,下载就以使用eclipse的java ee版中关联的tomcat为例子进行说明。
注:使用eclipse关联tomcat的方法想必大家已经知道了,否则不会看到这里了,即使大家真的不知道,也可以查看我的另外的文章,那里面有关于如何关联的介绍。
使用eclipse关联好tomcat之后,会在项目视图中产生一个“Servers”的文件夹里面又有一个文件夹对应新建的服务器,里面就是一些服务器的配置,仔细观察和对比这些配置,其实就是tomcat的conf目录下面的配置文件拷贝了一份过来,完全就是一样的。
我们比较关心的是其中一个叫做“server.xml”的文件,这里面配置有服务器的监听端口、部署情况等等,这个文件比较长,这里就不完整的贴出来了,只贴出我们要关心的部分(大约在114-127行):
<Host appBase="webapps" autoDeploy="true" name="localhost" unpackWARs="true"> <!-- SingleSignOn valve, share authentication between web applications Documentation at: /docs/config/valve.html --> <!-- <Valve className="org.apache.catalina.authenticator.SingleSignOn" /> --> <!-- Access log processes all example. Documentation at: /docs/config/valve.html Note: The pattern used is equivalent to using pattern="common" --> <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" pattern="%h %l %u %t "%r" %s %b" prefix="localhost_access_log" suffix=".txt"/> </Host>
这就是配置服务器的部署情况的。
我们通过servers视图部署项目:
在添加了部署之后原先的关于部署的配置已经自动变更为了:
<Host appBase="webapps" autoDeploy="true" name="localhost" unpackWARs="true"> <!-- SingleSignOn valve, share authentication between web applications Documentation at: /docs/config/valve.html --> <!-- <Valve className="org.apache.catalina.authenticator.SingleSignOn" /> --> <!-- Access log processes all example. Documentation at: /docs/config/valve.html Note: The pattern used is equivalent to using pattern="common" --> <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" pattern="%h %l %u %t "%r" %s %b" prefix="localhost_access_log" suffix=".txt"/> <Context docBase="PMS" path="/ROOT" reloadable="true" source="org.eclipse.jst.jee.server:PMS"/> </Host>
这个时候服务器已经可以启动了,平常时候我们也差不多就是这么做的,当然有些人(比如我)还会把自动重新加载关闭,然后就变成了这样:
<Host appBase="webapps" autoDeploy="true" name="localhost" unpackWARs="true"> <!-- SingleSignOn valve, share authentication between web applications Documentation at: /docs/config/valve.html --> <!-- <Valve className="org.apache.catalina.authenticator.SingleSignOn" /> --> <!-- Access log processes all example. Documentation at: /docs/config/valve.html Note: The pattern used is equivalent to using pattern="common" --> <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" pattern="%h %l %u %t "%r" %s %b" prefix="localhost_access_log" suffix=".txt"/> <Context docBase="PMS" path="/ROOT" reloadable="false" source="org.eclipse.jst.jee.server:PMS"/> </Host>
这样,当我们在服务器启动之后修改了java类文件服务器就不会自动地加载这个修改了的类对应的class文件了,这样做主要是它的自动重新加载不仅消耗机器的性能,而且还多数时候不好用,还是要手动的重启服务器。
直接修改关于部署的配置为下面这个样子(删去了注释):
<Host appBase="webapps" autoDeploy="true" name="localhost" unpackWARs="true"> <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" pattern="%h %l %u %t "%r" %s %b" prefix="localhost_access_log" suffix=".txt" /> <Context docBase="PMS" path="/ROOT" reloadable="false" source="org.eclipse.jst.jee.server:PMS"> <Manager className="org.apache.catalina.session.PersistentManager" saveOnRestart="false" /> </Context> </Host>
这样配置之后,就把对应部署的tomcat的session自动保存关闭了,原先的问题就没有再出现过了。
根据解决之后的配置可以看出来,其实出现这个问题的原因就是tomcat默认开启了对session在重启时候的自动持久化,我们需要做的就是关闭它,关闭的操作就是在对应应用的上下文(也就是<Context />)中添加:
<Manager className="org.apache.catalina.session.PersistentManager" saveOnRestart="false" />
只不过由于该标签在添加完“部署”配置之后是默认自己关闭的,我们需要让它使用单独的关闭标签,那样才能配置。
其实就是一句话的事儿。
本文介绍了一个在使用tomcat作为开发调试用服务器时候启动过程中出现的问题的原因和详细的解决方法。
关于描述的这个问题,很多人都不知道到底是怎么一回事,网上关于这个问题的文章也不是很多,我之前寻找的时候就是找了很久之后才看到的,本着做笔记和帮助他人的原则,写下这篇文章,希望对大家有所帮助。
enjoy!!