1. 程式人生 > 實用技巧 >簡單的Tomcat實現--3.3 歡迎頁面

簡單的Tomcat實現--3.3 歡迎頁面

歡迎頁面

  • 當服務啟動之後,如果指定的某個Context沒有指定頁面,也就是uri為/,那麼預設進入index.html或者index.jsp

  • 實現的思想就是,在專案配置資料夾conf下建立一個web.xml,這個配置檔案中儲存著設定好的檔案,當一個訪問未指定具體的哪個檔案時,就去解析這個檔案,獲取其中存在的檔案。

  • <?xml version="1.0" encoding="UTF-8" ?>
    <web-app>
        <welcome-file-list>
            <welcome-file>index.heml</welcome-file>
            <welcome-file>index.htm</welcome-file>
            <welcome-file>index.jsp</welcome-file>
        </welcome-file-list>
    </web-app>
    
  • 建立工具類webXmlUtil來解析這個檔案

  • package jerrymice.util;
    
    import cn.hutool.core.io.FileUtil;
    import jerrymice.catalina.Context;
    import org.jsoup.Jsoup;
    import org.jsoup.nodes.Document;
    import org.jsoup.nodes.Element;
    import org.jsoup.select.Elements;
    
    import java.io.File;
    
    /**
     * @author xsl20
     */
    public class WebXmlUtil {
        public static String getWelcomeFile(Context context) {
            String xml = FileUtil.readUtf8String(Constant.webXmlFile);
            Document document
                     = Jsoup.parse(xml);
            Elements elements = document.select("welcome-file");
    
            for (Element element : elements) {
                File tmpFile = new File(context.getDocBase(), element.text());
                if (tmpFile.exists()) {
                    // 如果找到了配置檔案中指定的檔案
                    return tmpFile.getName();
                }
            }
            return "index.html";
        }
    }
    
  • 下面改動Request類,根據請求解析其uri,然後先直接根據uri來獲取context物件,這樣就可以保證像/b這樣的訪問可以獲取到context,如果此時獲取到的context不為null,那麼就直接返回即可,如果獲取到的context為null,那麼就說明此時的uri不是一個資料夾或者是一個不存在的資料夾,那就繼續向下執行,嘗試從uri中解析出path,如果獲取到的path為null,那麼訪問的就是ROOT目錄下的檔案,如果不為空,就用這個path去獲取context物件,如果獲取到context物件為空,說明沒有這個path,那麼將context的path指定為根目錄下的那個context。儘管這個context是對應著根目錄的,但是uri並沒有變,例如訪問一個不存在的目錄/c/

    ,那麼這個請求對應的context的path就是/,但是這個uri對應的fileName是c/,這個檔案本身並不存在,所以會報404錯誤。

  •     public void parseContext(){
            Engine engine = service.getEngine();
            // 根據獲取到的uri去掃描得到的對映中去尋找這個資料夾,這樣/b就能夠獲取匹配而不一定是/b/
            context = engine.getDefaultHost().getContext(uri);
            if (context != null) {
                return;
            }
            String path = StrUtil.subBetween(uri, "/", "/");
            if (null == path) {
                // 如果uri = /timeConsume.html,那麼path = null, 不對uri進行改動
              path = "/";
            }
            else {
                // uri = /dir1/1.html, 那麼path= dir1, 經過此處之後path=/dir1
                // uri = /b/, path = /b
                path = "/" + path;
            }
            context = engine.getDefaultHost().getContext(path);
            if (null == context){
                context = engine.getDefaultHost().getContext("/");
            }
        }
    
  • public Request(Socket socket, Service service) throws IOException {
            this.socket = socket;
            this.service = service;
            parseHttpRequest();
            if (StrUtil.isEmpty(requestString)){
                return;
            }
            parseUri();
            parseContext();
            // 比如 uri 是 /a/index.html, 獲取出來的 Context路徑不是 "/”, 那麼要修正 uri 為 /index.html
            if (!"/".equals(context.getPath())){
                // 如果訪問的地址是/a,那麼經過remove之後uri就變為“”了,考慮到這種情況,讓uri等於"/"
                uri = StrUtil.removePrefix(uri, context.getPath());
                if (StrUtil.isEmpty(uri)){
                    uri = "/";
                }
            }
        }
    
  • uri 最後都會被修正為/檔名的形式, 然後在server中再去掉前面的/,得到檔名

  • 下面是Server類的修改

  • if("/".equals(uri)){
        uri = WebXMLUtil.getWelcomeFile(request.getContext());
    }
    
  • 當uri是根目錄時,就去訪問配置檔案中指定的那幾個檔案中存在的那一個,如果都不存在的話,就預設訪問index.html,這會報404錯誤。

  • 測試結果

    • 當訪問/b/時,會自動跳轉到/b/index.html