嵌入式Jetty:需要ServletContext来配置默认的servlet处理

时间:2016-10-02 14:24:59

标签: java spring-boot jetty

我正在尝试使用嵌入式jetty服务器设置spring boot应用程序。该服务器应运行一个小型webapp。但是,在启动时,我会在加载war文件之后得到以下异常。

微量

2016-10-02 16:07:59.302 ERROR 18765 --- [           main] o.s.boot.SpringApplication               : Application startup failed

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'defaultServletHandlerMapping' defined in class path resource [org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.web.servlet.HandlerMapping]: Factory method 'defaultServletHandlerMapping' threw exception; nested exception is java.lang.IllegalArgumentException: A ServletContext is required to configure default servlet handling
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:599) ~[spring-beans-4.2.6.RELEASE.jar!/:4.2.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1123) ~[spring-beans-4.2.6.RELEASE.jar!/:4.2.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1018) ~[spring-beans-4.2.6.RELEASE.jar!/:4.2.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:510) ~[spring-beans-4.2.6.RELEASE.jar!/:4.2.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) ~[spring-beans-4.2.6.RELEASE.jar!/:4.2.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.2.6.RELEASE.jar!/:4.2.6.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.2.6.RELEASE.jar!/:4.2.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.2.6.RELEASE.jar!/:4.2.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) ~[spring-beans-4.2.6.RELEASE.jar!/:4.2.6.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772) ~[spring-beans-4.2.6.RELEASE.jar!/:4.2.6.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:839) ~[spring-context-4.2.6.RELEASE.jar!/:4.2.6.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:538) ~[spring-context-4.2.6.RELEASE.jar!/:4.2.6.RELEASE]
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118) ~[spring-boot-1.3.5.RELEASE.jar!/:1.3.5.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:766) [spring-boot-1.3.5.RELEASE.jar!/:1.3.5.RELEASE]
    at org.springframework.boot.SpringApplication.createAndRefreshContext(SpringApplication.java:361) [spring-boot-1.3.5.RELEASE.jar!/:1.3.5.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:307) [spring-boot-1.3.5.RELEASE.jar!/:1.3.5.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1191) [spring-boot-1.3.5.RELEASE.jar!/:1.3.5.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1180) [spring-boot-1.3.5.RELEASE.jar!/:1.3.5.RELEASE]
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.web.servlet.HandlerMapping]: Factory method 'defaultServletHandlerMapping' threw exception; nested exception is java.lang.IllegalArgumentException: A ServletContext is required to configure default servlet handling
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:189) ~[spring-beans-4.2.6.RELEASE.jar!/:4.2.6.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588) ~[spring-beans-4.2.6.RELEASE.jar!/:4.2.6.RELEASE]
    ... 24 common frames omitted
Caused by: java.lang.IllegalArgumentException: A ServletContext is required to configure default servlet handling
    at org.springframework.util.Assert.notNull(Assert.java:115) ~[spring-core-4.2.6.RELEASE.jar!/:4.2.6.RELEASE]
    at org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer.<init>(DefaultServletHandlerConfigurer.java:53) ~[spring-webmvc-4.2.6.RELEASE.jar!/:4.2.6.RELEASE]
    at org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport.defaultServletHandlerMapping(WebMvcConfigurationSupport.java:451) ~[spring-webmvc-4.2.6.RELEASE.jar!/:4.2.6.RELEASE]
    at org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration$EnableWebMvcConfiguration$$EnhancerBySpringCGLIB$$671a10db.CGLIB$defaultServletHandlerMapping$28(<generated>) ~[spring-boot-autoconfigure-1.3.5.RELEASE.jar!/:1.3.5.RELEASE]
    at org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration$EnableWebMvcConfiguration$$EnhancerBySpringCGLIB$$671a10db$$FastClassBySpringCGLIB$$f33d99c3.invoke(<generated>) ~[spring-boot-autoconfigure-1.3.5.RELEASE.jar!/:1.3.5.RELEASE]
    at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) ~[spring-core-4.2.6.RELEASE.jar!/:4.2.6.RELEASE]
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:356) ~[spring-context-4.2.6.RELEASE.jar!/:4.2.6.RELEASE]
    at org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration$EnableWebMvcConfiguration$$EnhancerBySpringCGLIB$$671a10db.defaultServletHandlerMapping(<generated>) ~[spring-boot-autoconfigure-1.3.5.RELEASE.jar!/:1.3.5.RELEASE]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.7.0_111]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) ~[na:1.7.0_111]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.7.0_111]
    at java.lang.reflect.Method.invoke(Method.java:606) ~[na:1.7.0_111]
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162) ~[spring-beans-4.2.6.RELEASE.jar!/:4.2.6.RELEASE]
    ... 25 common frames omitted

我已将代码减少到最低限度并仍然出错。

主要

@Configuration
@ComponentScan
@EnableAutoConfiguration
public class ServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(ServerApplication.class);
    }

}

配置

@Configuration

@EnableAutoConfiguration
public class JettyServerCustomizer implements EmbeddedServletContainerCustomizer {

    @Override
    public void customize(ConfigurableEmbeddedServletContainer container) {
        if (container instanceof JettyEmbeddedServletContainerFactory) {
            customizeJetty((JettyEmbeddedServletContainerFactory) container);
        }
    }

    public void customizeJetty(
            JettyEmbeddedServletContainerFactory containerFactory) {
        containerFactory.addServerCustomizers(jettyServerCustomizer());
    }

    @Bean
    public JettyServerCustomizer jettyServerCustomizer() {
        return new JettyServerCustomizer() {

            @Override
            public void customize(Server server) {
                String jetty_home = System.getProperty("jetty.home","..");
                WebAppContext webapp = new WebAppContext();
                webapp.setContextPath("/");
                webapp.setWar(jetty_home+"/webapps/sample.war");
                server.setHandler(webapp);
            }
        };
    }
}

有什么建议吗?谢谢!

更新

在尝试Strelok的建议后,我得到了这个错误。

2016-10-02 16:55:03.715  INFO 20025 --- [           main] org.eclipse.jetty.servlet.ServletHolder  : unavailable

java.lang.NullPointerException: null
    at org.eclipse.jetty.servlet.ServletHolder.initMultiPart(ServletHolder.java:702) [jetty-servlet-9.2.16.v20160414.jar!/:9.2.16.v20160414]
    at org.eclipse.jetty.servlet.ServletHolder.initServlet(ServletHolder.java:607) [jetty-servlet-9.2.16.v20160414.jar!/:9.2.16.v20160414]
    at org.eclipse.jetty.servlet.ServletHolder.initialize(ServletHolder.java:396) [jetty-servlet-9.2.16.v20160414.jar!/:9.2.16.v20160414]
    at org.eclipse.jetty.servlet.ServletHandler.initialize(ServletHandler.java:871) [jetty-servlet-9.2.16.v20160414.jar!/:9.2.16.v20160414]
    at org.springframework.boot.context.embedded.jetty.JettyEmbeddedWebAppContext$JettyEmbeddedServletHandler.deferredInitialize(JettyEmbeddedWebAppContext.java:46) [spring-boot-1.3.5.RELEASE.jar!/:1.3.5.RELEASE]
    at org.springframework.boot.context.embedded.jetty.JettyEmbeddedWebAppContext.deferredInitialize(JettyEmbeddedWebAppContext.java:36) [spring-boot-1.3.5.RELEASE.jar!/:1.3.5.RELEASE]
    at org.springframework.boot.context.embedded.jetty.JettyEmbeddedServletContainer.handleDeferredInitialize(JettyEmbeddedServletContainer.java:167) [spring-boot-1.3.5.RELEASE.jar!/:1.3.5.RELEASE]
    at org.springframework.boot.context.embedded.jetty.JettyEmbeddedServletContainer.handleDeferredInitialize(JettyEmbeddedServletContainer.java:170) [spring-boot-1.3.5.RELEASE.jar!/:1.3.5.RELEASE]
    at org.springframework.boot.context.embedded.jetty.JettyEmbeddedServletContainer.start(JettyEmbeddedServletContainer.java:114) [spring-boot-1.3.5.RELEASE.jar!/:1.3.5.RELEASE]
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.startEmbeddedServletContainer(EmbeddedWebApplicationContext.java:293) [spring-boot-1.3.5.RELEASE.jar!/:1.3.5.RELEASE]
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.finishRefresh(EmbeddedWebApplicationContext.java:141) [spring-boot-1.3.5.RELEASE.jar!/:1.3.5.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:541) [spring-context-4.2.6.RELEASE.jar!/:4.2.6.RELEASE]
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118) [spring-boot-1.3.5.RELEASE.jar!/:1.3.5.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:766) [spring-boot-1.3.5.RELEASE.jar!/:1.3.5.RELEASE]
    at org.springframework.boot.SpringApplication.createAndRefreshContext(SpringApplication.java:361) [spring-boot-1.3.5.RELEASE.jar!/:1.3.5.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:307) [spring-boot-1.3.5.RELEASE.jar!/:1.3.5.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1191) [spring-boot-1.3.5.RELEASE.jar!/:1.3.5.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1180) [spring-boot-1.3.5.RELEASE.jar!/:1.3.5.RELEASE]

2 个答案:

答案 0 :(得分:0)

我认为您需要重用服务器中的处理程序:

return new JettyServerCustomizer() {

        @Override
        public void customize(Server server) {
            String jetty_home = System.getProperty("jetty.home","..");
            WebAppContext webapp = new WebAppContext();
            webapp.setContextPath("/");
            webapp.setWar(jetty_home+"/webapps/sample.war");
            webapp.setHandler(server.getHandler());
            server.setHandler(webapp);
        }
    };

答案 1 :(得分:0)

由于启用了WebMvc支持而发生此错误。这可能由于包含@EnableWebMvc的配置类而发生,但也由于自动配置。请尝试排除WebMvc自动配置。

@EnableAutoConfiguration(exclude = {WebMvcAutoConfiguration.class, WebMvcAutoConfiguration.EnableWebMvcConfiguration.class, WebMvcAutoConfiguration.WebMvcAutoConfigurationAdapter.class})

就我而言,我需要WebMvc支持,因此我获得了从@Configuration继承的WebMvcConfigurationSupport类的访问权限,并使用Jetty配置设置servlet上下文来修复NPE

@Bean
public org.eclipse.jetty.webapp.Configuration jettyConfiguration() {
    return new AbstractConfiguration() {
        @Override
        public void configure(WebAppContext context) throws Exception {
            // This line fixes the error in my case
            config.setServletContext(context.getServletContext());
        }
    };
}