在 spring-boot 中配置嵌入式 apache tomcat 内的“tomcat-server.xml”文件

Posted

技术标签:

【中文标题】在 spring-boot 中配置嵌入式 apache tomcat 内的“tomcat-server.xml”文件【英文标题】:Configuring 'tomcat-server.xml' file inside of embedded apache tomcat in spring-boot 【发布时间】:2021-03-03 03:28:48 【问题描述】:

我正在使用带有嵌入式 tomcat(9.0.16 版)的 spring boot (2.1.3.RELEASE) 开发一个 java 应用程序(jar 文件)。

我想覆盖tomcat的CatalinaErrorReportValve错误页面,

为了做到这一点,我需要让 Tomcat 使用我为此目的创建的自定义类,而不是默认类。 这可以通过更新 Tomcat 的配置文件“server.xml”中的 Host 元素来完成。

自定义类:

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.logging.Logger;

import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.valves.ErrorReportValve;

public class CustomErrorReportValve extends ErrorReportValve 

    // Create a simple logger
    Logger log = Logger.getLogger(CustomErrorReportValve.class.getName());

    @Override
    protected void report(Request request, Response response, Throwable t) 
        try 
            // Write a more friendly, less technical message to the user
            BufferedWriter out = new BufferedWriter(new OutputStreamWriter(response.getOutputStream()));
            out.write("<html><head><title>Oops</title><body>");
            out.write("<h1>Oops</h1>");
            out.write("<p>Well, that didn't go as we had expected.</p>");
            out.write("<p>Don't worry though, we're working on it.</p>");
            out.write("</body></html>");
            out.close();

            // Log the error with your favorite logging framework...
            log.severe("Uncaught throwable was thrown: " + t.getMessage());
         catch (IOException e) 
            e.printStackTrace();
        
    

server.xml(或使用嵌入式 tomcat 时的 tomcat-server.xml):

    <Valve className="org.apache.catalina.valves.ErrorReportValve" showReport="false" showServerInfo="false" />

我在spring docs 中发现,在spring 中使用嵌入式tomcat 时,配置文件称为tomcat-server.xml 而不是server.xml。

现在,问题是我在spring boot项目中找不到tomcat-server.xml,或者如何配置/覆盖它,如果没有,有没有其他方法可以自定义catalina ErrorReportValve错误页面嵌入式tomcat的springboot?

感谢您的帮助!

【问题讨论】:

不,你没有。使用java通过注册TomcatCustomizer来配置它来做你想做的事。 谢谢@M。 Deinum,这正是我正在寻找的,我发现这篇文章解释了问题以及如何自定义这些错误,链接:gitmemory.com/issue/spring-projects/spring-boot/21257/636275409 【参考方案1】:

您的问题似乎与以下问题有关:

Tomcat invokes ErrorReportValve directly for malformed URLs #21257
import org.apache.catalina.Container;
import org.apache.catalina.core.StandardHost;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MyConfig 
    // https://docs.spring.io/spring-boot/docs/2.4.4/reference/htmlsingle/#howto-use-tomcat-legacycookieprocessor
    // https://github.com/spring-projects/spring-boot/issues/21257#issuecomment-745565376
    @Bean
    public WebServerFactoryCustomizer<TomcatServletWebServerFactory> errorReportValveCustomizer() 

        return (factory) -> 
            factory.addContextCustomizers(context -> 
                final Container parent = context.getParent();
                if (parent instanceof StandardHost) 
                    ((StandardHost) parent).setErrorReportValveClass(
                        "your.package.CustomErrorReportValve");
                
            );
        ;
    

【讨论】:

以上是关于在 spring-boot 中配置嵌入式 apache tomcat 内的“tomcat-server.xml”文件的主要内容,如果未能解决你的问题,请参考以下文章

Spring-Boot 仅在一个配置文件中执行 data.sql

spring-boot 应用程序的外部配置

如何在 spring-boot 中拦截嵌入式 Tomcat 上的“全局”404

Spring-Boot / H2 将数据库快照写入文件系统

spring-boot 项目启动过慢问题

在 Spring-Boot 的嵌入式 Netty 中增加或移除内容长度限制