在第二次启动时,应用程序启动了两次而没有环境属性

时间:2018-07-16 09:07:41

标签: spring-boot configuration tomcat8

我们的Spring Boot应用程序启动了两次,但是第二次启动时没有设置环境。因此,在第二次启动时,应用程序无法启动。我们需要从外部tomcat config目录设置应用程序。为了使日志正常工作,我们进行了以下设置。

pom.xml

<?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">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.14.RELEASE</version>
        <relativePath />
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <start-class>foo.bar.MyApplication</start-class>
        <tomcat.version>8.0.32</tomcat.version>
    </properties>

    <dependencies>
        <!-- Spring Boot -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>
        <!-- Environment -->
        <dependency>
            <groupId>com.ibm.db2.jcc</groupId>
            <artifactId>db2jcc4</artifactId>
            <version>10.1</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>
        <!-- Test -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

主班

@SpringBootApplication
@EnableAspectJAutoProxy
public class MyApplication extends SpringBootServletInitializer {

    private static final Logger LOG = LoggerFactory.getLogger(MyApplication.class);

    public MyApplication() {
        LOG.info(">>>>>>>>>>> Welcome to MyApplication");
    }

    @Override
    protected SpringApplicationBuilder configure(final SpringApplicationBuilder builder) {
        return configureApplication(builder);
    }

    public static void main(final String[] args) {
        configureApplication(new SpringApplicationBuilder()).run(args);
    }

    private static SpringApplicationBuilder configureApplication(final SpringApplicationBuilder builder) {
        return builder.sources(MyApplication.class);
    }

    @Bean
    @Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
    public MyBean getMyBean() {
        LOG.debug("Created request scoped MyBean.");
        return new MyBean();
    }
}

server.xml(向下细分)

<?xml version="1.0" encoding="UTF-8"?>
<Server port="${tomcat.shutdown.port}" shutdown="SHUTDOWN">

    <Listener SSLEngine="on" className="org.apache.catalina.core.AprLifecycleListener" />

    <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />

    <Service name="Catalina">

        <Connector connectionTimeout="20000" port="8081" protocol="HTTP/1.1"
            redirectPort="${environment.https.redirect.port}" server="Apache" />
        <Connector port="9080" protocol="AJP/1.3"
            redirectPort="${environment.https.redirect.port}" />

        <Engine defaultHost="localhost" jvmRoute="${servername}" name="Catalina">

            <Host appBase="${tomcat.webapp.dir}" autoDeploy="true" deployOnStartup="true" name="localhost" unpackWARs="true"
                xmlNamespaceAware="false" xmlValidation="false">

                <Context docBase="my-app" path="/myapp" reloadable="true">
                    <Parameter name="spring.config.location" value="file:C:/tomcat/conf/" />
                    <Parameter name="spring.config.name" value="myapp" /> <!-- results in myapp.properties -->
                    <Parameter name="org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH" value="true" />
                </Context>
            </Host>
        </Engine>
    </Service>
</Server>

日志

Jul 16, 2018 10:17:14 AM org.apache.catalina.core.AprLifecycleListener lifecycleEvent
INFO: Loaded APR based Apache Tomcat Native library 1.2.4 using APR version 1.5.1.
Jul 16, 2018 10:17:14 AM org.apache.catalina.core.AprLifecycleListener lifecycleEvent
INFO: APR capabilities: IPv6 [true], sendfile [true], accept filters [false], random [true].
Jul 16, 2018 10:17:15 AM org.apache.catalina.core.AprLifecycleListener initializeSSL
INFO: OpenSSL successfully initialized (OpenSSL 1.0.2e 3 Dec 2015)
Jul 16, 2018 10:17:15 AM org.apache.coyote.AbstractProtocol init
INFO: Initializing ProtocolHandler ["http-apr-8081"]
Jul 16, 2018 10:17:15 AM org.apache.coyote.AbstractProtocol init
INFO: Initializing ProtocolHandler ["ajp-apr-9080"]
Jul 16, 2018 10:17:15 AM org.apache.catalina.startup.Catalina load
INFO: Initialization processed in 1404 ms
Jul 16, 2018 10:17:15 AM org.apache.catalina.core.StandardService startInternal
INFO: Starting service Catalina
Jul 16, 2018 10:17:15 AM org.apache.catalina.core.StandardEngine startInternal
INFO: Starting Servlet Engine: Apache Tomcat/8.0.32
Jul 16, 2018 10:17:25 AM org.apache.jasper.servlet.TldScanner scanJars
INFO: 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.
Jul 16, 2018 10:17:26 AM org.apache.catalina.core.ApplicationContext log
INFO: 2 Spring WebApplicationInitializers detected on classpath
  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::       (v1.5.14.RELEASE)

2018-07-16 10:17:27.316  INFO 4880 --- [ost-startStop-1] f.b.MyApplication                        : Starting MyApplication v1.0.2-SNAPSHOT on tomcat with PID 4880 (C:\tomcat\webapps\myapp\WEB-INF\classes started by admin in C:\Eclipse\eclipse-jee-oxygen-1a-win32-x86_64\eclipse)
2018-07-16 10:17:27,362 localhost-startStop-1 ERROR Unable to create directory C:\Eclipse\eclipse-jee-oxygen-1a-win32-x86_64\eclipse\${sys:LOG_PATH}\2018-07
2018-07-16 10:17:27.362 DEBUG 4880 --- [ost-startStop-1] f.b.MyApplication                        : Running with Spring Boot v1.5.14.RELEASE, Spring v4.3.18.RELEASE
2018-07-16 10:17:27.378  INFO 4880 --- [ost-startStop-1] f.b.MyApplication                        : No active profile set, falling back to default profiles: default
2018-07-16 10:17:27.472  INFO 4880 --- [ost-startStop-1] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@f7cbaab2: startup date [Mon Jul 16 10:17:27 CEST 2018]; root of context hierarchy
2018-07-16 10:17:29.562  INFO 4880 --- [ost-startStop-1] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$ddbcd45] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2018-07-16 10:17:29.859  INFO 4880 --- [ost-startStop-1] o.a.c.c.C.[.[.[/myapp]                   : Initializing Spring embedded WebApplicationContext
2018-07-16 10:17:29.859  INFO 4880 --- [ost-startStop-1] o.s.w.c.ContextLoader                    : Root WebApplicationContext: initialization completed in 2387 ms
2018-07-16 10:17:30.483  INFO 4880 --- [ost-startStop-1] o.s.b.w.s.ServletRegistrationBean        : Mapping servlet: 'dispatcherServlet' to [/]
2018-07-16 10:17:30.483  INFO 4880 --- [ost-startStop-1] o.s.b.w.s.FilterRegistrationBean         : Mapping filter: 'errorPageFilter' to: [/*]
2018-07-16 10:17:30.483  INFO 4880 --- [ost-startStop-1] o.s.b.w.s.FilterRegistrationBean         : Mapping filter: 'characterEncodingFilter' to: [/*]
2018-07-16 10:17:30.483  INFO 4880 --- [ost-startStop-1] o.s.b.w.s.FilterRegistrationBean         : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2018-07-16 10:17:30.483  INFO 4880 --- [ost-startStop-1] o.s.b.w.s.FilterRegistrationBean         : Mapping filter: 'httpPutFormContentFilter' to: [/*]
2018-07-16 10:17:30.483  INFO 4880 --- [ost-startStop-1] o.s.b.w.s.FilterRegistrationBean         : Mapping filter: 'requestContextFilter' to: [/*]
com.ibm.net.SocketKeepAliveParameters
2018-07-16 10:17:39.501  INFO 4880 --- [ost-startStop-1] j.LocalContainerEntityManagerFactoryBean : Building JPA container EntityManagerFactory for persistence unit 'default'
2018-07-16 10:17:42.903  INFO 4880 --- [ost-startStop-1] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2018-07-16 10:17:42.919  INFO 4880 --- [ost-startStop-1] f.b.MyApplication                        : >>>>>>>>>>> Welcome to MyApplication
2018-07-16 10:17:44.714  INFO 4880 --- [ost-startStop-1] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@f7cbaab2: startup date [Mon Jul 16 10:17:27 CEST 2018]; root of context hierarchy
2018-07-16 10:17:44.917  INFO 4880 --- [ost-startStop-1] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/root],methods=[GET]}" [...]
2018-07-16 10:17:45.120  INFO 4880 --- [ost-startStop-1] o.s.w.s.h.SimpleUrlHandlerMapping        : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2018-07-16 10:17:45.120  INFO 4880 --- [ost-startStop-1] o.s.w.s.h.SimpleUrlHandlerMapping        : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2018-07-16 10:17:45.214  INFO 4880 --- [ost-startStop-1] o.s.w.s.h.SimpleUrlHandlerMapping        : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2018-07-16 10:17:45.651  INFO 4880 --- [ost-startStop-1] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
2018-07-16 10:17:46.151  INFO 4880 --- [ost-startStop-1] f.b.MyApplication                        : Started MyApplication in 19.788 seconds (JVM running for 32.145)
2018-07-16 10:17:46.166  INFO 4880 --- [ost-startStop-1] o.a.c.s.HostConfig                       : Deploying web application directory C:\tomcat\webapps\myapp
2018-07-16 10:17:53.420  INFO 4880 --- [ost-startStop-1] o.a.j.s.TldScanner                       : 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.
2018-07-16 10:17:53.718  INFO 4880 --- [ost-startStop-1] o.a.c.c.C.[.[.[/myapp]                   : 2 Spring WebApplicationInitializers detected on classpath

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

2018-07-16 10:17:54.435  INFO 4880 --- [ost-startStop-1] f.b.MyApplication                        : Starting MyApplication v1.0.2-SNAPSHOT on tomcat with PID 4880 (C:\tomcat\webapps\myapp\WEB-INF\classes started by admin in C:\Eclipse\eclipse-jee-oxygen-1a-win32-x86_64\eclipse)
2018-07-16 10:17:54.451  INFO 4880 --- [ost-startStop-1] f.b.MyApplication                        : No active profile set, falling back to default profiles: default
2018-07-16 10:17:54.530  INFO 4880 --- [ost-startStop-1] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@8cc9db4a: startup date [Mon Jul 16 10:17:54 CEST 2018]; root of context hierarchy
2018-07-16 10:17:56.308  INFO 4880 --- [ost-startStop-1] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$5095fdde] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2018-07-16 10:17:56.575  INFO 4880 --- [ost-startStop-1] o.a.c.c.C.[.[.[/myapp]                   : Initializing Spring embedded WebApplicationContext
2018-07-16 10:17:56.575  INFO 4880 --- [ost-startStop-1] o.s.w.c.ContextLoader                    : Root WebApplicationContext: initialization completed in 2045 ms
2018-07-16 10:17:57.136  INFO 4880 --- [ost-startStop-1] o.s.b.w.s.ServletRegistrationBean        : Mapping servlet: 'dispatcherServlet' to [/]
2018-07-16 10:17:57.136  INFO 4880 --- [ost-startStop-1] o.s.b.w.s.FilterRegistrationBean         : Mapping filter: 'errorPageFilter' to: [/*]
2018-07-16 10:17:57.136  INFO 4880 --- [ost-startStop-1] o.s.b.w.s.FilterRegistrationBean         : Mapping filter: 'characterEncodingFilter' to: [/*]
2018-07-16 10:17:57.136  INFO 4880 --- [ost-startStop-1] o.s.b.w.s.FilterRegistrationBean         : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2018-07-16 10:17:57.136  INFO 4880 --- [ost-startStop-1] o.s.b.w.s.FilterRegistrationBean         : Mapping filter: 'httpPutFormContentFilter' to: [/*]
2018-07-16 10:17:57.136  INFO 4880 --- [ost-startStop-1] o.s.b.w.s.FilterRegistrationBean         : Mapping filter: 'requestContextFilter' to: [/*]
2018-07-16 10:17:57.214  WARN 4880 --- [ost-startStop-1] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Tomcat.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.apache.tomcat.jdbc.pool.DataSource]: Factory method 'dataSource' threw exception; nested exception is org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$DataSourceBeanCreationException: Cannot determine embedded database driver class for database type NONE. If you want an embedded database please put a supported one on the classpath. If you have database settings to be loaded from a particular profile you may need to active it (no profiles are currently active).
2018-07-16 10:17:57.230  INFO 4880 --- [ost-startStop-1] utoConfigurationReportLoggingInitializer : 

Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled.
2018-07-16 10:17:57.230 ERROR 4880 --- [ost-startStop-1] o.s.b.d.LoggingFailureAnalysisReporter   : 

***************************
APPLICATION FAILED TO START
***************************

Description:

Cannot determine embedded database driver class for database type NONE

Action:

If you want an embedded database please put a supported one on the classpath. If you have database settings to be loaded from a particular profile you may need to active it (no profiles are currently active).

错误原因

在第二次启动时,不会考虑server.xml(spring.config.locationspring.config.name)中作为上下文属性的配置设置。因此,Spring Boot应用程序没有myapp.properties可用,因此spring-boot-starter-data-jpa无法找到DataSource设置的任何配置,并且初始化失败。

分析

我研究了有关在类路径中检测到的两个WebApplicationInitializers的日志条目。这不是此行为的原因。有两个WebApplicationInitializers:

  • org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration.JerseyWebApplicationInitializer
  • foo.bar.MyApplication

Jersey初始化程序来自于以下依赖项:spring-boot-autoconfigure-1.5.14.RELEASE.jar及其相关代码指出:

// We need to switch *off* the Jersey WebApplicationInitializer because it
// will try and register a ContextLoaderListener which we don't need
servletContext.setInitParameter("contextConfigLocation", "<NONE>");

Jersey WebApplicationInitializer基本上不执行任何操作,这不是此行为的原因。

因此,我研究了此行为的堆栈跟踪,并得到以下结果:

org.springframework.web.SpringServletContainerInitializer.onStartup(Set<Class<?>>, ServletContext)上设置断点

首次启动

SpringServletContainerInitializer.onStartup(Set<Class<?>>, ServletContext) line: 169    
StandardContext.startInternal() line: 5244  
StandardContext(LifecycleBase).start() line: 147    
ContainerBase$StartChild.call() line: 1408  
ContainerBase$StartChild.call() line: 1398  
FutureTask<V>.run() line: 277   
ThreadPoolExecutor.runWorker(ThreadPoolExecutor$Worker) line: 1153  
ThreadPoolExecutor$Worker.run() line: 628   
Thread.run() line: 785  

第二次启动

SpringServletContainerInitializer.onStartup(Set<Class<?>>, ServletContext) line: 169    
StandardContext.startInternal() line: 5244  
StandardContext(LifecycleBase).start() line: 147    
StandardHost(ContainerBase).addChildInternal(Container) line: 725   
StandardHost(ContainerBase).addChild(Container) line: 701   
StandardHost.addChild(Container) line: 717  
HostConfig.deployDirectory(ContextName, File) line: 1091    
HostConfig$DeployDirectory.run() line: 1830 
Executors$RunnableAdapter<T>.call() line: 522   
FutureTask<V>.run() line: 277   
ThreadPoolExecutor.runWorker(ThreadPoolExecutor$Worker) line: 1153  
ThreadPoolExecutor$Worker.run() line: 628   
Thread.run() line: 785  

根据第二个堆栈跟踪,由于某些原因,tomcat希望再次部署目录/ tomcat / webapps / myapp,并且这次不使用server.xml的上下文属性。

提示

由于我们需要完全控制日志记录,因此我们使用spring.config.location而不是@PropertySources。加载属性源可能为时已晚,根本无法选择。

非常感谢您的帮助。

2 个答案:

答案 0 :(得分:0)

我自己解决了这个问题。原因是tomcat服务器本身。配置错误。由于这不是标准的tomcat安装(客户专业化),因此在此处解释解决方案没有多大意义。

答案 1 :(得分:0)

您必须具有SpringBootServletInitializer的两个子类。并且其中一类可能缺少@Configuration。如果要运行两个实例,请确保在SpringBootServletInitializer的两个子类上都具有@Configuration。如果要运行单个实例,请删除第二个继承。