集成Clojure,Spring和Tomcat时的类加载过程

时间:2015-08-10 13:36:32

标签: java spring spring-mvc tomcat clojure

我们一起使用Spring MVC和clojure来构建WAR Web应用程序并使用Tomcat部署应用程序。控制器以clojure实现,gen-class生成要从Spring框架扫描的带注释的类文件。

当我通过以下方式打印类路径时:

(seq (.getURLs (java.lang.ClassLoader/getSystemClassLoader)))

我只有$TOMCAT_HOME/bin/bootstrap.jar$TOMCAT_HOME/bin/tomcat-juli.jar。我期待webapp/ROOT/WEB-INF/classes列在seq中。为什么呢?

从代码的clojure部分打印时的堆栈跟踪如下:

java.lang.Exception: at columbus.controller$_hello.invoke(controller.clj:17) 
at columbus.controller.TestController.hello(Unknown Source) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
at java.lang.reflect.Method.invoke(Method.java:606) 
at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:219) 
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132) 
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:100) 
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:604) 
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:565) 
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80) 
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:923) 
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:852) 
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882) 
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:778) 
at javax.servlet.http.HttpServlet.service(HttpServlet.java:621) 
at javax.servlet.http.HttpServlet.service(HttpServlet.java:728) 
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305) 
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) 
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) 
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) 
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) 
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88) 
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76) 
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) 
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) 
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222) 
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123) 
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502) 
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171) 
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100) 
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953) 
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118) 
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408) 
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1041) 
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:603) 
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310) 
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) 
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) 
at java.lang.Thread.run(Thread.java:744) 

1 个答案:

答案 0 :(得分:1)

id.get() & id.set()为您提供JVM和Tomcat使用的类加载器。每个webapp都有自己的类加载器,当tomcat重新加载应用程序时,它会丢弃当前的应用程序类加载器并创建一个新的。

系统类加载器是应用程序类加载器的父级。当您在类加载器中查找某些内容时,您首先将类加载器委托给其父项,然后如果其父项无法找到匹配的内容,则尝试自行加载它。但它并没有看到儿童类加载器。因此,如果您从系统类加载器开始,您将无法在那里找到特定于您的Web应用程序的任何内容。

在您的应用程序代码中,您可以获取应用程序加载的类(如TestController)并在其上调用getResourceAsStream,它将查找与您在WEB-INF / classes下提供的路径匹配的文件。