Tomcat目錄文件列表功能和定制化

沒有需求,就沒有折騰

不過我還是喜歡折騰,只要有目的,就要嗨起來。

先說一下背景。
某天,產品小伙伴過來提了一個需求:能不能把公司的需求文檔以列表的方式展示出來,當開發者需要哪個的時候,自己在目錄中尋找并點擊進入(需要哪個點哪個,so easy),也就不用記錄那么多文檔url了。
另外說明一下,公司的需求文檔是以文件夾和html組織形式部署在tomcat的,版本8,這是前提。
聽完需求,格子的腦袋就開始運轉起來,這不是分分鐘能搞定的事嗎,袖子擼起來,說做咱做。

眾(Java)所(程序猿)周知,一般訪問Tomcat某個目錄時,如果沒有設置歡迎文件的話,是會報找不到的異常的(也就是傳說中的404),如果你開心的話,是可以設置歡迎文件來防止404,顯然這個方法是解決不了我們的需求的,確切來說,是沒辦法簡單解決。(如果非要解決,思路無非是這樣,設置歡迎文件,在歡迎文件里讀取當前目錄,并將目錄下的子目錄遍歷作為列表展示給訪問者,這里不做討論,愛咋咋地)

傳說中的404

片頭結束,開始正片,tomcat是提供目錄訪問功能的,請不要眨眼觀看下列實驗步驟。

1、在webapp下新建目錄,并啟動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

接下來,訪問http://localhost/zoro觀看效果,是不是看到了,甩手就是一個404

Tomcat原生404

2、修改tomcat配置

#編輯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原生列表目錄

是不是很丑,我也覺得很丑,對于我這種顏控來說,簡直不忍直視,看不下去了,那就開始整容。

3、定制目錄列表

在web.xml的90幾行(上面那串神秘代碼之上),有這樣一些注釋

<!-- ================== Built 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。

上述來源:tomcat官網

看完上面的文檔,應該對定制自己的目錄列表有一些思路了。
定制目錄列表需要自己定義globalXsltFile/contextXsltFile/localXsltFile,tomcat提供了定制的example。
話不多說,動手吧,如果諸位看官需要對所有目錄進行同樣的定制,那么可以采用globalXsltFile,如果跟格子一樣,只需要特定目錄下的,那么建議采用localXstlFile,先用tomcat提供的示例看下效果。
在特定目錄下(格子這里是$CALINA_BASE/webapps/zoro)下新建文件zoro.xslt(or .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/<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>

保存上面文件后,修改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>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>

重啟tomcat,看效果


Tomcat目錄定制示例

是不是好了一些了,但是還是一般般,畢竟是官網提供的示例,也沒辦法漂亮到哪里去,不過定制的方法已經提供,剩下的就是html美化了,各位可以自行發揮。

格子這邊用bootstrap的表格改了一版,如圖

基于Bootstrap美化的定制目錄

5、再啰嗦幾句

在進行定制化的時候,難免有些特殊需求,雖然繁瑣但是還是可以實現的。
比如格子這邊需要對目錄進行截取,可以在xslt文件中,利用substring函數來實現

 <xsl:variable name="urlPath" select="substring(@urlPath,12)"/>

當然,還有很多其他的函數,或者通過java/javasrcipt方式來擴展,畢竟不是本文主題,不做贅述,需要的自行百度

寫在最后

好久沒寫博客了,求捧場,求點贊,求夸獎。


yeah
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,563評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,694評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,672評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,965評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,690評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,019評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,013評論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,188評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,718評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,438評論 3 360
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,667評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,149評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,845評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,252評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,590評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,384評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,635評論 2 380

推薦閱讀更多精彩內容