没有需求,就没有折腾
不过我还是喜欢折腾,只要有目的,就要嗨起来。
先说一下背景。
某天,产品小伙伴过来提了一个需求:能不能把公司的需求文档以列表的方式展示出来,当开发者需要哪个的时候,自己在目录中寻找并点击进入(需要哪个点哪个,so easy),也就不用记录那么多文档 url 了。
另外说明一下,公司的需求文档是以文件夹和 html 组织形式部署在 tomcat 的,版本 8,这是前提。
听完需求,格子的脑袋就开始运转起来,这不是分分钟能搞定的事吗,袖子撸起来,说做咱做。
众 (Java) 所(程序猿)周知,一般访问 Tomcat 某个目录时,如果没有设置欢迎文件的话,是会报找不到的异常的(也就是传说中的 404),如果你开心的话,是可以设置欢迎文件来防止 404,显然这个方法是解决不了我们的需求的,确切来说,是没办法简单解决。(如果非要解决,思路无非是这样,设置欢迎文件,在欢迎文件里读取当前目录,并将目录下的子目录遍历作为列表展示给访问者,这里不做讨论,爱咋咋地)
传说中的 404
片头结束,开始正片,tomcat 是提供目录访问功能的,请不要眨眼观看下列实验步骤。
- #目录结构
- /webapps
- /zoro
- /dir1
- /dir2
- /dir3
- /dir4
- /dir5
- /dir6
- #启动tomcat
- #如果是Windows请执行startup.bat
- →startup.bat(双击运行)
- #如果是linux请执行startup.sh
- cd $CATALINA_BASE/bin
- chmod *.sh (如果已赋权,请忽略)
- ./bin/startup.sh
接下来,访问
观看效果,是不是看到了,甩手就是一个 404
- http://localhost/zoro
Tomcat 原生 404
- #编辑tomcat配置目录下的web的xml文件
- vim $CATALINA_BASE/conf/web.xml
- #大概在100来行,可以看到如下一串神秘代码
- <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>
把上面的 listings 的值改为 true,然后重启 tomcat 查看效果。
Tomcat 原生列表目录
是不是很丑,我也觉得很丑,对于我这种颜控来说,简直不忍直视,看不下去了,那就开始整容。
在 web.xml 的 90 几行 (上面那串神秘代码之上),有这样一些注释
- <!--==================B uilt In Servlet Definitions====================-
- ->
- <!-- The default servlet for all web applications, that serves static -->
- <!-- resources. It processes all requests that are not mapped to other
- -->
- <!-- servlets with servlet mappings (defined either here or in your own
- -->
- <!-- web.xml file). This servlet supports the following initialization
- -->
- <!-- parameters (default values are in square brackets): -->
- <!-- -->
- <!-- debug Debugging detail level for messages logged -->
- <!-- by this servlet. [0] -->
- <!-- -->
- <!-- fileEncoding Encoding to be used to read static resources -->
- <!-- [platform default] -->
- <!-- -->
- <!-- input Input buffer size (in bytes) when reading -->
- <!-- resources to be served. [2048] -->
- <!-- -->
- <!-- listings Should directory listings be produced if there -->
- <!-- is no welcome file in this directory? [false] -->
- <!-- WARNING: Listings for directories with many -->
- <!-- entries can be slow and may consume -->
- <!-- significant proportions of server resources. -->
- <!-- -->
- <!-- output Output buffer size (in bytes) when writing -->
- <!-- resources to be served. [2048] -->
- <!-- -->
- <!-- readonly Is this context "read only", so HTTP -->
- <!-- commands like PUT and DELETE are -->
- <!-- rejected? [true] -->
- <!-- -->
- <!-- readmeFile File to display together with the directory -->
- <!-- contents. [null] -->
- <!-- -->
- <!-- sendfileSize If the connector used supports sendfile, this -->
- <!-- represents the minimal file size in KB for -->
- <!-- which sendfile will be used. Use a negative -->
- <!-- value to always disable sendfile. [48] -->
- <!-- -->
- <!-- useAcceptRanges Should the Accept-Ranges header be included -->
- <!-- in responses where appropriate? [true] -->
- <!-- -->
- <!-- For directory listing customization. Checks localXsltFile, then -->
- <!-- globalXsltFile, then defaults to original behavior. -->
- <!-- -->
- <!-- localXsltFile Make directory listings an XML doc and -->
- <!-- pass the result to this style sheet residing -->
- <!-- in that directory. This overrides -->
- <!-- contextXsltFile and globalXsltFile[null] -->
- <!-- -->
- <!-- contextXsltFile Make directory listings an XML doc and -->
- <!-- pass the result to this style sheet which is -->
- <!-- relative to the context root. This overrides -->
- <!-- globalXsltFile[null] -->
- <!-- -->
- <!-- globalXsltFile Site wide configuration version of -->
- <!-- localXsltFile. This argument must either be an -->
- <!-- absolute or relative (to either -->
- <!-- $CATALINA_BASE/conf or $CATALINA_HOME/conf) -->
- <!-- path that points to a location below either -->
- <!-- $CATALINA_BASE/conf (checked first) or -->
- <!-- $CATALINA_HOME/conf (checked second).[null] -->
- <!-- -->
- <!-- showServerInfo Should server information be presented in the -->
- <!-- response sent to clients when directory -->
- <!-- listings is enabled? [true] -->
属性 | 描述 |
---|---|
debug | 调试级别,如果不是 tomcat 开发人员,则没有什么太大的用处。截止本文写作时,有用的值是 0、1、11、1000。默认值为 0。 |
listings | 如果没有欢迎文件,要不要显示目录列表?值可以是 true 或 false。欢迎文件是 servlet api 的一部分。警告:目录列表中含有的很多项目都是非常消耗服务性能的,如果对大型目录列表多次进行请求,会严重消耗服务器资源。 |
gzip | 如果某个文件存在 gzip 格式的文件(带有 gz 后缀名的文件通常就在原始文件旁边)。如果用户代理支持 gzip 格式,并且启用了该选项,Tomcat 就会提供该格式文件的服务。默认为 false。如果直接请求带有 gz 后缀名的文件,是可以访问它们的,所以如果原始资源受安全挟制的保护,则 gzip 文件也同样是受保护的。 |
readmeFile | 如果提供了目录列表,那么可能也会提供随带的 readme 文件。这个文件是被插入的,因此可能会包含 HTML。 |
globalXsltFile | 如果你希望定制目录列表,你可以使用一个 XSL 转换)。这个值是一个可用于所有目录列表的相对路径文件名(既相对于 CATALINA_BASE/conf/ 也相对于 $CATALINA_HOME/conf/)。可参看下面介绍的 contextXsltFile 和 localXsltFile。该 xml 文件的格式会在下文介绍。 |
contextXsltFile | 你可以通过 contextXsltFile 来定制你的目录列表。这必须是一个上下文相对路径(例如:/path/to/context.xslt),相对于带有 .xsl 或 .xslt 扩展名的文件。它将覆盖 globalXsltFile。如果提供了该值,但相对文件却不存在,则将使用 globalXsltFile。如果 globalXsltFile 也不存在,则显示默认的目录列表。 |
localXsltFile | 你还可以在每个目录通过配置 localXsltFile 定制你的目录列表。它应该是在产生列表的目录里的一个相对路径文件名。它覆盖 globalXsltFile 和 contextXsltFile。如果该值存在,但是文件不存在,那么就使用 contextXsltFile。如果 contextXsltFile 也不存在,那么就会使用 globalXsltFile。如果 globalXsltFile 也不存在,那么默认的目录列表就会被显示出来。 |
showServerInfo | 当使用目录列表,服务器信息是否应该提供给发往客户端的响应中。默认为 true。 |
- <?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/<version-major-minor/></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>
- <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>true</param-value>
- </init-param>
- <!--看这里-->
- <init-param>
- <param-name>localXsltFile</param-name>
- <param-value>zoro.xslt</param-value>
- </init-param>
- <load-on-startup>1</load-on-startup>
- </servlet>
- <xsl:variable name="urlPath" select="substring(@urlPath,12)" />
来源: http://www.jianshu.com/p/81b40a158123