简体   繁体   English

Tomcat类路径不变

[英]Tomcat classpath doesn't change

I have standart servlet webapp using Spring WebApplicatonContext defined in web.xml 我有使用web.xml中定义的Spring WebApplicatonContext的标准servlet webapp

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/spring-config.xml</param-value>
</context-param>

<listener>
    <listener-class>
        org.springframework.web.context.ContextLoaderListener
    </listener-class>
</listener>

So i have bean in my config that recieves in constructor relative path to file 所以我在我的配置中有bean可以接收构造函数到文件的相对路径

<bean id="cluster" class="by.training.tasks.cluster.servlet.ClusterScope">
    <constructor-arg value="${node.i_am}"/>
    <constructor-arg value="cluster.json"/>
</bean>

And when i try to deploy app in Tomcat (9.0.12), i get following error: 当我尝试在Tomcat(9.0.12)中部署应用程序时,出现以下错误:

Connected to server
[2018-09-19 01:32:29,664] Artifact JavaMultithread: Artifact is being deployed, please wait...
19-Sep-2018 13:32:31.983 INFO [RMI TCP Connection(5)-127.0.0.1] org.apache.jasper.servlet.TldScanner.scanJars At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.
19-Sep-2018 13:32:32.077 INFO [RMI TCP Connection(5)-127.0.0.1] org.springframework.web.context.ContextLoader.initWebApplicationContext Root WebApplicationContext: initialization started
19-Sep-2018 13:32:32.171 INFO [RMI TCP Connection(5)-127.0.0.1] org.springframework.web.context.support.XmlWebApplicationContext.prepareRefresh Refreshing Root WebApplicationContext: startup date [Wed Sep 19 13:32:32 MSK 2018]; root of context hierarchy
19-Sep-2018 13:32:32.264 INFO [RMI TCP Connection(5)-127.0.0.1] org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions Loading XML bean definitions from ServletContext resource [/WEB-INF/spring-config.xml]
19-Sep-2018 13:32:32.811 INFO [RMI TCP Connection(5)-127.0.0.1] org.springframework.jdbc.datasource.DriverManagerDataSource.setDriverClassName Loaded JDBC driver: org.postgresql.Driver
Classpath C:\java-dev\apache-tomcat-9.0.12\bin\.
19-Sep-2018 13:32:33.937 WARNING [RMI TCP Connection(5)-127.0.0.1] org.springframework.web.context.support.XmlWebApplicationContext.refresh Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'cluster' defined in ServletContext resource [/WEB-INF/spring-config.xml]: Bean instantiation via constructor failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [by.training.tasks.cluster.servlet.ClusterScope]: Constructor threw exception; nested exception is java.io.FileNotFoundException: cluster.json (Не удается найти указанный файл)
19-Sep-2018 13:32:33.952 SEVERE [RMI TCP Connection(5)-127.0.0.1] org.springframework.web.context.ContextLoader.initWebApplicationContext Context initialization failed
 org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'cluster' defined in ServletContext resource [/WEB-INF/spring-config.xml]: Bean instantiation via constructor failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [by.training.tasks.cluster.servlet.ClusterScope]: Constructor threw exception; nested exception is java.io.FileNotFoundException: cluster.json (Не удается найти указанный файл)
    at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:282)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1267)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1124)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:535)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:495)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:317)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:315)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:759)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:869)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550)
    at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:409)
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:291)
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:103)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4643)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5109)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:743)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:719)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:703)
    at org.apache.catalina.startup.HostConfig.manageApp(HostConfig.java:1737)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:287)
    at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
    at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
    at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:457)
    at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:406)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:287)
    at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
    at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
    at javax.management.remote.rmi.RMIConnectionImpl.doOperation(RMIConnectionImpl.java:1468)
    at javax.management.remote.rmi.RMIConnectionImpl.access$300(RMIConnectionImpl.java:76)
    at javax.management.remote.rmi.RMIConnectionImpl$PrivilegedOperation.run(RMIConnectionImpl.java:1309)
    at javax.management.remote.rmi.RMIConnectionImpl.doPrivilegedOperation(RMIConnectionImpl.java:1401)
    at javax.management.remote.rmi.RMIConnectionImpl.invoke(RMIConnectionImpl.java:829)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:357)
    at sun.rmi.transport.Transport$1.run(Transport.java:200)
    at sun.rmi.transport.Transport$1.run(Transport.java:197)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.Transport.serviceCall(Transport.java:196)
    at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:568)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:826)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:683)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:682)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [by.training.tasks.cluster.servlet.ClusterScope]: Constructor threw exception; nested exception is java.io.FileNotFoundException: cluster.json (Не удается найти указанный файл)
    at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:182)
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:117)
    at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:275)
    ... 59 more
Caused by: java.io.FileNotFoundException: cluster.json (Не удается найти указанный файл)
    at java.io.FileInputStream.open0(Native Method)
    at java.io.FileInputStream.open(FileInputStream.java:195)
    at java.io.FileInputStream.<init>(FileInputStream.java:138)
    at java.io.FileInputStream.<init>(FileInputStream.java:93)
    at java.io.FileReader.<init>(FileReader.java:58)
    at by.training.tasks.cluster.servlet.ClusterScope.<init>(ClusterScope.java:43)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
[2018-09-19 01:32:33,999] Artifact JavaMultithread: Error during artifact deployment. See server log for details.
    at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:170)
    ... 61 more

I've put System.out in ClusterScope counstructor and saw that classpath: 我已经将System.out放在ClusterScope协调器中,并看到了该类路径:

Classpath C:\java-dev\apache-tomcat-9.0.12\bin\.

I've tried to set bean to lazy-init. 我试图将bean设置为lazy-init。 Deployment proceed successfull, but when app access that bean the same FNF error occurs and same classpath is shown. 部署成功进行,但是当应用程序访问该bean时,发生相同的FNF错误,并显示相同的类路径。 Re-read this docs ( https://tomcat.apache.org/tomcat-8.5-doc/class-loader-howto.html ) many times but still don't understand such behaviour. 重读此文档( https://tomcat.apache.org/tomcat-8.5-doc/class-loader-howto.html )多次,但仍然不了解这种行为。

File cluster.json is located in src/main/resources dir, which packaged to WEB-INF/classes in .war 文件cluster.json位于src / main / resources目录中,该目录打包到.war中的WEB-INF / classs中

ClusterScope.java ClusterScope.java

public ClusterScope(String shardName, String clusterConfPath) throws FileNotFoundException {
    final String SEPARATOR = "\\.";
    String[] tokens = shardName.split(SEPARATOR);

    thisNode = tokens[0];
    thisShard = tokens[1];
    //\\
    System.out.println("Classpath " + new File(".").getAbsoluteFile());
    //\\
    BufferedReader reader = new BufferedReader(new FileReader(clusterConfPath));
    cluster = new Gson().fromJson(reader, new TypeToken<Map<String, Map<String, String>>>() {}.getType());
}

Finally a solution was found: implement ResourceLoaderAware interface on ClusterScope and load that file as resource 最终找到了一个解决方案:在ClusterScope上实现ResourceLoaderAware接口并将该文件作为资源加载

        Resource clusterConf = resourceLoader.getResource("classpath:cluster.json") ;
        BufferedReader reader = new BufferedReader(new InputStreamReader(clusterConf.getInputStream()));

Thanks to commentator M. Deinum 感谢评论员M.Deinum

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM