什么是默认 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 也不存在,则显示默认的目录列表。

任何 localXsltFile 既是 Tomcat 配置文件的一部分,也是 Web 应用程序的一部分。根据 Tomcat 安全模型,这些文件被视为可信文件。对该文件的写入权限应像对任何 Tomcat 配置文件的写入权限一样,仅限受信任的用户访问。这包括通过 WebDAV、PUT 或类似方式进行远程访问的用户。

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] 已弃用。此选项将在 Tomcat 12 及以后版本中移除,并且不会有替代选项,届时它将被硬编码为 true

showServerInfo

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

sortListings

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

sortDirectoriesFirst

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

allowPartialPut

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

directoryRedirectStatusCode

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

allowPostAsGet

控制是否将使用 POST 方法对静态资源的直接请求(即非转发或包含请求)视为使用 GET 方法进行处理。如果不允许,请求将被拒绝。将请求视为使用 GET 方法处理的默认行为保持不变。[true]

如何自定义目录列表?

可以用自己的实现覆盖 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 部分。