当前位置: 首页 > 知识库问答 >
问题:

无法使用主线程的上下文类加载器向@SpringBootApplication的内置Tomcat添加web应用程序

汤飞翮
2023-03-14

我正在尝试将WAR作为web应用程序加载,并随独立的JAR一起提供。当我的@springbootapplication正在启动时,我提取war文件并将其复制到文件系统。之后,我做了一个简单的tomcat.addwebapp()调用,我希望它能起作用。但看看:

@Bean
public EmbeddedServletContainerFactory servletContainerFactory() {

    return new TomcatEmbeddedServletContainerFactory() {

        @Override
        protected TomcatEmbeddedServletContainer getTomcatEmbeddedServletContainer(Tomcat tomcat) {

            String appHome = System.getProperty(Environment.APP_HOME);

            String targetFileName = "web-0.0.1-SNAPSHOT.war";               
            InputStream resourceAsStream = getClass().getClassLoader().getResourceAsStream(targetFileName);

            File target = new File(Paths.get(appHome, targetFileName).toString());

            try {

                // Copy the file to the file system
                java.nio.file.Files.copy(resourceAsStream, target.getAbsoluteFile().toPath(), StandardCopyOption.REPLACE_EXISTING);

                // Add the web application and bind it to the context path /web
                Context context = tomcat.addWebapp("/web", target.getAbsolutePath());
                WebappLoader loader = new WebappLoader(Thread.currentThread().getContextClassLoader());
                context.setLoader(loader);

            } catch (ServletException ex) {
                throw new IllegalStateException("Failed to add webapp", ex);
            } catch(Exception e) {                  
                throw new IllegalStateException("Failed to add webapp", e);
            }
            return super.getTomcatEmbeddedServletContainer(tomcat);
        }
    };
}

问题是,在ServletContainerFactory()返回之后,我得到了大量的FileNotFoundException。您可以在这里看到完整的输出,但它可以归结为:

java.io.IOException: Unable to create the directory [/tmp/tomcat.2878705033245220680.8080/webapps/web]
    at org.apache.catalina.startup.ExpandWar.expand(ExpandWar.java:115) ~[tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.catalina.startup.ContextConfig.fixDocBase(ContextConfig.java:615) [tomcat-embed-core-8.5.11.jar:8.5.11]
..
2017-02-12 19:39:44.393  INFO 10137 --- [ost-startStop-1] o.apache.catalina.startup.ContextConfig  : No global web.xml found
2017-02-12 19:39:44.590  WARN 10137 --- [ost-startStop-1] o.a.tomcat.util.scan.StandardJarScanner  : Failed to scan [file:/home/stefan/.m2/repository/org/bytedeco/javacv/1.3/javacpp-1.3.jar] from classloader hierarchy
..
java.io.FileNotFoundException: /home/stefan/.m2/repository/org/bytedeco/javacv/1.3/javacpp-1.3.jar (No such file or directory)
    at java.util.zip.ZipFile.open(Native Method) ~[na:1.8.0_121]
    at java.util.zip.ZipFile.<init>(ZipFile.java:219) ~[na:1.8.0_121]
..
2017-02-12 19:39:44.590  WARN 10137 --- [ost-startStop-1] o.a.tomcat.util.scan.StandardJarScanner  : Failed to scan [file:/home/stefan/.m2/repository/org/bytedeco/javacv/1.3/opencv-3.1.0-1.3.jar] from classloader hierarchy
..
java.io.FileNotFoundException: /home/stefan/.m2/repository/org/bytedeco/javacv/1.3/opencv-3.1.0-1.3.jar (No such file or directory)
    at java.util.zip.ZipFile.open(Native Method) ~[na:1.8.0_121]
    at java.util.zip.ZipFile.<init>(ZipFile.java:219) ~[na:1.8.0_121]
..
2017-02-12 19:39:44.591  WARN 10137 --- [ost-startStop-1] o.a.tomcat.util.scan.StandardJarScanner  : Failed to scan [file:/home/stefan/.m2/repository/org/bytedeco/javacv/1.3/ffmpeg-3.2.1-1.3.jar] from classloader hierarchy
..
java.io.FileNotFoundException: /home/stefan/.m2/repository/org/bytedeco/javacv/1.3/ffmpeg-3.2.1-1.3.jar (No such file or directory)
    at java.util.zip.ZipFile.open(Native Method) ~[na:1.8.0_121]
    at java.util.zip.ZipFile.<init>(ZipFile.java:219) ~[na:1.8.0_121]
..

最后一个例外是ClassNotFoundException,它肯定与上面的错误有关:

java.lang.ClassNotFoundException: org.apache.jasper.servlet.JspServlet
    at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1285) ~[tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1119) ~[tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.catalina.core.DefaultInstanceManager.loadClass(DefaultInstanceManager.java:520) ~[tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.catalina.core.DefaultInstanceManager.loadClassMaybePrivileged(DefaultInstanceManager.java:501) ~[tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.catalina.core.DefaultInstanceManager.newInstance(DefaultInstanceManager.java:118) ~[tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1050) ~[tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:989) ~[tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4913) [tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5223) [tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) [tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1419) [tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1409) [tomcat-embed-core-8.5.11.jar:8.5.11]
    at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_121]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_121]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_121]
    at java.lang.Thread.run(Thread.java:745) [na:1.8.0_121]

似乎所有的依赖项都缺失了。问题是我必须做些什么来解决这个问题。正如建议的那样,我还将tomcat-embed-core依赖项放到Spring应用程序的pom.xml中,但这并不起作用。

<dependency>
    <groupId>org.apache.tomcat.embed</groupId>
    <artifactId>tomcat-embed-core</artifactId>
    <version>8.5.11</version>
</dependency>

感谢任何帮助!

共有1个答案

羊舌墨一
2023-03-14

对于java.io.FileNotFoundException,可以在https://stackoverflow.com/A/37857690中找到解决方案

可以通过添加以下内容来修复ClassNotFoundException

<dependency>
  <groupId>org.apache.tomcat.embed</groupId>
  <artifactId>tomcat-embed-jasper</artifactId>
  <version>8.5.11</version>
</dependency>
 类似资料:
  • 问题内容: 如果不输入URL,我想让Tomcat自动在我的应用程序上下文中添加一个斜杠。 当我使用Jetty进行测试时,它会自动在应用程序的上下文中添加斜杠,但是Tomcat不会这样做。 我不确定一旦部署将命名上下文,因为我会将WAR交给其他人,因此HTML中的任何资源引用都是相对的。有什么方法可以让Tomcat自动添加重定向尾号到相同的上下文? 当前在Spring 3中使用Tomcat 7。 问

  • 问题内容: 我是Java的新手,刚开始弄清类加载器的概念。现在,关于线程上下文类加载器的使用,log4j出现了一些问题。 我收到以下错误: 我的应用程序大致以这种方式工作:在初始化URLClassLoader#1时,它会构建并加载一些类,这些类使用log4j。稍后在URLClassLoader#2上进行构造(其父类为URLClassLoader#1)并加载更多类,这些类也使用log4j。当使用UR

  • 我正在处理一个Spring Boot应用程序,其中我使用该应用程序公开SOAP WebService。我在Spring boot应用程序中使用Apache CFX framework for SOAP impl。我正在使用基于注释的方法。 我在一个bean中的Spring Boot配置文件中设置应用程序上下文时遇到了问题。下面是我的代码。 配置文件如下所示。 现在我有了bean SOAPproce

  • 我正在尝试以编程方式设置一个spring boot应用程序上下文根。上下文根的原因是我们希望从访问应用程序,并将所有控制器路径附加到它。 下面是Web-App的应用程序配置文件。 这是主页面的索引控制器。 应用程序的新根应该位于,但它仍然位于。 我错过了什么导致spring boot没有在请求映射之前添加上下文根?

  • 我安装了Tomcat6,并希望添加web应用程序来启动URL。我学习了如何在Tomcat7.0中设置web应用程序的上下文路径 我在/conf/catalina/localhost/path中创建了root.xml。在root.xml文件中有以下内容

  • 我需要将sqljdbc42.jar库添加到类路径中,以便连接到Azure SQL数据库。如何(如果可能的话)在Azure Web Service-Web App(Java with Tomcat server)中做到这一点。添加JDBC库还有其他方法吗? 连接字符串: 复制自门户:jdbc:sqlserver://testnabaza.database.windows.net:1433;datab