将 Spring Boot RESTful Web 服务部署到 Tomcat 时仍然缺少 Web.xml

Posted

技术标签:

【中文标题】将 Spring Boot RESTful Web 服务部署到 Tomcat 时仍然缺少 Web.xml【英文标题】:Web.xml still missing when deploying a Spring Boot RESTful Web Service to Tomcat 【发布时间】:2015-09-09 23:54:36 【问题描述】:

我正在尝试将使用 Spring Boot 构建的 RESTful Web 服务部署到 Tomcat 实例中,但收效甚微。

我的软件配置如下:我的电脑是运行OS X Yosemite 10.10.3的Mac,有Oracle Java JDK 8 1.8.0_45Gradle 2.4Apache Tomcat 7.0.47。我使用IntelliJ IDEA 14.1.4作为开发平台。

我首先关注guide,然后我得到了一个 jar,它启动了一个按预期工作的嵌入式容器。然后我按照链接在另一个guide 末尾的关于converting a Spring Boot JAR Application to a WAR 的文档进行操作。我按照Section 59.4 "Packaging executable jar and war files" 中的说明进行操作,然后按照Section 74.1 "Create a deployable war file" 中的说明进行操作。根据该网站其他几个面临同样问题的成员的帖子(here、here、here 和here,仅举几例),我现在应该可以创建一个创建一个 WAR 并将其部署在我的 Tomcat 上。不幸的是,事实并非如此。

该项目包含以下 3 个 Java 文件:Application.javaGreeting.javaGreetingController.java。第一种如下:

package hello;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.web.SpringBootServletInitializer;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableAutoConfiguration
@SpringBootApplication
public class Application extends SpringBootServletInitializer 

    public static void main(String[] args) 
        SpringApplication.run(Application.class, args);
    

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) 
        return application.sources(Application.class);
    


第二个文件包含以下内容:

package hello;

public class Greeting 

    private final long id;

    private final String content;

    public Greeting(long id, String content) 
        this.id = id;
        this.content = content;
    

    public long getId() 
        return id;
    

    public String getContent() 
        return content;
    


最后,后一个文件是:

package hello;

import java.util.concurrent.atomic.AtomicLong;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class GreetingController 

    private static final String template = "Hello, %s!";

    private final AtomicLong counter = new AtomicLong();

    @RequestMapping("/hello")
    public Greeting greeting(@RequestParam(value="name", defaultValue="World") String name) 
        return new Greeting(counter.incrementAndGet(), String.format(template, name));
    

该项目还包含以下 build.gradle 文件:

buildscript 
    repositories 
        mavenCentral()
    
    dependencies 
        classpath("org.springframework.boot:spring-boot-gradle-plugin:1.2.4.RELEASE")
    


apply plugin: 'war'
apply plugin: 'java'
apply plugin: 'idea'
apply plugin: 'spring-boot'

sourceCompatibility = 1.8
targetCompatibility = 1.8

war 
    baseName = 'rest'
//    version =  '0.1.0'


repositories 
    mavenLocal()
    mavenCentral()


configurations 
    providedRuntime


dependencies 
    compile("org.springframework.boot:spring-boot-starter-web")
    providedRuntime("org.springframework.boot:spring-boot-starter-tomcat")
    testCompile("junit:junit")

现在,如果我运行任务“gradle war”,我会生成一个大约 8 Mb 的 WAR 文件。我可以成功地将它部署到我的本地 Tomcat,但是当我将浏览器指向 http://localhost:8080/rest/hello?name=World 时,我得到了一个空白页面,而不是带有预期 JSON 的页面。如果我运行任务“gradle build”或“gradle bootRepackage”,我会得到一个 JAR 和一个 WAR 以及它们的原始版本。我之所以提到这些命令,是因为我在任何地方都没有看到它们,知道它们可能很有用。原始版本的大小都在 8 Mb 左右,而 JAR 和 WAR 的大小均为 12 Mb。如果我同时部署两个 WAR,我不会收到任何错误消息,但浏览器中也没有任何结果。这里有人建议 web.xml 可能丢失,实际上没有 WAR 实际上包含这样的文件。我这么说是因为我的 Tomcat 不是很新,出于某种原因,我认为 Spring Boot 必须从上面的代码和注释中自动创建一个 web.xml

正如@dunni 在 cmets 中所建议的,这里是我的 Tomcat 日志文件。首先catalina.log

giu 24, 2015 10:35:01 AM org.apache.catalina.startup.HostConfig deployWAR
INFO: Deploying web application archive /usr/local/apache-tomcat-7.0.47/webapps/rest.war

然后localhost.log:

giu 24, 2015 10:35:02 AM org.apache.catalina.core.ApplicationContext log
INFO: Spring WebApplicationInitializers detected on classpath: [org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration@4dfaba52]

最后是manager.log

giu 24, 2015 10:34:43 AM org.apache.catalina.core.ApplicationContext log
INFO: htmlManager: list: Listing contexts for virtual host 'localhost'
giu 24, 2015 10:34:44 AM org.apache.catalina.core.ApplicationContext log
INFO: HTMLManager: list: Listing contexts for virtual host 'localhost'
giu 24, 2015 10:35:02 AM org.apache.catalina.core.ApplicationContext log
INFO: HTMLManager: list: Listing contexts for virtual host 'localhost'

以上内容是我部署WAR后得到的。如果我随后尝试连接到 http://localhost:8080/、http://localhost:8080/rest/、http://localhost:8080/rest/hello 或 http://localhost:8080/rest/hello?name=World,则没有任何变化。

发生了什么事?我错过了什么?你能解释一下问题是什么,我该怎么做才能在 Tomcat 上成功部署这个玩具服务?非常感谢。


由于上述日志没有真正的帮助,我尝试重新启动 Tomcat 守护程序,我得到了一些更有意义的东西。现在我有以下文件:catalina.logcatalina.outhost-manager.log(空)、launchd.stderr(空)、launchd.stdoutlocalhost_access_log.txt(空)、localhost.logmanager.log(空) . catalina.logcatalina.out 现在包含以下内容:

giu 24, 2015 11:11:49 AM org.apache.catalina.core.AprLifecycleListener init
INFO: The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: /Users/stefano/Library/Java/Extensions:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java:.
giu 24, 2015 11:11:49 AM org.apache.coyote.AbstractProtocol init
INFO: Initializing ProtocolHandler ["http-bio-8080"]
giu 24, 2015 11:11:49 AM org.apache.coyote.AbstractProtocol init
INFO: Initializing ProtocolHandler ["ajp-bio-8009"]
giu 24, 2015 11:11:49 AM org.apache.catalina.startup.Catalina load
INFO: Initialization processed in 666 ms
giu 24, 2015 11:11:49 AM org.apache.catalina.core.StandardService startInternal
INFO: Starting service Catalina
giu 24, 2015 11:11:49 AM org.apache.catalina.core.StandardEngine startInternal
INFO: Starting Servlet Engine: Apache Tomcat/7.0.47
giu 24, 2015 11:11:49 AM org.apache.catalina.startup.HostConfig deployWAR
INFO: Deploying web application archive /usr/local/apache-tomcat-7.0.47/webapps/Plakko.war
giu 24, 2015 11:11:51 AM org.apache.catalina.util.SessionIdGenerator createSecureRandom
INFO: Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [574] milliseconds.
giu 24, 2015 11:11:51 AM org.apache.catalina.startup.HostConfig deployWAR
INFO: Deploying web application archive /usr/local/apache-tomcat-7.0.47/webapps/rest.war
giu 24, 2015 11:11:52 AM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory /usr/local/apache-tomcat-7.0.47/webapps/docs
giu 24, 2015 11:11:52 AM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory /usr/local/apache-tomcat-7.0.47/webapps/host-manager
giu 24, 2015 11:11:53 AM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory /usr/local/apache-tomcat-7.0.47/webapps/manager
giu 24, 2015 11:11:53 AM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory /usr/local/apache-tomcat-7.0.47/webapps/ROOT
giu 24, 2015 11:11:53 AM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["http-bio-8080"]
giu 24, 2015 11:11:53 AM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["ajp-bio-8009"]
giu 24, 2015 11:11:53 AM org.apache.catalina.startup.Catalina start
INFO: Server startup in 3349 ms

launchd.stdout 包含:

Wed Jun 24 11:11:48 CEST 2015
Starting Tomcat
Waiting for 89105

localhost.log 包含:

giu 24, 2015 11:11:52 AM org.apache.catalina.core.ApplicationContext log
INFO: Spring WebApplicationInitializers detected on classpath: [org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration@2d5eb959]

如果我尝试使用 Web 服务,localhost_access_log.txt 会更新为:

217.20.22.194 - - [24/Jun/2015:11:23:16 +0200] "GET / HTTP/1.1" 200 11444
217.20.22.194 - - [24/Jun/2015:11:23:19 +0200] "GET /rest/ HTTP/1.1" 404 5
217.20.22.194 - - [24/Jun/2015:11:23:19 +0200] "GET /rest/hello HTTP/1.1" 404 5
217.20.22.194 - - [24/Jun/2015:11:23:20 +0200] "GET /rest/hello?name=World HTTP/1.1" 404 5

由于我感觉这些日志并没有真正的帮助,我尝试关闭和启动 Tomcat。在这种情况下,我在catalina.logcatalina.out 中发现了一些有趣的东西。前者:

giu 24, 2015 11:36:56 AM org.apache.catalina.startup.HostConfig deployWAR
INFO: Deploying web application archive /usr/local/apache-tomcat-7.0.47/webapps/rest.war
giu 24, 2015 11:36:59 AM org.apache.catalina.core.ContainerBase addChildInternal
SEVERE: ContainerBase.addChild: start: 
org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/rest]]
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:633)
    at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:983)
    at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1660)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
    at java.util.concurrent.FutureTask.run(FutureTask.java:262)
    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:724)
Caused by: java.lang.NoSuchMethodError: java.lang.reflect.Parameter.isNamePresent()Z
    at org.springframework.core.StandardReflectionParameterNameDiscoverer.getParameterNames(StandardReflectionParameterNameDiscoverer.java:56)
    at org.springframework.core.PrioritizedParameterNameDiscoverer.getParameterNames(PrioritizedParameterNameDiscoverer.java:65)
    at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:182)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1139)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1042)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:504)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
    at org.springframework.boot.autoconfigure.condition.BeanTypeRegistry$OptimizedBeanTypeRegistry.getFromFactory(BeanTypeRegistry.java:320)
    at org.springframework.boot.autoconfigure.condition.BeanTypeRegistry.get(BeanTypeRegistry.java:162)
    at org.springframework.boot.autoconfigure.condition.OnBeanCondition.collectBeanNamesForType(OnBeanCondition.java:158)
    at org.springframework.boot.autoconfigure.condition.OnBeanCondition.getBeanNamesForType(OnBeanCondition.java:147)
    at org.springframework.boot.autoconfigure.condition.OnBeanCondition.getMatchingBeans(OnBeanCondition.java:119)
    at org.springframework.boot.autoconfigure.condition.OnBeanCondition.getMatchOutcome(OnBeanCondition.java:94)
    at org.springframework.boot.autoconfigure.condition.SpringBootCondition.matches(SpringBootCondition.java:45)
    at org.springframework.context.annotation.ConditionEvaluator.shouldSkip(ConditionEvaluator.java:102)
    at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForBeanMethod(ConfigurationClassBeanDefinitionReader.java:190)
    at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForConfigurationClass(ConfigurationClassBeanDefinitionReader.java:148)
    at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitions(ConfigurationClassBeanDefinitionReader.java:124)
    at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:318)
    at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:239)
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:254)
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:94)
    at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:606)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:462)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:686)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:320)
    at org.springframework.boot.context.web.SpringBootServletInitializer.run(SpringBootServletInitializer.java:117)
    at org.springframework.boot.context.web.SpringBootServletInitializer.createRootApplicationContext(SpringBootServletInitializer.java:108)
    at org.springframework.boot.context.web.SpringBootServletInitializer.onStartup(SpringBootServletInitializer.java:68)
    at org.springframework.web.SpringServletContainerInitializer.onStartup(SpringServletContainerInitializer.java:175)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5423)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    ... 10 more

giu 24, 2015 11:36:59 AM org.apache.catalina.startup.HostConfig deployWAR
SEVERE: Error deploying web application archive /usr/local/apache-tomcat-7.0.47/webapps/rest.war
java.lang.IllegalStateException: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/rest]]
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:904)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:633)
    at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:983)
    at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1660)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
    at java.util.concurrent.FutureTask.run(FutureTask.java:262)
    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:724)

而后者catalina.out

giu 24, 2015 11:36:56 AM org.apache.catalina.startup.HostConfig deployWAR
INFO: Deploying web application archive /usr/local/apache-tomcat-7.0.47/webapps/rest.war

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v1.2.4.RELEASE)

2015-06-24 11:36:59.019  INFO 89274 --- [ost-startStop-1] o.s.boot.SpringApplication               : Starting application on Mac-mini-di-Stefano.local with PID 89274 (/usr/local/apache-tomcat-7.0.47/webapps/rest/WEB-INF/lib/spring-boot-1.2.4.RELEASE.jar started by stefano in /usr/local/apache-tomcat-7.0.47/bin)
2015-06-24 11:36:59.047  INFO 89274 --- [ost-startStop-1] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@34a13c2b: startup date [Wed Jun 24 11:36:59 CEST 2015]; root of context hierarchy
2015-06-24 11:36:59.648  INFO 89274 --- [ost-startStop-1] .b.l.ClasspathLoggingApplicationListener : Application failed to start with classpath: [file:/usr/local/apache-tomcat-7.0.47/webapps/rest/WEB-INF/classes/, file:/usr/local/apache-tomcat-7.0.47/webapps/rest/WEB-INF/lib/aopalliance-1.0.jar, file:/usr/local/apache-tomcat-7.0.47/webapps/rest/WEB-INF/lib/classmate-1.0.0.jar, file:/usr/local/apache-tomcat-7.0.47/webapps/rest/WEB-INF/lib/hibernate-validator-5.1.3.Final.jar, file:/usr/local/apache-tomcat-7.0.47/webapps/rest/WEB-INF/lib/jackson-annotations-2.4.0.jar, file:/usr/local/apache-tomcat-7.0.47/webapps/rest/WEB-INF/lib/jackson-core-2.4.6.jar, file:/usr/local/apache-tomcat-7.0.47/webapps/rest/WEB-INF/lib/jackson-databind-2.4.6.jar, file:/usr/local/apache-tomcat-7.0.47/webapps/rest/WEB-INF/lib/jboss-logging-3.1.3.GA.jar, file:/usr/local/apache-tomcat-7.0.47/webapps/rest/WEB-INF/lib/jcl-over-slf4j-1.7.12.jar, file:/usr/local/apache-tomcat-7.0.47/webapps/rest/WEB-INF/lib/jul-to-slf4j-1.7.12.jar, file:/usr/local/apache-tomcat-7.0.47/webapps/rest/WEB-INF/lib/log4j-over-slf4j-1.7.12.jar, file:/usr/local/apache-tomcat-7.0.47/webapps/rest/WEB-INF/lib/logback-classic-1.1.3.jar, file:/usr/local/apache-tomcat-7.0.47/webapps/rest/WEB-INF/lib/logback-core-1.1.3.jar, file:/usr/local/apache-tomcat-7.0.47/webapps/rest/WEB-INF/lib/slf4j-api-1.7.12.jar, file:/usr/local/apache-tomcat-7.0.47/webapps/rest/WEB-INF/lib/snakeyaml-1.14.jar, file:/usr/local/apache-tomcat-7.0.47/webapps/rest/WEB-INF/lib/spring-aop-4.1.6.RELEASE.jar, file:/usr/local/apache-tomcat-7.0.47/webapps/rest/WEB-INF/lib/spring-beans-4.1.6.RELEASE.jar, file:/usr/local/apache-tomcat-7.0.47/webapps/rest/WEB-INF/lib/spring-boot-1.2.4.RELEASE.jar, file:/usr/local/apache-tomcat-7.0.47/webapps/rest/WEB-INF/lib/spring-boot-autoconfigure-1.2.4.RELEASE.jar, file:/usr/local/apache-tomcat-7.0.47/webapps/rest/WEB-INF/lib/spring-boot-starter-1.2.4.RELEASE.jar, file:/usr/local/apache-tomcat-7.0.47/webapps/rest/WEB-INF/lib/spring-boot-starter-logging-1.2.4.RELEASE.jar, file:/usr/local/apache-tomcat-7.0.47/webapps/rest/WEB-INF/lib/spring-boot-starter-web-1.2.4.RELEASE.jar, file:/usr/local/apache-tomcat-7.0.47/webapps/rest/WEB-INF/lib/spring-context-4.1.6.RELEASE.jar, file:/usr/local/apache-tomcat-7.0.47/webapps/rest/WEB-INF/lib/spring-core-4.1.6.RELEASE.jar, file:/usr/local/apache-tomcat-7.0.47/webapps/rest/WEB-INF/lib/spring-expression-4.1.6.RELEASE.jar, file:/usr/local/apache-tomcat-7.0.47/webapps/rest/WEB-INF/lib/spring-web-4.1.6.RELEASE.jar, file:/usr/local/apache-tomcat-7.0.47/webapps/rest/WEB-INF/lib/spring-webmvc-4.1.6.RELEASE.jar, file:/usr/local/apache-tomcat-7.0.47/webapps/rest/WEB-INF/lib/validation-api-1.1.0.Final.jar]
2015-06-24 11:36:59.663 ERROR 89274 --- [ost-startStop-1] o.s.boot.SpringApplication               : Application startup failed

java.lang.NoSuchMethodError: java.lang.reflect.Parameter.isNamePresent()Z
    at org.springframework.core.StandardReflectionParameterNameDiscoverer.getParameterNames(StandardReflectionParameterNameDiscoverer.java:56)
    at org.springframework.core.PrioritizedParameterNameDiscoverer.getParameterNames(PrioritizedParameterNameDiscoverer.java:65)
    at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:182)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1139)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1042)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:504)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
    at org.springframework.boot.autoconfigure.condition.BeanTypeRegistry$OptimizedBeanTypeRegistry.getFromFactory(BeanTypeRegistry.java:320)
    at org.springframework.boot.autoconfigure.condition.BeanTypeRegistry.get(BeanTypeRegistry.java:162)
    at org.springframework.boot.autoconfigure.condition.OnBeanCondition.collectBeanNamesForType(OnBeanCondition.java:158)
    at org.springframework.boot.autoconfigure.condition.OnBeanCondition.getBeanNamesForType(OnBeanCondition.java:147)
    at org.springframework.boot.autoconfigure.condition.OnBeanCondition.getMatchingBeans(OnBeanCondition.java:119)
    at org.springframework.boot.autoconfigure.condition.OnBeanCondition.getMatchOutcome(OnBeanCondition.java:94)
    at org.springframework.boot.autoconfigure.condition.SpringBootCondition.matches(SpringBootCondition.java:45)
    at org.springframework.context.annotation.ConditionEvaluator.shouldSkip(ConditionEvaluator.java:102)
    at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForBeanMethod(ConfigurationClassBeanDefinitionReader.java:190)
    at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForConfigurationClass(ConfigurationClassBeanDefinitionReader.java:148)
    at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitions(ConfigurationClassBeanDefinitionReader.java:124)
    at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:318)
    at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:239)
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:254)
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:94)
    at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:606)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:462)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:686)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:320)
    at org.springframework.boot.context.web.SpringBootServletInitializer.run(SpringBootServletInitializer.java:117)
    at org.springframework.boot.context.web.SpringBootServletInitializer.createRootApplicationContext(SpringBootServletInitializer.java:108)
    at org.springframework.boot.context.web.SpringBootServletInitializer.onStartup(SpringBootServletInitializer.java:68)
    at org.springframework.web.SpringServletContainerInitializer.onStartup(SpringServletContainerInitializer.java:175)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5423)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:633)
    at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:983)
    at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1660)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
    at java.util.concurrent.FutureTask.run(FutureTask.java:262)
    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:724)

通过查看这些日志,我感觉 Spring 的自动魔法过程中出现了一些问题,但不幸的是我不知道是什么以及如何解决它。有什么帮助吗?

【问题讨论】:

在 Servlet-3.0 兼容的应用程序中不需要 web.xml。 SpringBootServletInitializer 完成了这项工作。 tomcat 日志文件中是否还有任何日志消息? @dunni 感谢您的回复,我认为我需要一个web.xml(并且 Spring Boot 正在从项目中的 Java 代码和注释中生成一个),因为我的 Tomcat 不是很新。感谢您建议查看日志文件(顺便说一下,我将添加到我的问题中):我不应该在深夜发布任何内容,否则我会错过这些琐碎的事情。跨度> 我将我的 Tomcat 更新到最新的 8 版本(8.0.23),但仍然没有运气...... 【参考方案1】:

你用的是什么版本的java? gradle 文件表明你打算使用 java 8,但是这个错误表明你不是...

java.lang.NoSuchMethodError: java.lang.reflect.Parameter.isNamePresent()

The Parameter class was not introduced until java 8。你的tomcat用的是什么版本的java?

【讨论】:

再次感谢您的帮助!我跟着this guide 在我的 Yosemite 上安装了我的 Tomcat。我认为它使用的是最新的 Java(在撰写此消息时),即 Oracle Java 8 u 45。实际上,如果我在终端中调用 java -version,我会得到以下信息:java version "1.8.0_45"Java(TM) SE Runtime Environment (build 1.8.0_45-b14)@987654327 @。不过,在那里运行的其他服务是使用 Java 7 创建的。我还能检查什么? 我发现一个页面建议打开终端,cd 到 Tomcat 安装文件夹并运行 java -cp lib/catalina.jar org.apache.catalina.util.ServerInfo 以确定 Tomcat 和 Java 的版本。这是结果输出:Server version: Apache Tomcat/8.0.23Server built: May 19 2015 14:58:38 UTCServer number: 8.0.23.0OS Name: Mac OS XOS Version: 10.10.3Architecture: x86_64JVM Version: 1.8.0_45-b14JVM Vendor: Oracle Corporation

以上是关于将 Spring Boot RESTful Web 服务部署到 Tomcat 时仍然缺少 Web.xml的主要内容,如果未能解决你的问题,请参考以下文章

将 Spring Boot RESTful Web 服务部署到 Tomcat 时仍然缺少 Web.xml

使用 Spring Boot Actuator 构建 RESTful Web 服务

将Spring Boot RESTful Web Service部署到Tomcat时,Web.xml仍然丢失

如何为 Spring Boot RESTful Web 服务配置多级身份验证?

用spring boot快速创建 Restful Web Service

用于 RESTful Web 服务的 Spring Boot 与 Apache CXF?