什么是默认 Servlet

默认 Servlet 是提供静态资源并提供目录列表(如果启用了目录列表)的 Servlet。

在哪里声明?

$CATALINA_BASE/conf/web.xml 中全局声明。默认情况下,声明为:

    <servlet>
        <servlet-name>default</servlet-name>
        <servlet-class>
          org.apache.catalina.servlets.DefaultServlet
        </servlet-class>
        <init-param>
            <param-name>debug</param-name>
            <param-value>0</param-value>
        </init-param>
        <init-param>
            <param-name>listings</param-name>
            <param-value>false</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
...
    <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

因此,默认情况下,默认 servlet 在 webapp 启动时加载,目录列表被禁用,调试被关闭。

如果需要更改应用程序的 DefaultServlet 设置, 可以通过在 /WEB-INF/web.xml 中重新定义 DefaultServlet 来覆盖默认配置。 但是,如果尝试将应用程序部署到另一个容器上,这将导致问题,因为 DefaultServlet 类将无法识别。 可以通过使用特定于 Tomcat 的 /WEB-INF/tomcat-web.xml 部署描述符来解决此问题。 格式与 /WEB-INF/web.xml 相同。将覆盖任何默认设置,但不会覆盖 /WEB-INF/web.xml 中的设置。 由于是特定于 Tomcat 的,因此只有在应用程序部署到 Tomcat 上时才会对其进行处理。

可以更改什么?

DefaultServlet 允许以下 initParameters:

属性Property 说明Description

debug

调试级别。除非是 tomcat 开发人员,否则它不是很有用。在撰写本文时,有用的值为 0、1、11。[0]

listings

如果不存在欢迎文件,是否可以显示目录列表?值可以是 true 或 false [false] 欢迎文件是 servlet api 的一部分。 警告:包含许多条目的目录列表很昂贵。对大型目录列表的多个请求可能会消耗很大一部分服务器资源。

precompressed

如果存在文件的预压缩版本(原始文件旁边的文件名后附加了 .br.gz 的文件),则如果用户代理支持匹配的内容编码(br 或 gzip)并且启用了此选项,则 Tomcat 将提供预压缩文件。[错误] 如果直接请求,则可以访问扩展名为 .br.gz 的预压缩文件,因此如果原始资源受到安全约束的保护,则预压缩版本必须受到类似的保护。 还可以配置预压缩格式列表。语法是 [content-encoding]=[file-extension] 对的逗号分隔列表。例如:br=.br,gzip=.gz,bzip2=.bz2。如果指定了多种格式,则 Client 端支持多种格式,并且 Client 端不表达首选项,则格式列表的顺序将被视为服务器首选项顺序,并用于选择返回的格式。

readmeFile

如果显示目录列表,则 readme 文件也可能随列表一起显示。此文件按原样插入,因此可能包含 HTML。

globalXsltFile

如果要自定义目录列表,可以使用 XSL 转换。此值是一个相对文件名($CATALINA_BASE/conf/ 或 $CATALINA_HOME/conf/),将用于所有目录列表。这可以按上下文和/或每个目录覆盖。请参阅下面的 contextXsltFilelocalXsltFile。xml 的格式如下所示。

contextXsltFile

还可以通过配置 contextXsltFile 按上下文自定义目录列表。这必须是扩展名为 .xsl.xslt 的文件的上下文相对路径(例如:/path/to/context.xslt)。这将覆盖 globalXsltFile。如果此值存在但文件不存在,则将使用 globalXsltFile。如果 globalXsltFile 不存在,则将显示默认目录列表。

localXsltFile

还可以通过配置 localXsltFile 来按目录自定义目录列表。这必须是将要发布列表的目录中的文件,扩展名为 .xsl.xslt。这将覆盖 globalXsltFilecontextXsltFile。如果此值存在,但文件不存在,则将使用 contextXsltFile。如果 contextXsltFile 不存在,则将使用 globalXsltFile。如果 globalXsltFile 不存在,则将显示默认目录列表。

input

读取要提供的资源时的输入缓冲区大小(以字节为单位)。[2048]

output

写入要提供的资源时的输出缓冲区大小(以字节为单位)。[2048]

readonly

此上下文是否为“只读”,因此 PUT 和 DELETE 等 HTTP 命令被拒绝?[true]

fileEncoding

读取静态资源时使用的文件编码。[platform default]

useBomIfPresent

如果静态文件包含字节顺序标记 (BOM),则应使用它来优先使用 fileEncoding 来确定文件编码。此设置必须是 true (删除 BOM 并优先使用 fileEncoding)、false (删除 BOM 但不使用它)或 pass-through (不使用 BOM 也不删除它)之一。[true]

sendfileSize

如果使用的连接器支持 sendfile,则这表示将使用 sendfile 的最小文件大小(以 KiB 为单位)。使用负值可始终禁用 sendfile。[48]

useAcceptRanges

如果为 true,则将在响应适合时设置 Accept-Ranges 标头。[true]

showServerInfo

启用目录列表时,是否应在发送给客户端的响应中显示服务器信息。[true]

sortListings

服务器是否应该对目录中的列表进行排序。[false]

sortDirectoriesFirst

服务器应在列出所有文件之前列出所有目录。[false]

allowPartialPut

服务器是否应该将带有 Range 标头的 HTTP PUT 请求视为部分 PUT?请注意,虽然 RFC 7233 阐明了 Range 标头仅对 GET 请求有效,但 RFC 9110(已废弃 RFC 7233)现在允许部分放置。[true]

directoryRedirectStatusCode

进行目录重定向(尾部斜杠缺失)时,将其用作 HTTP 响应代码。[302]

如何自定义目录列表?

可以用自己的实现覆盖 DefaultServlet,并在 web.xml 声明中使用它。 如果能理解刚才所说的内容,我们将假定可以读取 DefaultServlet servlet 的代码并进行适当的调整。 (如果不是,那么该方法不适合)

可以使用 localXsltFilecontextXsltFileglobalXsltFile,DefaultServlet 将创建一个 xml 文档, 并根据 XSLT 文件中提供的值通过 xsl 转换运行它。首先检查 localXsltFile, 然后检查 contextXsltFile,接着检查 globalXsltFile。如果未配置 XSLT 文件,则使用默认行为。

格式:

    <listing>
     <entries>
      <entry type='file|dir' urlPath='aPath' size='###' date='gmt date'>
        fileName1
      </entry>
      <entry type='file|dir' urlPath='aPath' size='###' date='gmt date'>
        fileName2
      </entry>
      ...
     </entries>
     <readme></readme>
    </listing>
  • 如果 type='dir' ,则 size 将缺失

  • 自述文件 Readme 是 CDATA 条目

下面是一个模拟默认 tomcat 行为的 xsl 文件示例:

<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="3.0">

  <xsl:output method="html" html-version="5.0"
    encoding="UTF-8" indent="no"
    doctype-system="about:legacy-compat"/>

  <xsl:template match="listing">
   <html>
    <head>
      <title>
        Sample Directory Listing For
        <xsl:value-of select="@directory"/>
      </title>
      <style>
        h1 {color : white;background-color : #0086b2;}
        h3 {color : white;background-color : #0086b2;}
        body {font-family : sans-serif,Arial,Tahoma;
             color : black;background-color : white;}
        b {color : white;background-color : #0086b2;}
        a {color : black;} HR{color : #0086b2;}
        table td { padding: 5px; }
      </style>
    </head>
    <body>
      <h1>Sample Directory Listing For
            <xsl:value-of select="@directory"/>
      </h1>
      <hr style="height: 1px;" />
      <table style="width: 100%;">
        <tr>
          <th style="text-align: left;">Filename</th>
          <th style="text-align: center;">Size</th>
          <th style="text-align: right;">Last Modified</th>
        </tr>
        <xsl:apply-templates select="entries"/>
        </table>
      <xsl:apply-templates select="readme"/>
      <hr style="height: 1px;" />
      <h3>Apache Tomcat/10.1</h3>
    </body>
   </html>
  </xsl:template>


  <xsl:template match="entries">
    <xsl:apply-templates select="entry"/>
  </xsl:template>

  <xsl:template match="readme">
    <hr style="height: 1px;" />
    <pre><xsl:apply-templates/></pre>
  </xsl:template>

  <xsl:template match="entry">
    <tr>
      <td style="text-align: left;">
        <xsl:variable name="urlPath" select="@urlPath"/>
        <a href="{$urlPath}">
          <pre><xsl:apply-templates/></pre>
        </a>
      </td>
      <td style="text-align: right;">
        <pre><xsl:value-of select="@size"/></pre>
      </td>
      <td style="text-align: right;">
        <pre><xsl:value-of select="@date"/></pre>
      </td>
    </tr>
  </xsl:template>

</xsl:stylesheet>

如何保护目录列表?

在每个单独的 Web 应用程序中使用 web.xml。请参阅 Servlet 规范的 security 部分。