从Intellij IDEA运行Spring Boot(1.2.7)Web应用程序(响应SSL请求)效果很好。
构建JAR工件以从命令行运行,启动时引发错误
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.
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.
根据错误请求添加了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); } } }
Spring Boot(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会输出以下信息(我忽略了所有DEBUG消息,因为它们没有找到似乎并不适当的配置文件application.properties / application / application-production.properties)
. ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: 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
在IntelliJ IDEA-项目结构-工件-可用元素中,所有Gradle依赖库都需要提取到 Spring Root应用程序JAR的Output Root中,才能从Java命令行执行正常运行。
将JAR工件更改为此后,我可以构建JAR并从命令行JVM运行它。
为了使默认的TomcatEmbeddedServletContainerFactory在HTTPS / SSL端口8443上运行,请指定与application.properties中所要求的等效的java命令行参数。
即
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