Java Spring启动JAR-缺少EmbeddedServletContainerFactory

Java Spring启动JAR-缺少EmbeddedServletContainerFactory,java,spring,spring-boot,Java,Spring,Spring Boot,SpringBoot(1.2.7)web应用程序(响应SSL请求)在IntellijIDEA上运行时效果非常好 构建JAR工件从命令行运行,启动时抛出错误 org.springframework.context.ApplicationContextException: 无法启动嵌入式容器 嵌套异常是org.springframework.context.ApplicationContextException:由于缺少EmbeddedServletContainerFactory bean,无法启

SpringBoot(1.2.7)web应用程序(响应SSL请求)在IntellijIDEA上运行时效果非常好

构建JAR工件从命令行运行,启动时抛出错误

org.springframework.context.ApplicationContextException:
无法启动嵌入式容器
嵌套异常是
org.springframework.context.ApplicationContextException:由于缺少EmbeddedServletContainerFactory bean,无法启动EmbeddedWebApplicationContext。

问题
  • 如何避免这个错误
  • 如果需要声明EmbeddedServletContainerFactory,如何让它的ServletContainer处理对控制器的请求
  • 尝试过的解决方案 根据错误请求添加了EmbeddedservletContainerFactory。项目现在从JAR启动,但控制器并不像从IntelliJ运行时那个样接收请求

    下面是添加EmbeddedServletContainerFactory后我的Application.class的外观

    package org.coursera.diabetes;
    
    import com.j256.ormlite.dao.Dao;
    import com.j256.ormlite.support.ConnectionSource;
    import diabetes.common.model.*;
    import org.apache.catalina.connector.Connector;
    import org.apache.coyote.http11.Http11NioProtocol;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
    import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
    import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
    import org.springframework.boot.context.embedded.tomcat.TomcatConnectorCustomizer;
    import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Profile;
    import org.springframework.core.env.Environment;
    import org.springframework.core.io.ClassPathResource;
    import org.springframework.core.io.Resource;
    
    import java.io.File;
    import java.io.IOException;
    import java.sql.SQLException;
    import java.util.ArrayList;
    import java.util.List;
    
    @SpringBootApplication
    public class Application {
        private static final Logger logger = LoggerFactory.getLogger(Application.class);
    
        private static final String dbUrl = "jdbc:h2:mem:testdb";
    
        public static void main(String[] args) {
            SpringApplication.run(Application.class, args);
    
        }
    
        @Bean
        @Profile("production")
        public EmbeddedServletContainerFactory servletContainer(@Value("${keystore.file}") Resource keystoreFile) {
            TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory();
            //factory.setPort(8443);
            String absoluteKeystoreFile = "";
    
            try {
                absoluteKeystoreFile = keystoreFile.getFile().getAbsolutePath();
                logger.info(String.format("******** keystore: %s", absoluteKeystoreFile));
            } catch (IOException e) {
                e.printStackTrace();
            }
    
            tomcat.addAdditionalTomcatConnectors(createSslConnector(absoluteKeystoreFile));
            return tomcat;
        }
    
        private Connector createSslConnector(String absKeystoreFile) {
            Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
            Http11NioProtocol protocol = (Http11NioProtocol) connector.getProtocolHandler();
            try {
                connector.setScheme("https");
                connector.setSecure(true);
                connector.setPort(8443);
                protocol.setSSLEnabled(true);
                protocol.setKeystoreFile(absKeystoreFile);
                protocol.setKeystorePass("changeit");
                protocol.setKeyAlias("tomcat");
                return connector;
            }
            catch (Exception ex) {
                throw new IllegalStateException("can't access keystore: [" + "keystore"
                        + "] or truststore: [" + "keystore" + "]", ex);
            }
        }
    }
    
    笔记 SpringBoot(web)应用程序在Intellij IDEA中运行非常出色,它响应https请求,而不需要在application.properties中执行多行操作:

    security.require-ssl=true
    server.port=8443
    server.ssl.key-store=src/main/resources/private/keystore
    server.ssl.key-store-password=changeit
    server.ssl.key-password=changeit
    
    要从命令行启动JAR工件,我使用:

    java -Dspring.profiles.active=production -Dkeystore.file=file:///$PWD/keystore -jar diabetes-spring.jar
    
    JAR启动时不会出错,但是https web请求(从Intellij工作)只返回Apache/tomcat 404 “请求的资源不可用”

    编辑 使用-Ddebug运行JAR将输出以下信息(我将省略所有调试消息,因为它们没有找到配置文件application.properties/application/application-production.properties,这些文件似乎不相关)


    在intellijidea-Project Structure-Artifacts-Available元素中,所有的Gradle依赖项库都需要提取到输出根中,Spring Boot应用程序的JAR才能从java命令行执行中正常运行

    将JAR工件更改为这个之后,我可以构建JAR并从命令行JVM运行它

    对于要在HTTPS/SSL端口8443上运行的默认TomcatEmbeddedServletContainerFactory,请指定与application.properties中所需参数等效的java命令行参数

    i、 e


    试着将事情恢复原状,并查看自动配置报告(使用--debug运行),看看为什么嵌入式servlet容器不能自动运行-configured@AndyWilkinson谢谢尝试了-Ddebug选项。奇怪的是,在运行JAR时,没有生成自动配置报告。(上面复制了输出。)。在IDEA中运行--调试,报告按预期生成。我想知道在构建JAR工件时,自动配置是否以某种方式关闭。如何构建JAR?在IDEA->Project Structure(Cmd+;)->Artifacts->+按钮中,->JAR->from Modules with Dependencies->select main Module->select main class->JAR files from libraries:extract to the target JAR->directory for META-INF/MANIFEST.MF:/src/main/resources/->Build(在菜单中)->Build artifacts->[选择JAR的名称]->Build
      .   ____          _            __ _ _
     /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
    ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
     \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
      '  |____| .__|_| |_|_| |_\__, | / / / /
     =========|_|==============|___/=/_/_/_/
     :: Spring Boot ::
    
    2015-11-13 14:16:39.980  INFO 47600 --- [           main] org.coursera.diabetes.Applica
    tion        : Starting Application on Bakers-MacBook-Pro.local with PID 47600 (/User
    s/baker/coursera-android/MoCCA-15/spring-tests/diabetes_root2/diabetes-spring/out/artifa
    cts/diabetes_spring_jar/diabetes-spring.jar started by blam in /Users/blam/coursera-and
    roid/MoCCA-15/spring-tests/diabetes_root2/diabetes-spring/out/artifacts/diabetes_spring
    _jar)
    2015-11-13 14:16:39.983 DEBUG 47600 --- [           main] o.s.boot.SpringApplication
                : Loading source class org.coursera.diabetes.Application
    2015-11-13 14:16:40.011 DEBUG 47600 --- [           main] o.s.b.c.c.ConfigFileApplicati
    onListener  : Activated profiles production
    2015-11-13 14:16:40.011 DEBUG 47600 --- [           main] o.s.b.c.c.ConfigFileApplicati
    onListener  : Loaded config file 'file:./config/application.properties'
    2015-11-13 14:16:40.020  INFO 47600 --- [           main] ationConfigEmbeddedWebApplica
    tionContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbe
    ddedWebApplicationContext@23faf8f2: startup date [Fri Nov 13 14:16:40 WET 2015]; root o
    f context hierarchy
    2015-11-13 14:16:40.022 DEBUG 47600 --- [           main] ationConfigEmbeddedWebApplica
    tionContext : Bean factory for org.springframework.boot.context.embedded.AnnotationConf
    igEmbeddedWebApplicationContext@23faf8f2: org.springframework.beans.factory.support.Def
    aultListableBeanFactory@6cc7b4de: defining beans [org.springframework.context.annotatio
    n.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.inter
    nalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequired
    AnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProc
    essor,application]; root of factory hierarchy
    2015-11-13 14:16:40.220 DEBUG 47600 --- [           main] ationConfigEmbeddedWebApplica
    tionContext : Unable to locate MessageSource with name 'messageSource': using default [
    org.springframework.context.support.DelegatingMessageSource@20ce78ec]
    2015-11-13 14:16:40.221 DEBUG 47600 --- [           main] ationConfigEmbeddedWebApplica
    tionContext : Using ApplicationEventMulticaster [org.springframework.context.event.Simp
    leApplicationEventMulticaster@393671df]
    2015-11-13 14:16:40.226  WARN 47600 --- [           main] ationConfigEmbeddedWebApplica
    tionContext : Exception encountered during context initialization - cancelling refresh
    attempt
    
    org.springframework.context.ApplicationContextException: Unable to start embedded conta
    iner; nested exception is org.springframework.context.ApplicationContextException: Unab
    le to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactor
    y bean.
            at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRe
    fresh(EmbeddedWebApplicationContext.java:132)
            at org.springframework.context.support.AbstractApplicationContext.refresh(Abstr
    actApplicationContext.java:474)
            at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refr
    esh(EmbeddedWebApplicationContext.java:117)
            at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:68
    9)
            at org.springframework.boot.SpringApplication.run(SpringApplication.java:321)
            at org.springframework.boot.SpringApplication.run(SpringApplication.java:969)
            at org.springframework.boot.SpringApplication.run(SpringApplication.java:958)
            at org.coursera.diabetes.Application.main(Application.java:40)
    Caused by: org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean.
            at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.getEmbeddedServletContainerFactory(EmbeddedWebApplicationContext.java:182)
            at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.createEmbeddedServletContainer(EmbeddedWebApplicationContext.java:155)
            at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:129)
            ... 7 common frames omitted
    
    2015-11-13 14:16:40.227  INFO 47600 --- [           main] .b.l.ClasspathLoggingApplicationListener : Application failed to start with classpath: [file:/Users/baker/coursera-android/MoCCA-15/spring-tests/diabetes_root2/diabetes-spring/out/artifacts/diabetes_spring_jar/diabetes-spring.jar]
    2015-11-13 14:16:40.228 ERROR 47600 --- [           main] o.s.boot.SpringApplication               : Application startup failed
    
    org.springframework.context.ApplicationContextException: Unable to start embedded container; nested exception is org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean.
            at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:132)
            at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:474)
            at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:117)
            at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:689)
            at org.springframework.boot.SpringApplication.run(SpringApplication.java:321)
            at org.springframework.boot.SpringApplication.run(SpringApplication.java:969)
            at org.springframework.boot.SpringApplication.run(SpringApplication.java:958)
            at org.coursera.diabetes.Application.main(Application.java:40)
    Caused by: org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean.
            at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.getEmbeddedServletContainerFactory(EmbeddedWebApplicationContext.java:182)
            at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.createEmbeddedServletContainer(EmbeddedWebApplicationContext.java:155)
            at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:129)
            ... 7 common frames omitted
    
    java -jar your-spring.jar --security.require-ssl=true --server.port=8443 --server.ssl.key-store=keystore --server.ssl.key-store-password=changeit --server.ssl.key-password=changeit