陷阱:千万不要随便把serlvet.jar之类的包放在系统的classpath下面

540 查看

源于学习用spring十分钟搭建restful风格的web服务

最近开始着手学习spring,按照官网的guide,十分钟搭建一个restful风格的web服务的hello world,原地址在这里:Building a RESTful Web Service
一切过程都很顺利,直到运行的时候,出现了这个鬼:

第一反应是官网的case太老,疏于更新了。这种情况也不是没有。
但我一看spring的官网这么酷炫,貌似经常更新,不应该出现这么低级的错误。

就我的经验来看,这种问题,一般都是jar的版本问题导致的。
而对于servlet来说,就有两种情况,要么是servlet包太老,要么就是servlet容器太老。

stackoverflow的答案:小心JVM的系统目录

我google一下,在stackoverflow上,对于同一个问题,看到这么一个答案:

按照其解决步骤:
我查看了一下servlet容器,spring的demo里面是内置tomcat8的,所以不存在容器问题,那么只可能是servlet包问题了。
这个时候第三个步骤:
千万不要把servlet-api.jar或者j2ee.jar放在/WEB-INF/lib里,更糟糕的是放在JRE/lib或者JRE/lib/ext里面,这是新手常犯的错误。

看到这里,我第一反应是检查了classpath的路径,果然在一个路径下发现有躺着一个servlet.jar,不知道什么时候放上去的。
移除掉这个jar,再运行就成功了。

JAVA类加载机制

稍微有点遗憾的是,那位大神没解释原因。
我仔细回想了一下,大学时曾看过一些JVM类加载的问题,顺便找到了这篇文章:
深入研究Java类加载机制

详细请看那篇文章,这里简单总结下:
JVM会优先加载系统lib或者用户自己配置的classpath下的jar包,然后再加载项目中的jar包。作为项目开发人员,千万不要外部包放到系统目录和classpath路径下,这是在为以后埋坑。

新技能get:正确导入servlet容器的方式

有一个小tips:
对于eclipse,最好选择eclipse自带的servlet容器,其操作方式是:
右键项目 ---> Properties ---> Java Build Path ---> Add Library... ---> Server Runtime ---> J2EE Priview(当然,如果你需要配置自己的tomcat,在这里选择tomcat即可) ----> Finish.