Spring Boot 2 中缺少 TomcatEmbeddedServletContainerFactory

Posted

技术标签:

【中文标题】Spring Boot 2 中缺少 TomcatEmbeddedServletContainerFactory【英文标题】:TomcatEmbeddedServletContainerFactory is missing in Spring Boot 2 【发布时间】:2018-05-21 20:36:34 【问题描述】:

我有 Spring Boot 应用程序版本 1.5.x,它使用 org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory,我正在尝试将其迁移到 Spring Boot 2,但应用程序无法编译,尽管 a 依赖于 org.springframework.boot:spring-boot-starter-tomcat。编译器发出以下错误:

error: package org.springframework.boot.context.embedded.tomcat

【问题讨论】:

Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean的可能重复 【参考方案1】:

在 Spring boot 2.0.0.RELEASE 中,您可以替换为以下代码::

@Bean
public ServletWebServerFactory servletContainer() 
    TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory() 
        @Override
        protected void postProcessContext(Context context) 
            SecurityConstraint securityConstraint = new SecurityConstraint();
            securityConstraint.setUserConstraint("CONFIDENTIAL");
            SecurityCollection collection = new SecurityCollection();
            collection.addPattern("/*");
            securityConstraint.addCollection(collection);
            context.addConstraint(securityConstraint);
        
    ;
    tomcat.addAdditionalTomcatConnectors(redirectConnector());
    return tomcat;


private Connector redirectConnector() 
    Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
    connector.setScheme("http");
    connector.setPort(8080);
    connector.setSecure(false);
    connector.setRedirectPort(8443);
    return connector;

【讨论】:

这应该是公认的答案。正是我想要的。我唯一不同的是这一行:Connector connector = new Connector(TomcatServletWebServerFactory.DEFAULT_PROTOCOL); 感谢您的回答。 如果我这样做,我会收到IllegalStateException: No ServletContext set - 知道我错过了什么吗? 我按照你提到的做了,但是当我在 http 上点击我的应用程序时,它仍然给我错误:错误请求主机和端口的这种组合需要 TLS。理想情况下,当没有连接器时会出现此错误。如果我需要做其他事情,请告诉我。我点击网址:localhost:8443 嗨@displayname,对于No ServletContext set,我做了一个简单的演示来理解并分享我的发现here。如果你有兴趣:) 嗨@Anurag,您需要点击localhost:8080,或者您在connector.setPort(your_http_port) 中设置的http 端口。如果您点击localhost:8443,请确保您至少拥有自签名证书,以及 application.properties 中所需的属性,以告诉 Tomcat 证书在哪里,密码是什么等等。【参考方案2】:

该类已被删除并替换为org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory 更多信息请查看:Spring-Boot-2.0-Migration-Guide,上面写着:

为了支持反应式用例,嵌入式容器 包结构已被相当广泛地重构。 EmbeddedServletContainer 已重命名为 WebServer 和 org.springframework.boot.context.embedded 包已被重新定位 到 org.springframework.boot.web.server。相应地, EmbeddedServletContainerCustomizer 已重命名为 WebServerFactoryCustomizer。

例如,如果您正在自定义嵌入式 Tomcat 容器 使用 TomcatEmbeddedServletContainerFactory 回调接口, 你现在应该使用 TomcatServletWebServerFactory 如果你正在使用 EmbeddedServletContainerCustomizer bean,您现在应该使用 WebServerFactoryCustomizer bean。

我遇到的问题是我需要发送更大的请求,然后允许默认大小:

@Bean
    public TomcatServletWebServerFactory containerFactory() 
        return new TomcatServletWebServerFactory() 
            protected void customizeConnector(Connector connector) 
                int maxSize = 50000000;
                super.customizeConnector(connector);
                connector.setMaxPostSize(maxSize);
                connector.setMaxSavePostSize(maxSize);
                if (connector.getProtocolHandler() instanceof AbstractHttp11Protocol) 

                    ((AbstractHttp11Protocol <?>) connector.getProtocolHandler()).setMaxSwallowSize(maxSize);
                    logger.info("Set MaxSwallowSize "+ maxSize);
                
            
        ;

    

【讨论】:

【参考方案3】:

太好了! 我来自这篇文章: https://blog.swdev.ed.ac.uk/2015/06/24/adding-embedded-tomcat-ajp-support-to-a-spring-boot-application/

使用 Spring Boot 2.1.3:

@Configuration
@Data
public class TomcatConfiguration 

@Value("$tomcat.ajp.port")
int ajpPort;

@Value("$tomcat.ajp.remoteauthentication")
String remoteAuthentication;

@Value("$tomcat.ajp.enabled")
boolean tomcatAjpEnabled;

@Bean
public TomcatServletWebServerFactory servletContainer() 

    TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
    if (tomcatAjpEnabled)
    
        Connector ajpConnector = new Connector("AJP/1.3");
        ajpConnector.setPort(ajpPort);
        ajpConnector.setSecure(false);
        ajpConnector.setAllowTrace(false);
        ajpConnector.setScheme("https");
        tomcat.addAdditionalTomcatConnectors(ajpConnector);
    

    return tomcat;
  


【讨论】:

在 Spring Boot 2.3.2 中我得到:java.lang.IllegalArgumentException: The AJP Connector is configured with secretRequired="true" but the secret attribute is either null or "". This combination is not valid.

以上是关于Spring Boot 2 中缺少 TomcatEmbeddedServletContainerFactory的主要内容,如果未能解决你的问题,请参考以下文章

spring boot 学习一 springboot项目初步搭建

Spring Boot 2.1 缺少多个 org.hibernate.jpa.event 类

缺少请求正文的 Spring Boot POST 请求?

使用 Spring Boot Maven 插件时,jar 文件中缺少 Spring Boot 应用程序中的资源

json响应spring boot中缺少字段

由于缺少 WebApp 库,在 Spring-boot-starter 项目中构建失败