将 Spring Boot 部署到 Tomcat
Posted
技术标签:
【中文标题】将 Spring Boot 部署到 Tomcat【英文标题】:Deploy Spring Boot to Tomcat 【发布时间】:2014-09-04 16:21:09 【问题描述】:所以我是 Spring 新手 - 所以我想我会尝试 Spring Boot
我正在使用 Maven 构建 - 我设置了一个视图请求,当我运行它时,“App”看起来像是它自己启动了 Tomcat,并且我在默认的 8080 端口有一个服务,所以当我调用 localhost:8080/service
一切都好。
但是,当我尝试将其打包为 WAR 以部署到服务器时,它不起作用
所以我想我会回到基础并将其部署到本地的 tomcat 服务器上,看看会发生什么
所以首先什么都没发生 - 404 - 做了一些谷歌搜索发现我需要包含这样的网络入口点 - 这是我的主要课程
@ComponentScan
@EnableAutoConfiguration
public class App extends SpringBootServletInitializer
public static void main( String[] args )
SpringApplication.run(App.class, args);
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application)
return application.sources(appClass);
private static Class<App> appClass = App.class;
所以它看起来像它工作,在控制台中我可以看到红色的 catalina 启动文本,然后我看到 Spring boot 启动(我以前没有看到)
但是,当我尝试调用服务 localhost:8080/service
时,我仍然收到 404
当我将它作为“应用程序”运行时,它会起作用
有什么明显的事情我需要做的吗?我只是制造战争
-
将 pom xml 包类型更改为 war
在上面的代码 sn-p 中包含了覆盖
作为战争输出
我已经解压缩了 WAR,它看起来很好 - 有一个 WEB-INF 和一组依赖项等。
任何帮助都会很好 - 因为有人在将 Spring Boot 应用程序部署为 WAR 时遇到类似问题?
***更新****
现在我可以让我的战争在我的本地 Tomcat 7 服务器上正确部署 - 但是当我尝试部署到外部托管的 Tomcat 容器时,我得到了
at org.springframework.web.SpringServletContainerInitializer.onStartup(SpringServletContainerInitializer.java:175)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5262)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
... 15 more
Jul 14, 2014 1:49:01 PM org.apache.catalina.startup.HostConfig deployDirectory
SEVERE: Error deploying web application directory /usr/local/shared/tomcat/thecookpot/webapps/cookpot
java.lang.IllegalStateException: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/cookpot]]
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:898)
at org.apache.catalina.core.ContainerBase.access$000(ContainerBase.java:130)
at org.apache.catalina.core.ContainerBase$PrivilegedAddChild.run(ContainerBase.java:153)
at org.apache.catalina.core.ContainerBase$PrivilegedAddChild.run(ContainerBase.java:142)
at java.security.AccessController.doPrivileged(Native Method)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:869)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:615)
at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:1095)
at org.apache.catalina.startup.HostConfig$DeployDirectory.run(HostConfig.java:1617)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:619)
Jul 14, 2014 1:49:01 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory /usr/local/shared/tomcat/thecookpot/webapps/examples
Jul 14, 2014 1:49:01 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory /usr/local/shared/tomcat/thecookpot/webapps/host-manager
Jul 14, 2014 1:49:01 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory /usr/local/shared/tomcat/thecookpot/webapps/CookPot
Jul 14, 2014 1:49:02 PM org.apache.catalina.loader.WebappClassLoader validateJarFile
INFO: validateJarFile(/usr/local/shared/tomcat/thecookpot/webapps/CookPot/WEB-INF/lib/tomcat-embed-core-7.0.52.jar) - jar not loaded. See Servlet Spec 2.3, section 9.7.2. Offending class: javax/servlet/Servlet.class
Jul 14, 2014 1:49:02 PM org.apache.catalina.loader.WebappClassLoader validateJarFile
INFO: validateJarFile(/usr/local/shared/tomcat/thecookpot/webapps/CookPot/WEB-INF/lib/tomcat-embed-el-7.0.52.jar) - jar not loaded. See Servlet Spec 2.3, section 9.7.2. Offending class: javax/el/Expression.class
Jul 14, 2014 1:49:06 PM org.apache.catalina.core.ContainerBase addChildInternal
SEVERE: ContainerBase.addChild: start:
org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/CookPot]]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:895)
at org.apache.catalina.core.ContainerBase.access$000(ContainerBase.java:130)
at org.apache.catalina.core.ContainerBase$PrivilegedAddChild.run(ContainerBase.java:153)
at org.apache.catalina.core.ContainerBase$PrivilegedAddChild.run(ContainerBase.java:142)
at java.security.AccessController.doPrivileged(Native Method)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:869)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:615)
at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:1095)
at org.apache.catalina.startup.HostConfig$DeployDirectory.run(HostConfig.java:1617)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:619)
Caused by: java.security.AccessControlException: access denied (java.util.PropertyPermission java.awt.headless write)
at java.security.AccessControlContext.checkPermission(AccessControlContext.java:323)
at java.security.AccessController.checkPermission(AccessController.java:546)
at java.lang.SecurityManager.checkPermission(SecurityManager.java:532)
at java.lang.System.setProperty(System.java:727)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:263)
at org.springframework.boot.builder.SpringApplicationBuilder.run(SpringApplicationBuilder.java:130)
at org.springframework.boot.context.web.SpringBootServletInitializer.createRootApplicationContext(SpringBootServletInitializer.java:89)
at org.springframework.boot.context.web.SpringBootServletInitializer.onStartup(SpringBootServletInitializer.java:51)
at org.springframework.web.SpringServletContainerInitializer.onStartup(SpringServletContainerInitializer.java:175)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5262)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
... 15 more
Jul 14, 2014 1:49:06 PM org.apache.catalina.startup.HostConfig deployDirectory
SEVERE: Error deploying web application directory /usr/local/shared/tomcat/thecookpot/webapps/CookPot
java.lang.IllegalStateException: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/CookPot]]
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:898)
at org.apache.catalina.core.ContainerBase.access$000(ContainerBase.java:130)
at org.apache.catalina.core.ContainerBase$PrivilegedAddChild.run(ContainerBase.java:153)
at org.apache.catalina.core.ContainerBase$PrivilegedAddChild.run(ContainerBase.java:142)
at java.security.AccessController.doPrivileged(Native Method)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:869)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:615)
at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:1095)
at org.apache.catalina.startup.HostConfig$DeployDirectory.run(HostConfig.java:1617)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:619)
Jul 14, 2014 1:49:06 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory /usr/local/shared/tomcat/thecookpot/webapps/ROOT
Jul 14, 2014 1:49:06 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory /usr/local/shared/tomcat/thecookpot/webapps/manager
Jul 14, 2014 1:49:06 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory /usr/local/shared/tomcat/thecookpot/webapps/docs
Jul 14, 2014 1:49:06 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory /usr/local/shared/tomcat/thecookpot/webapps/Cookpot
Jul 14, 2014 1:49:06 PM org.apache.catalina.loader.WebappClassLoader validateJarFile
INFO: validateJarFile(/usr/local/shared/tomcat/thecookpot/webapps/Cookpot/WEB-INF/lib/tomcat-embed-core-7.0.52.jar) - jar not loaded. See Servlet Spec 2.3, section 9.7.2. Offending class: javax/servlet/Servlet.class
Jul 14, 2014 1:49:06 PM org.apache.catalina.loader.WebappClassLoader validateJarFile
INFO: validateJarFile(/usr/local/shared/tomcat/thecookpot/webapps/Cookpot/WEB-INF/lib/tomcat-embed-el-7.0.52.jar) - jar not loaded. See Servlet Spec 2.3, section 9.7.2. Offending class: javax/el/Expression.class
Jul 14, 2014 1:49:09 PM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["http-bio-6350"]
Jul 14, 2014 1:49:09 PM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["ajp-bio-4350"]
Jul 14, 2014 1:49:09 PM org.apache.catalina.startup.Catalina start
INFO: Server startup in 17529 ms
【问题讨论】:
你有没有运行“mvn package”来创建.war?另外,在您的pom.xml
中,您是否将spring-boot-starter-tomcat
标记为provided
?请参阅here 了解此内容。
一般来说,Tomcat 会在你的应用程序的 URL 前加上 appname/
。应用程序的 Tomcat 名称是什么?
您是否遵循了 Spring.io 上的指南,该指南描述了如何将您的应用程序打包为 WAR 并部署到 Tomcat? spring.io/guides/gs/convert-jar-to-war
@philthomas26 你能准确解释一下你是如何解决这个问题的吗?因为我也一样。提前谢谢你
我以前遇到过这个问题,可以确认接受的解决方案有效。我也没有使用 Gradle 遇到过,因此也可以使用 Gradle 代替 Maven。
【参考方案1】:
当我们选择 Spring Boot 时,我们不想产生 WAR。来自root page:
Spring Boot makes it easy to create stand-alone [...]
Applications that can you can "just run".
Embed Tomcat or Jetty directly (no need to deploy WAR files)
编辑: 所以,如果目的是“尝试 Spring Boot”,我建议不要生成 WAR 文件。
如果您确实需要生成 WAR 文件(保持您的代码针对 SpringBoot 构建并生成可以在任何标准 servlet 容器中运行的文件...),那么您应该阅读文档Converting a Spring Boot JAR Application to a WAR。
您是否在构建过程中包含 spring-boot-maven-plugin ?你没有描述这一步...
【讨论】:
如果您发布一个有关如何正确执行此操作的相关示例会有所帮助 @staticx 可以在 Spring 的网站上找到:convert Spring Boot JAR to WAR。但在我看来,mcoolive 实际上确实比詹姆斯更好地回答了这个问题,考虑到没有人提到这个问题很奇怪。 Spring Boot 的全部意义在于运行一个简单的 jar 文件。仅当您使用 java servlet 容器(例如 tomcat)时才会生成 war 文件。有关这方面的更多信息,请查看:spring.io inside and out 这条评论没有回答问题。 cmets一般会回答问题吗? 此“答案”仅提供作者对他是否认为 OP 的目标合理与否的意见。【参考方案2】:Spring Boot 参考文档中的章节Packaging executable jar and war files 指出:
要构建一个既可执行又可部署到外部容器的 war 文件,您需要将嵌入式容器依赖项标记为“已提供”,例如:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<!-- ... -->
<packaging>war</packaging>
<!-- ... -->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<!-- ... -->
</dependencies>
</project>
【讨论】:
我相信在mvn package
最终生成可部署到tomcat 的.war
之前,我必须mvn clean
,同时应用此解决方案(它终于奏效了)。
“.war-ize”spring-boot 应用的步骤总结:(1)<packaging>war</packaging>
,以及pom.xml
中带有“provided”的上述依赖,(2)修改Application.java
extends SpringBootServletInitializer
和问题中的@Override
。通过 java -jar
生成可运行的 .war
并使用 spring-boot 1.3.1 部署到 tomcat 7.0.59 和 jetty 9.3.6。
重要的是要注意spring-boot-maven-plugin
构建插件应该调用目标repackage
See doc。【参考方案3】:
以下代码适用于不依赖 tomcat 的 tomcat8 部署。
@SpringBootApplication
@EnableAutoConfiguration
@ComponentScan
public class ManufacturingRegionApplication extends SpringBootServletInitializer
public static void main(String[] args)
new SpringApplicationBuilder(ManufacturingRegionApplication.class).application().run(args);
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder applicationBuilder)
return applicationBuilder.sources(application);
private static Class<ManufacturingRegionApplication> application = ManufacturingRegionApplication.class;
不需要以下依赖。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
@RestController
@RequestMapping(value = "/manufacturing-region-service")
public class ManufacturingRegionService
@Resource
private ManufacturingRegionDao manufacturingRegionDao;
@ResponseBody
@Transactional(readOnly = true)
@RequestMapping(value = "/region-codes/abbr", method = GET, produces = "application/json")
http://localhost:8080/manufacturing-region-api/manufacturing-region-service/region-codes/ABBRVALUE
【讨论】:
以上是关于将 Spring Boot 部署到 Tomcat的主要内容,如果未能解决你的问题,请参考以下文章
如何在外部 tomcat 中部署 Spring-boot REST API
尝试在外部在tomcat 9上运行带有rest控制器的spring boot war文件
Spring Boot REST Controller 部署在外部 tomcat 9 服务器上时返回 404