天天看點

JSP、Servlet中的相對路徑和絕對路徑 頁面跳轉問題通路servlet的路徑問題

1.JSP、Servlet中的相對路徑和絕對路徑 

    前提:假設你的Http位址為http://192.168.0.1/你的web應用為test,path="/test"那麼你的web應用URL為http://192.168.0.1/test/

    如果JSP,JS檔案放在WEB-INF目錄下根本無法通路的,JSP如果放在WEB-INF目錄下可以通過伺服器内部轉向進行通路(主要是為了頁面的安全),但是JS是通過用戶端向伺服器請求的,是以圖檔以及一些JS,CSS隻能放在WEB-INF外面 

  web應用的目錄結構: 

   test/web/

     css/ 

     js/

        test.js

     web-inf/ 

       classes/ 

       lib/ 

       user/ 

         a.jsp 

         b.jsp 

       images/       

       web.xml 

         <servlet-mapping> 

           <servlet-name>handleservlet</servlet-name> 

           <url-pattern>/handleservlet</url-pattern>此映射是相對于目前web應用的 

         </servlet-mapping> 

  所有相對路徑都是由"/"開頭的 。如:/image/a.gif,/user/main.jsp,大家知道在html中的相對路徑是這樣的:

  有個html檔案:a.html,其中有<link href="one.css" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" rel="stylesheet" type="text/css">,其中href屬性表示引用的css檔案的路徑。 

     one.css:表示one.css和a.hmtl處于同一個目錄 

     user/one.css:表示one.css處于a.html所在目錄的子目錄user中,即user是a.html在同一個目錄 。 

    ../one.css:表示one.css位于a.hmtl上一級目錄下, 

    ../../one.css:表示one.css位于a.hmtl上一級目錄的上一級目錄下, 

    ./:表示和a.hmtl同一目錄  

  我們稱上述相對路徑為html相對路徑

  1、 伺服器端的位址 

  伺服器端的相對位址指的是相對于你的web應用的位址,這個位址是在伺服器端解析的 (不同于html和javascript中的相對位址,他們是 由用戶端浏覽器解析的 )也就是說這時候在jsp和servlet中的相對位址應該是相對于你的web應用,即相對于http://192.168.0.1/test/的。 

  其用到的地方有: 

     forward:servlet中的request.getRequestDispatcher(address);這個address是在伺服器端解析的,是以,你要forwarder到user/a.jsp應該這麼寫:request.getRequestDispatcher("/user/a.jsp ")這個/相對于目前的web應用test,其絕對位址就是:http://192.168.0.1/test/user/a.jsp。 

     redirect:在jsp中<%response.sendRedirect("/rtccp/user/a.jsp");%> 

  2、 用戶端的位址 

  所有的html中的相對位址都是相對于http://192.168.0.1/的,而不是http://192.168.0.1/test/的 。 

  Html中的form表單的action屬性的位址應該是相對于http://192.168.0.1/的,是以,如果送出到user/a.jsp為:action="/test/ user/a.jsp" ;送出到servlet為action="/test/handleservlet" 

  Javascript也是在用戶端解析的,是以其相對路徑和form表單一樣。 

  3、 站點根目錄和css路徑問題  (jsp是伺服器端程式,位址是變化的,引用時一般用站點根目錄的相對路徑) 

  我們稱類似這樣的相對路徑/test/…. 為相對于站點根目錄 的相對路徑 。 

  當在jsp中引入css時,如果其相對路徑相對于目前jsp檔案的,而在一個和這個jsp的路徑不一樣的servlet中forward這個jsp時,就會發現這個css樣式根本沒有起作用。這是因為在servlet中轉發時css的路徑就是相對于這個servlet的相對路徑而非jsp的路徑了。是以這時候不能在jsp中用這樣的路徑:<link href="one.css" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" rel="stylesheet" type="text/css">或者<link href="../../one.css" target="_blank" rel="external nofollow" rel="stylesheet" type="text/css">類似href="one.css" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" 和../../one.css的html相對路徑是相對于引用這個css的檔案(a.jsp)的相對路徑 。而在servlet中轉發時就是相對于這個servlet的相對路徑了,因為jsp路徑和servlet路徑是不一樣的 ,是以這樣的引用肯定是出錯的。 

  是以這個時候,要用站點根目錄,就是相對于http://192.168.0.1/的目錄,以“/”開頭。 

  是以上述錯誤應更正為href=”/test/one.css” 類似的站點根目錄的相對目錄。這樣在servlet轉發後和jsp中都是相對于站點根目錄的相對路徑 ,就能正确使用所定義的css樣式了。

頁面跳轉問題:

Forward 高,  Redirect 低, 因為Redirect 的流程是這樣的,  request1  sent to server,  server return back to client, 然後

request2 then sent to server. 但是Forward 僅在server side處理, 對client side 是透明的. 由于Redirect 有兩次傳輸, 是以效率低. 

範圍: 

由于對request.setAttribute() 來說, 它攜帶的對象生存範圍隻在request内, 是以Redirect 方式會導緻request攜帶的對象丢失.

使用說明:

1. sendRedirect

     servlet和jsp裡面一樣

     response.sendRedirect(); 

2. include  這種也是上面提到的forward形式,request的值會儲存

    1)  servlet裡面

    request.getRequestDispatcher( "jsp2.jsp" ).include(request,   response);  

    2)  jsp裡面

    <jsp:include page= "include.jsp" />

說明 

頁面會同時包含頁面1和頁面2的内容,位址欄不變。 

使用request.setAttribute的内容,可以正常使用

3. forword

    1)  servlet裡面

    request.getRequestDispatcher( "jsp2.jsp" ).forward(request,   response);  

    2)  jsp裡面

    <jsp:forward page= "include.jsp" />

說明 

頁面會是頁面2的内容,位址欄不變 

使用request.setAttribute的内容,可以正常使用

3.JSP中用相對路徑引用JS,CSS檔案的三種情況

  第一種情況 最常見的情況

   一個tomcat上都跑多個工程, 用工程名來區分

   因為我的的URL是 :http://localhost/工程名 /home/index.jsp

   多了一個工程名,是以要加 <%=request.getContextPath() %>

   如:<script src="<%=request.getContextPath() %> /home/test.js"></script>

  寫<%=request.getContextPath() %>太麻煩,可以在每一個jsp檔案頂部加入以下内容後,

   Java代碼 

  1. <%   
  2. String path = request.getContextPath();   
  3. String basePath = request.getScheme()+"://" +request.getServerName()+":" +request.getServerPort()+path+"/" ;   
  4. %>   
  5. <base href="<%=basePath%>" > 

     就可直接使用 <script src=" /home/test.js"></script>了

   第二, 直接通路jsp檔案

   真實項目中, 一個tomcat上要是也跑了多個工程, 并用IP來區分

   url 是這樣的: http://localhost/home/index.jsp     注意這裡,是直接通路JSP檔案(jsp檔案不在web-inf下,可以直接通路),不是servlet也不是struts 。

   test2.js 與index.jsp 放在同一檔案夾下,下面用相對路徑來引入JS檔案 是OK 的:

  <script src=test2.js></script>

   index.jsp可以找到test2.js檔案

   第三種情況: servlet轉發到jsp(jsp在web-inf下,必須用servlet或action通路)

   在第二情況的基礎上,一個tomcat上要是也跑了多個工程, 并用IP來區分。

   我們通路的是servlet 或是struts的action , 再轉發到 index.jsp 

    url 是: http://localhost/***.do

    url 是: http://localhost/index.action

    這裡不是通路JSP檔案了

    下面是OK 的.

     <script src=/home/ test2.js></script>

    test2.js 前面一定要有/home/

    實際項目中, 通路 servlet或是struts的action最多, 是以這裡要使用<script src=/home/test2.js></script>。

----------------------------------------------------------------------------------------------------------------------------------

通路servlet的路徑問題

一、url-pattern的三種配置

  在web.xml配置檔案中配置有關Servlet的時候,<url-pattern>标簽是用于配置目前Servlet攔截的路徑,也就是說,用戶端浏覽器通路<url-pattern>标簽配置的路徑才能通路對應Servlet内容。

關于攔截路徑的配置方式其實有三種方式:

  1. 完全路徑比對:是以“/”開始,路徑中間不能包含通配符“*”,例如:/firstServclet,表示通路路徑為http://localhost:8080/08_servlet/firstServlet。
  2. 目錄比對:是以“/”開始,以“/*”結尾的,例如:/firstServlet/*,表示通路路徑為http://localhost:8080/08_servlet/firstServlet路徑下任意内容。
  3. 擴充名比對:是以“*”開始,不能以“/”開始,以“.xxx”結尾,例如:*.do,表示通路路徑為所有擴充名為“.do”的路徑。

值得注意的問題:

  1. 在一個<servlet-mapping>标簽中,可以配置多個<url-pattern>标簽。也就是說,一個Servlet可以攔截多個不同路徑的通路。
  2. 上述三種配置路徑方式具有優先級:完全路徑比對 -> 目錄比對 -> 擴充名比對。

下面通過一些測試,來看看路徑配置的三種方式:

如下有一些映射關系:

  1. Servlet1 映射到 /abc/*
  2. Servlet2 映射到 /*
  3. Servlet3 映射到 /abc
  4. Servlet4 映射到 *.do

問題:

  • 當請求URL為“/abc/a.html”,“/abc/*”和“/*”都比對,哪個servlet響應?Servlet1
  • 當請求URL為“/abc”時,“/abc/*”和“/abc”都比對,哪個servlet響應?Servlet3
  • 當請求URL為“/abc/a.do”時,“/abc/*”和“*.do”都比對,哪個servlet響應?Servlet1
  • 當請求URL為“/a.do”時,“/*”和“*.do”都比對,哪個servlet響應?Servlet2
  • 當請求URL為“/xxx/yyy/a.do”時,“/*”和“*.do”都比對,哪個servlet響應?Servlet2

  如果用戶端浏覽器請求的路徑是錯誤時,頁面會顯示404錯誤内容。這是因為所有釋出到Tomcat伺服器的Web應用程式的web.xml檔案都繼承了Tomcat伺服器安裝目錄中conf目錄中的web.xml檔案。當通路路徑是錯誤的,或者對應Servlet沒有配置,實際上會執行Tomcat伺服器中的web.xml的相關配置,具體内容如下:

1 <servlet>
 2     <servlet-name>default</servlet-name>
 3 
 4 <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
 5     <init-param>
 6         <param-name>debug</param-name>
 7         <param-value>0</param-value>
 8     </init-param>
 9     <init-param>
10         <param-name>listings</param-name>
11         <param-value>true</param-value>
12     </init-param>
13     <load-on-startup>1</load-on-startup>
14 </servlet>
15 <servlet-mapping>
16     <servlet-name>default</servlet-name>
17     <url-pattern>/</url-pattern>
18 </servlet-mapping>      

1.2. 相對路徑與絕對路徑

之前我們開發的Servlet,在用戶端浏覽器中都是直接在位址欄中輸入路徑來通路的。如果建立一個頁面來通路Servlet應該怎麼樣呢?下面我們來看一看:

  • 在Web工程中的WebRoot目錄下,建立一個新目錄名為“html”,然後在該目錄下建立一個新的HTML頁面。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

  <head>

    <title>01.html</title>

    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">

    <meta http-equiv="description" content="this is my page">

    <meta http-equiv="content-type" content="text/html; charset=UTF-8">

  </head>

  <body>

    <h1>相對路徑通路Servlet</h1><br>

<a href="" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" >相對路徑通路Servlet</a>

<h1>絕對路徑通路Servlet</h1><br>

<a href="" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" >絕對路徑通路Servlet</a>

  </body>

</html>

  • 在Web工程中的WebRoot目錄下,建立一個新的HTML頁面。
1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 2 <html>
 3   <head>
 4 <title>02.html</title>
 5     <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
 6     <meta http-equiv="description" content="this is my page">
 7     <meta http-equiv="content-type" content="text/html; charset=UTF-8">
 8   </head>
 9   <body>
10     <h1>相對路徑通路Servlet</h1><br>
11     <a href="">相對路徑通路Servlet</a>
12     <h1>絕對路徑通路Servlet</h1><br>
13     <a href="">絕對路徑通路Servlet</a>
14   </body>
15 </html>      
  • 在Web工程中建立一個Servlet。
public class PathServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("成功通路到Servlet");
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}      
  • 配置Web工程的web.xml檔案。
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  <servlet>
    <servlet-name>PathServlet</servlet-name>
    <servlet-class>app.java.servlet.PathServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>PathServlet</servlet-name>
    <url-pattern>/pathServlet</url-pattern>
  </servlet-mapping>
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>      
  • 将目前Web工程釋出到Tomcat伺服器,并啟動Tomcat伺服器。
  • 打開浏覽器,分别通路01.html、02.html和PathServlet。

 通路01.html的路徑:http://localhost:8080/08_servlet/html/01.html。

 通路02.html的路徑:http://localhost:8080/08_servlet/02.html。

 通路PathServlet的路徑:http://localhost:8080/08_servlet/pathServlet。

  • 根據上述的通路路徑,可以知道在01.html和02.html頁面中,通過絕對路徑通路PathServlet是相同的。
  • 在01.html和02.html頁面中,通過相對路徑通路PathServlet是不同的。

在01.html頁面中利用相對路徑通路PathServlet應該是../pathServlet。原因是pathServlet是在01.html頁面的父級目錄中。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>01.html</title>
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="this is my page">
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <h1>相對路徑通路Servlet</h1><br>
    <a href="../pathServlet">相對路徑通路Servlet</a>
    <h1>絕對路徑通路Servlet</h1><br><a href="http://localhost:8080/08_servlet/pathServlet" target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow" >絕對路徑通路Servlet</a>
</body></html>      

² 在01.html頁面中利用相對路徑通路PathServlet應該是./pathServlet或直接通路攔截名稱pathServlet。原因是pathServlet與02.html頁面處在同一級别的目錄中。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>02.html</title>
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="this is my page">
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <h1>相對路徑通路Servlet</h1><br>
    <a href="pathServlet">相對路徑通路Servlet</a>
    <h1>絕對路徑通路Servlet</h1><br>
    <h1>絕對路徑通路Servlet</h1><br>
    <a href="http://localhost:8080/08_servlet/pathServlet">  絕對路徑通路Servlet</a>
  </body>
</html>      

---------------------------------------------------------------------------------------------------------------------------------------

servlet中,所有路徑的配置都要用絕對路徑。

什麼是絕對路徑,就是以“/”開頭的路徑(開發中就這樣了解)。

實際開發中,“/”所代表的含義不同,但主要分以下兩種情況:

1.servlet内部配置路徑

servlet内部的含義就是:在用戶端看不到,全是在(應用)背景處理的部分(簡單說,就是除了JSP以外的所有地方)。包含以下2點:

a. web.xml中servlet 配置的路徑

<servlet>

  <servlet-name>helloWorld</servlet-name>

  <servlet-class>

   com.bill99.li.servlet.HelloWorldServlet

  </servlet-class>

 </servlet>

 <servlet-mapping>

  <servlet-name>helloWorld</servlet-name>

  <url-pattern>/test1/helloWorld</url-pattern>

 </servlet-mapping>

我們配置的這個“ /test1/helloWorld”,前面必須加“/” ---- 該“/”代表我們應用的名稱。比如我們的應用名是“test”,那通路我們應有的位址就是: http:// 192.168.XX.XX:8080/test ,說白了就是代表項目的名稱。

“ /test1/helloWorld”代表的路徑就是http:// 192.168.XX.XX:8080/test/test1/helloWorld

b.forward轉發的路徑(注意:不包含redirect重定向)

做完背景業務邏輯處理後,需要做頁面的跳轉,比如:

req.getRequestDispatcher("/pages/succ.jsp").forward(req, resp);

這時候跳轉的頁面"/pages/succ.jsp"也必須添加“/”,它代表的含義也一樣,是我們應用的名稱。

總結:

在應用内部,“/”代表的就是應用的名稱!!!

2.頁面配置的路徑

頁面是指什麼 ------  肯定是指我們的JSP頁面,而JSP頁面是服務端解析的,對我們而言是下載下傳到用戶端,讓浏覽器解析為HTML展示出來的頁面。

比如,我們的應用url是:http:// 192.168.XX.XX:8080/test

那站點的路徑就是:http:// 192.168.XX.XX:8080/   --- 很明顯 test 是應用名

對用戶端的浏覽器而言,它認識的隻有站點,也就是說,我們的jsp頁面,“/”代表的是站點名。

是以在“/”後需要添加上我們應用的名稱才能正确的通路到。(也容易了解,一個tomcat下可以部署多個應用,就相當于一個站點多個應用,怎麼差別不同的應用呢,當然是不同應用名啦-----這個需要和上面的servlet内部配置路徑區分了解一下啊,因為servlet本身就部署在服務端,在站點内部了,内部處理肯定知道它是站點下的哪個應用内,但對于外部而言,隻知道一個站點IP。)

頁面主要表現有以下3個地方:

a. form的action路徑配置

頁面舉例:

<form action=" /test /test1/helloWorld" method="post">

解析:

應用名是test,/ 代表站點的url http:// 192.168.XX.XX:8080/,是以/test代表 http:// 192.168.XX.XX:8080/test

而/test1/helloWorld代表servlet在web.xml中配置的通路路徑,所有上面的action可以正确的通路。

但是在真正的應用中,我們經常這樣寫:

<form action="${pageContext.request.contextPath}/test1/helloWorld" method="post">

${pageContext.request.contextPath} 的效果就是"/應用名" ,這裡等于 /test

一樣的效果,不解釋啦。

b. 頁面資源引用

同樣,隻要是頁面中引入的東西(常常需要引入CSS,JS,圖檔等),都要如此寫,比如

<script type="text/javascript" src="${pageContext.request.contextPath}/pages/event/js/addevent.js"></script>

c. jsp/servlet的重定向 redirect

首先必須了解重定向的概念:重定向其實向伺服器發送了2次請求,第一次把請求url告訴給伺服器,伺服器看到這個請求的狀态碼,馬上明白該url是需要浏覽器來重新去請求的url,于是呢把該url顯示在浏覽器的位址欄内,再次向伺服器請求(第二次了吧),伺服器響應,然後傳回。

很明顯,隻要和頁面打交道的,“/”都代表站點名,需要在後面添加應用名以區分是哪個應用的請求。所有。。。。不解釋也明白了吧!

總結:

所有涉及前端頁面的地方,“/”代表的是站點名,需要我們在“/”加上應用名以明确應用服務!!

=========================================================

基本上可以總結為兩點:

a. servlet中所有通路路徑都要用絕對路徑“/”開頭

b. 頁面中“/”表示站點路徑(在用戶端展現出來,隻知道它的站點路徑,所有需要“/”後追加應用名來區分屬于站點下的哪個應用),其他地方的“/”表示應用路徑(在服務端的應用程式内調用,肯定是相對于應用的路徑啦)