面試——路徑、轉發與重定向的區別

情形

複習尚學堂java的mybatis第二天遇到了一系列問題,並以此來複習關於項目路徑,服務器路徑,絕對路徑,相對路徑以及轉發和重定向的區別

一、轉發與重定向

1.兩者的區別

鏈接:https://blog.csdn.net/liubin5620/article/details/79922692

二、路徑

我們以web開發的各種資源作爲大環境探討路徑的問題和定義

項目路徑:叫做項目根目錄或者WEB應用程序的根目錄,也就是idea中當前web項目中的web文件夾路徑,爲web,如下圖所示:

服務器路徑:tomcat軟件文件夾下的 webapps文件夾,也就是tomcat/webapp文件夾,叫做服務器根目錄或者web站點根目錄我們的web項目最終打包上傳到tomcat服務器上,並存在於webapps目錄下,並且以項目名稱作爲文件夾

我們可以在idea中配置當前項目上傳到服務器根目錄下的項目文件夾名稱,名稱是可以更改的,可以與idea中的項目名稱不同(最好一致)。這點idea與eclipse不同,eclipse項目在tomcat服務器根目錄下的項目文件夾名稱與在本地項目名相同(即ide中項目名相同),當然我們需要注意,假設我們更改了idea項目在服務器根目錄下的文件夾名稱,例如將/cmz_ReviewMybatis改爲——>/ReviewMybatis,則會使用/cmz_ReviewMybatis不能訪問到當前項目資源,需要使用/ReviewMybatis來訪問,並且後續的資源訪問也要使用/ReviewMybatis作爲開始的url訪問後續的資源,並且會影響重定向與靜態資源訪問的路徑,具體下文會提到。如圖所示:

複習項目打包上傳到tomcat的過程

  1. 在idea中,如果項目不是用maven管理的,則將項目src目錄下的所有java文件編譯成爲class文件,並放到項目文件夾web文件夾下的web-inf文件夾下的classes文件夾中(web(webapp)/web-inf/classes)其中resources文件夾中的資源文件例如spring等配置文件也會保存在classes文件夾下,而項目的依賴jar包則會上傳到WEB-INF文件夾下的lib文件夾中
  2. 將項目根目錄的文件夾web,重命名爲項目的名稱(這裏爲cmz_ReviewMybatis,後面的war_exploded不用管,不算名稱,只是表示打包成war包而已),並將這個文件夾放到服務器根目錄下,即放到webapps下,最終路徑爲webapps/cmz_ReviewMybatis。最終項目結構如圖所示:

      3.如果idea的項目採用maven進行管理,最終上傳到服務器根目錄中的項目結構會有所不同,classes文件夾不在web-inf文件夾下,maven項目在服務器根目錄下的項目路徑如圖所示:

    4.PS:不論是maven做依賴管理還是不採用maven,所有項目所依賴的jar包都要上傳到webapps/項目名稱/web-inf/lib目錄下的,有時候可能依賴管理會出現一些問題,導致一部分jar包沒有上傳到tomcat的該目錄只是留在項目本地,從而導致tomcat啓動後該項目一些服務報錯,這是因爲在tomcat服務器中的項目缺少jar包依賴的原因,我們需要將這些jar包上傳到lib包即可,操作如下:

絕對路徑以'/'開頭的,從根目錄下訪問資源的路徑爲絕對路徑,如:/a/b/c

相對路徑只要不以'/'開頭的,相對於當前資源的路徑,,如:a/b/c或者../a/b/c或者../../a/b/c等。

三、轉發、重定向、靜態資源訪問的路徑

1、三者資源訪問路徑的根目錄'/'不是同一個路徑

請求分爲客戶端直接請求,服務器重定向並要求客戶端請求、客戶端直接訪問靜態資源請求。三種方式中,資源的請求路徑也會有所不同,相對路徑和絕對路徑也會有所不同:

  • 如果請求是轉發,/表示項目根目錄,所有的請求都是以項目根目錄作爲參照點和起始點進行訪問的,不論路徑是絕對路徑還是相對路徑。
  • 如果請求是重定向,或者瀏覽器請求靜態資源引用,/表示服務器根目錄,所有的請求都是以服務器根目錄作爲起始點和參照點進行訪問,不論路徑是絕對路徑還是相對路徑
  • 也就是說,除轉發,/表示項目根目錄;其他所有請求例如重定向或者請求靜態資源,/表示的都是服務器根目錄。

首先我們要明確一點:客戶端訪問的url是以服務器根目錄作爲起始點訪問的,雖然轉發是以項目根目錄作爲起始點訪問資源並且發生了跳轉,但是這一步是發生在服務器內部的,客戶端看不到,所以轉發過後客戶端的url不會因爲服務器轉發而發生變化。

我們結合例子說明。

案例

step1.構建一個servlet,轉發到index.jsp

//註解中用@表示註解聲明,註解中Servlet資源的路徑url爲虛擬路徑,也就是說我們的PeopleServlet的資源存放在項目的web/homework/people文件
//夾下,並以selAll命名,虛擬路徑雖然不存在在實際的項目根目錄下,但是是可以實際訪問到的。我們可以把它認爲是實際存在與項目根路徑下的,
//也就是web/下。
@WebServlet(value = {"/homework/people/selAll"})
public class PeopleServlet extends HttpServlet {

    private PeopleService peopleServlet = new PeopleServiceImpl();

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        List<People> peopleList = peopleServlet.show();
        req.setAttribute("list", peopleList);
        //相對路徑
        //只要不以/開頭的都是相對路徑,相對路徑是從當前資源所在的虛擬文件夾出發,找到其他資源的過程

        // 絕對路徑
        //只要路徑中以/開頭的都叫做全路徑,從項目根目錄web出發找到其他資源的過程

        //如果請求是轉發,/表示項目根目錄,也就是idea中當前web項目中的web文件夾路徑,爲web
        //由於我們的servlet目前資源在web/homework/people下,所以如果要跳轉到index.jsp(位置在web/index.jsp下)
        //需要向上跳躍兩個目錄,寫成../../index.jsp,或者寫絕對路徑/index.jsp。
        // PS:如果請求是重定向,或者瀏覽器請求靜態資源引用,如css,href,img,script。其中/表示的是tomcat文件夾下的
        // webapps文件夾,也就是tomcat/webapp文件夾,叫做服務器根目錄。我們的項目是放在webapp下
        // PS:也就是說,除了請求是轉發,/表示項目根目錄,其他所有請求例如重定向或者請求靜態資源,/表示的都是服務器根目錄。

        req.getRequestDispatcher("/index.jsp").forward(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doPost(req, resp);
    }
}

2.構建index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri = "http://java.sun.com/jsp/jstl/core" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
      <img src="/cmz_ReviewMybatis/image/a.png"><br/>
      <table>
          <tr>
              <th>編號</th>
              <th>姓名</th>
              <th>年齡</th>
          </tr>
          <c:forEach items="${list}" var="peo">
              <tr>
                  <td>${peo.id}</td>
                  <td>${peo.name}</td>
                  <td>${peo.age}</td>
              </tr>
          </c:forEach><br/>
      </table>

  $END$
  </body>
</html>

step3.在web.xml中添加歡迎頁面了列表

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
        <welcome-file>index.html</welcome-file>
        <welcome-file>default.jsp</welcome-file>
        <welcome-file>default.html</welcome-file>
    </welcome-file-list>
</web-app>

(1)上述爲轉發以及靜態資源訪問路徑的正確書寫,在啓動tomcat後直接訪問歡迎頁面,圖片會進行加載,但是由於我們沒有訪問Servlet的url,所以表中的數據並不會出現

(2)我們直接訪問PeopleServlet,PeopleServlet會獲取到表中人員數據,並將數據放進Request中進行轉發,轉發回到index.jsp中。所以index.jsp將圖片和數據庫人員數據顯示完全。

(3)如果我們在index.jsp中將img的路徑替換爲images/a.png後,

  • <1>直接訪問主頁index.jsp,是可以訪問到圖片資源的,因爲是靜態資源訪問並且訪問路徑是相對路徑,所以資源訪問的起始點是服務器根目錄,所以會在localhost:9090/cmz_ReviewMybatis/images/a.png下訪問,結合項目在服務器根目錄下的目錄結構,顯然是可以訪問到的。
  • <2>如果我們訪問localhost:9090/cmz_ReviewMybatis/homework/people/selAll,也就是訪問servlet,並轉發到index.jsp,則可以訪問到數據庫數據,但是訪問不到圖片了,因爲訪問的是靜態資源並且是相對路徑,所以參照點和起始點是服務器根目錄,所以會在localhost:9090/cmz_ReviewMybatis/homework/people/images/a.png下尋找,但是在服務器中資源並不放在這個位置,而放在localhost:9090/cmz_ReviewMybatis/images/a.png這個位置,所以自然訪問不到。

(4)如果我們將圖片資源路徑設置爲/images/a.png

  • <1>直接訪問主頁,訪問不到圖片
  • <2>通過轉發回到index.jsp訪問資源,仍然獲取不到圖片資源

總結

對於相對路徑和絕對路徑來說,我們最好書寫絕對路徑,如果書寫相對路徑,則要想好該相對路徑轉化爲絕對路徑是什麼。並且要根據請求是轉發還是非轉發請求來對相對路徑選擇不同的參照點,轉發的起始點/是項目根目錄,而重定向或者靜態資源請求的起始點/則是服務器根目錄。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章