文档章节

关于在使用tomcat做开发测试的某些时候无端报ClassNotFound异常的解决方法

阿信sxq
 阿信sxq
发布于 2015/08/01 14:21
字数 1832
阅读 992
收藏 44

        很多人都使用tomcat来作为java web项目的服务器,特别是在开发阶段,选择的人更多。本文所说的问题针对tomcat的开发环境,在正式环境中不会出现这个问题。

        前段时间,在进行项目运行的时候出现了一件怪事:一个类明明就有,但是tomcat在启动的时候就是要反复报“java.lang.ClassNotFoundException”,经过不断检查,上网查询,终于找到了原因并解决之,下面做一些说明,希望对其他人有所帮助。

0、重现

        要重现这个问题,需要满足一些条件:在开发的IDE中进行部署(如eclipse,这是很常见的),项目中有用户登录的操作,连续的直接重启服务器(这在开发中也是很常见的)。

        这个问题并不是每次都会出现,只不过出现的概率也是挺大的,出现的时候报的错误就是说的用于在session中保存用户登录的那个类找不到,服务器也启动成功,但是看到有异常总感觉不舒坦,就想解决了她。

1、原因

        出现这个问题的原因就是tomcat在关闭的时候会保存当前存在的session对象,然后在启动的时候恢复,这个的具体过程没有去研究过,不过关于这个的例子大家可以试一试——就是在正式环境(不是在IDE中部署)中,用户登录之后不关闭浏览器,使用tomcat的shutdown脚本关闭服务器,然后在启动服务器,就可以看到浏览器的session还是有效的。

        这个功能默认都是开启的,但是在开发环境中服务器关闭的时候保存的用户对象对应的类有可能已经改变了(部署的时候重新编译有可能会造成这种情况),等到服务器启动的时候恢复session就找不到类了,所以就报了那个错误。

        再出现这个错误之后我们就会去找,发现这个类真真正正是存在的,然后就会很疑惑,不知所以。

        下面就来解决这个问题。

2、解决方法

        既然前面已经说过,这个问题的原因是因为tomcat要试图恢复关闭时保存的session造成成的,那么我们就关闭这个功能吧,这样服务器启动还会快速一些呢。

        说干就干,下载就以使用eclipse的java ee版中关联的tomcat为例子进行说明。

2.1 在eclipse中关联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 &quot;%r&quot; %s %b" prefix="localhost_access_log" suffix=".txt"/>
</Host>

        这就是配置服务器的部署情况的。

2.2 部署项目之后的配置

        我们通过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 &quot;%r&quot; %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 &quot;%r&quot; %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文件了,这样做主要是它的自动重新加载不仅消耗机器的性能,而且还多数时候不好用,还是要手动的重启服务器。

2.3 关闭tomcat关闭时的session自动保存

        直接修改关于部署的配置为下面这个样子(删去了注释):

<Host appBase="webapps" autoDeploy="true" name="localhost" unpackWARs="true">

   <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
       pattern="%h %l %u %t &quot;%r&quot; %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自动保存关闭了,原先的问题就没有再出现过了。

3、总结

        根据解决之后的配置可以看出来,其实出现这个问题的原因就是tomcat默认开启了对session在重启时候的自动持久化,我们需要做的就是关闭它,关闭的操作就是在对应应用的上下文(也就是<Context />)中添加:

<Manager className="org.apache.catalina.session.PersistentManager" saveOnRestart="false" />

        只不过由于该标签在添加完“部署”配置之后是默认自己关闭的,我们需要让它使用单独的关闭标签,那样才能配置。

        其实就是一句话的事儿。

4、后记

        本文介绍了一个在使用tomcat作为开发调试用服务器时候启动过程中出现的问题的原因和详细的解决方法。

        关于描述的这个问题,很多人都不知道到底是怎么一回事,网上关于这个问题的文章也不是很多,我之前寻找的时候就是找了很久之后才看到的,本着做笔记和帮助他人的原则,写下这篇文章,希望对大家有所帮助。

        enjoy!!


© 著作权归作者所有

阿信sxq

阿信sxq

粉丝 231
博文 83
码字总数 73652
作品 1
成都
后端工程师
私信 提问
加载中

评论(8)

阿信sxq
阿信sxq 博主

引用来自“泥沙砖瓦浆木匠”的评论

收到~ 是有时候
那个异常看着挺烦的
阿信sxq
阿信sxq 博主

引用来自“迷你卡卡西”的评论

谢谢分享!
阿信sxq
阿信sxq 博主

引用来自“夏阳hc”的评论

感谢分享。
阿信sxq
阿信sxq 博主

引用来自“jeffsui”的评论

收到
泥瓦匠BYSocket
泥瓦匠BYSocket
收到~ 是有时候
迷你卡卡西
迷你卡卡西
谢谢分享!
夏阳hc
夏阳hc
感谢分享。
jeffsui
jeffsui
收到
做ServletContextListener时老显示ClassNotFound异常,怎么办呀?

环境:eclipse_ee_mars tomcat 8.5 linux 代码的功能是,利用ServletContextListener监听Servlet上下文(创建和注销),以及利用ServletContextAttributeListener来监听属性的变化。我自己写...

月光散落
2017/05/30
436
1
java【jar包的正确运行方式】

-jar参数运行应用时classpath的设置方法 你是否在使用java -jar参数运行打包好的jar应用程序的时候发现应用程序无法找到classpath下设置好的第三方类库的内容?无论怎么设置classpath参数都无...

止静
2014/09/10
283
0
Jar缺少依赖包的时候,什么时候报错?

一个类中某方法某行代码依赖另一个Jar,将此类打包成Jar,不提供被依赖,然后使用这个类这个方法,会报ClassNotFound,报ClassNotFound的准确时候是? 使用这个类的时候? 进入这个方法的时候...

黎明伟
2013/06/22
222
4
eclipse 启动tomcat, java.lang.ClassNotFoundExcepti

其实,eclipse经常会犯这些小脾气,不知道如何解决的,确实很恼人,毕竟不是程序问题,有时候会花比较长的时间,时间花在这上面确实很蛋疼 我总结,应该eclipse没有把部分class文件,部署到~...

beanGou
2015/09/23
48
0
Eclipse里面调试java总结

正所谓“工欲善其事必先利其器",会用Eclipse去调试可以帮助识别和解决应用程序缺陷,同时也可以帮助我们去阅读和理解一些源码是有极大的帮助的。可以极大的提高我们的工作效率。 1.基础知识...

双月通天
2015/09/11
335
0

没有更多内容

加载失败,请刷新页面

加载更多

golang-字符串-地址分析

demo package mainimport "fmt"func main() {str := "map.baidu.com"fmt.Println(&str, str)str = str[0:5]fmt.Println(&str, str)str = "abc"fmt.Println(&s......

李琼涛
今天
4
0
Spring Boot WebFlux 增删改查完整实战 demo

03:WebFlux Web CRUD 实践 前言 上一篇基于功能性端点去创建一个简单服务,实现了 Hello 。这一篇用 Spring Boot WebFlux 的注解控制层技术创建一个 CRUD WebFlux 应用,让开发更方便。这里...

泥瓦匠BYSocket
今天
6
0
从0开始学FreeRTOS-(列表与列表项)-3

FreeRTOS列表&列表项的源码解读 第一次看列表与列表项的时候,感觉很像是链表,虽然我自己的链表也不太会,但是就是感觉很像。 在FreeRTOS中,列表与列表项使用得非常多,是FreeRTOS的一个数...

杰杰1号
今天
4
0
Java反射

Java 反射 反射是框架设计的灵魂(使用的前提条件:必须先得到代表的字节码的 Class,Class 类 用于表示.class 文件(字节码)) 一、反射的概述 定义:JAVA 反射机制是在运行状态中,对于任...

zzz1122334
今天
5
0
聊聊nacos的LocalConfigInfoProcessor

序 本文主要研究一下nacos的LocalConfigInfoProcessor LocalConfigInfoProcessor nacos-1.1.3/client/src/main/java/com/alibaba/nacos/client/config/impl/LocalConfigInfoProcessor.java p......

go4it
昨天
9
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部