天天看點

html中表單的action屬性作了什麼?建議改進,轉發用ServletContext擷取路徑

表單一般是浏覽器實作的,當然也有程式設計語言,比如python的post方法,然後配合任意一門背景語言比如javaweb來擷取post資料。

在此聲明,post不安全。post和get的詳細差別請先研究http協定詳細的規格再結合浏覽器F12抓個包詳細看。(或者wireshark,如果你用的https的包還是用浏覽器友善)

因為是浏覽器實作的,是以post也是明文的!!!

從wireshark抓包看到是明文的。

表單的幾個屬性非常重要。

name屬性如果寫,則送出表單時才會帶上這個資料。

且Post是由&分割的。

也就是說你這樣:

URL?a=1&b=2

post也是這樣,隻不過post跟在了

request body

裡面。

關于請求和響應,一句話概括:

請求:

請求行,請求頭,請求體(簡單的參數傳遞)

響應:

響應行,響應頭,響應體(html/css/js/image/mp3/m3u8/...)

然後跟在一堆請求包裡面。

響應表單中有name屬性的則是:

請求行…

請求頭…

請求體:

a=1&b=2

<form action=”URL”></form>
           

這個URL非常的坑。故且可以了解為絕對URL和相對URL。

知道參數是URL。

那麼,什麼是URL?

我講個故事。

以前的一群科學家們在用美國二戰時留下的網絡時,想搞1個分布式系統。當時想的是制造這樣一種網絡,可以讓人點一下,就可以通路位于某個Ip的機器的資源。由于這種點一下點一下的方式,(你可以把滑鼠放到1個超連結上,看到滑鼠變成了抓手模樣)實在是太棒了。于是好多不搞計算機的也加入近來,他們也讓自己的及其變成伺服器,這樣他們就組成了一個巨大的分布式系統。而這個系統就是www,簡稱web。

圍繞着web,就有好多事情。最重要的就是關于浏覽器和伺服器。這兩個都是建立在作業系統之上的應用層軟體。前前後後美國的幾個大公司都參和了不止一腳,每參和一腳就會讓前段程式員氣到罵娘。

總之,有一群無聊的人讓http協定成了www明面上使用最廣的協定,圍繞着http,聚集着一堆增值服務,因為http太簡陋,沒啥玩的。這就好比我買了個樹黴派結果沒買配套硬體一樣。。。

總之呢,怎麼确定這個大的分布式系統中我,要到哪裡,去抓某個資源呢?也就是

<a href="" target="_blank" rel="external nofollow"

寫什麼呢?如果中國銀行寫了

www.bank.com

,美國銀行也寫了

www.bank.com

,那不就亂了麼?這個時候,就需要唯一的确定某個位址。是以啊,用wireshark抓一下包就會發現一堆DNS流量,其實就是去幹這個事情了。那其中肯定會牽扯到金錢交易,畢竟域名伺服器幫你解析了麻,雖然幹的活簡單,可是架不住這麼多人用,你也沒辦法。這就是标準的重要性。

再來看看URL的格式就會發現一些有趣的事情。

協定名://主機名:端口/路徑

,我們寫form表單,讓浏覽器去請求的時候,其實我們隻需要寫

baidu.com

,但是浏覽器在拿到這個字元串後立刻變成了

http://www.baidu.com

,然後去取資源。

www.baidu.com

這台主機,然後傳回一個

index.html

這個頁面。這樣就ok了。

是以我們form表單在寫的時候寫的

/

代表什麼呢?

根路徑,到底是相對于誰的根呢?

是背景代碼的根呢?還是什麼?

我們需要深入了解伺服器程式的設計。

早期的html也就是靜态頁面,沒什麼好糾結的。伺服器也就是看用戶端要取這個資源,然後就傳回對應的html頁面。在這種情況下,伺服器不需要跟用戶端保持一個連接配接,注意,http是無連接配接的。它雖然是基于tcp協定,tcp協定保證了可靠連接配接,但是http并不會建立連接配接,就是一個簡單的請求(get/post/head/…),響應。這種情況下伺服器是不需要跟你保持1個連接配接的。你上web也很無聊啊,就是看看這個站點釋出了什麼,連個互動都沒有。可是你要知道,今天web遍布全球,是以這種情況是不會持續很長時間的。于是,http馬上更新到了1.1,但其實是優化了用戶端的上網速度而已。這中間有些技術出來攪混這譚水,比如java applet。這是什麼呢?就是伺服器有個小程式,叫做applet,然後發給你的浏覽器,你的浏覽器就可以動态的給你展示一些内容,就像伺服器給你提供的服務一樣,不過這時是緩解了伺服器的壓力。想象一下,當時可能有個人發了個有趣的小遊戲,然後放到一個大論壇,這時很多人都下載下傳然後去玩。是不是好快樂?但是這就暴露了安全問題。導緻後來哪怕是cookie那個RFC草案的提出,都會被無限放大為侵入計算機系統的病毒,估計就是這個時候人們變得草木皆驚了。然後出現了像php這樣的腳本語言。所謂腳本是什麼呢?就是浏覽器不是傳過來1個請求麻,然後解析一下,畢竟是html頁面而已,伺服器抓去到事實上的請求位址,就開始去解析,然後可能還經過了各種庫的處理,ok,伺服器處理完了,就把處理好的資料再塞到html頁面發給浏覽器裡面。

是以,form的action屬性其實是說,我這裡有post的資料(一般form也都是post請求),我要發送到這個action這個url下面。通過url可以唯一的确定伺服器的位址。–伺服器預設端口是80,協定是http。是以,

協定名://主機名:端口/路徑

已經知道了

協定名://主機名:端口

,就剩路徑了。你要知道,現在的伺服器你給的路徑都不是某個具體的腳本檔案了,而是伺服器的内部路徑,也就是一串字元串,你看不出規律的,這即友善也安全。不然我抓個圖看看:

html中表單的action屬性作了什麼?建議改進,轉發用ServletContext擷取路徑

可以看到,支付寶的action位址是詳細的URL,雖然指向的是本頁面。

是以,action作了把資料送到這個URL定位的資源上面。資源可以是超文本,視訊,音頻,甚至動态處理的腳本語言,伺服器的某個處理路徑…

順便說一下,想實施發送一個post,需要在form中寫

<input type="submit"

<button onclick="函數"

來發送post或觸發js發送post請求。

但如果post到的位址它不接受,伺服器找不到等,那這個資料就發送不了。

那麼,

<form action='#'

幹了什麼呢?

#

簡單的來說是把資料送到了目前頁面進行處理,action什麼都不加或者幹脆不寫action都是把資料送到目前頁處理,

#

是比較老的寫法了。

再說說後段怎麼辦。

action可以是絕對URL,和相對URL。絕對的就參考支付寶的寫法,是https就寫443,否則寫80。因為考慮是絕對的就寫全為好。

回想一起那我寫的這幾篇文章:

https://blog.csdn.net/u010563350/article/details/81147457

https://blog.csdn.net/u010563350/article/details/81351274

https://blog.csdn.net/u010563350/article/details/81351280

,

是以,寫絕對路徑絕對是無可争議,而且不容易出錯。而寫絕對路徑比較省力的寫法,(也是避免把頁面寫死的辦法)就是後兩種。

當然也可以看看這篇文章:https://blog.csdn.net/lutinghuan/article/details/6450174?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1.channel_param

,是以,就是找到了項目的首頁嘛。其中的get什麼的都是tomcat提供的方法而已。

然後就是tomcat在運作時在response時會把其中的替換掉。

然後就是相對路徑了。

相對路徑會寫

/

開頭,

/項目名/

才到改項目的根。有幾點非常不友好,1.Linux中的絕對路徑是以

/

開頭,這就容易讓人先入為主而混淆。

2.在伺服器,例如tomcat中,生成html頁面發送給用戶端的時候會先看自身的配置。這個時候如果需求變了,想要把路徑改改,會造成非常大的困擾。

為了讓你們再少走點坑,我所幸把路徑這個坑給你們将清除了。

在linux中,目錄以

/

分割,

在windows中,目錄以’‘分割。

但是Java它處理’'是有點毛病,必須得

\\

代表1個

\

。也就是你想要D盤的這個路徑

D:\MySite\WebContent\WEB-INF

的檔案,你必須這樣寫:

D:\\MySite\\WebContent\\WEB-INF

。其他程式設計語言是沒這個坑的。

\

一般用來指逃避字元,也就是把1個正常的字元轉化為特殊的含義,有人也稱為轉移字元。

這也就是Java檔案時必須這樣:

File f = new File("D:\\MySite\\WebContent\\WEB-INF");

的原因。而且Java還不支援多行字元,類似于python和go中這樣的寫法:

#python
str='''

bala1
bala2
bala3

'''
//go
str :=  ```
bala1
bala2
bala3
`` `
           

這些說到底是檔案系統的路徑問題了。Linux沿用的Unix檔案系統的路徑,而Windows沿用的是Dos系統的檔案路徑。Linux最初是找着Unix抄的作業系統,Windows最初是照着Dos改的MsDos系統加的外皮。

而相對路徑我認為最簡單的方式是看浏覽器的位址欄,查找目前所在路徑,然後再根據這個檔案(jsp)找到對應的路徑。

html中表單的action屬性作了什麼?建議改進,轉發用ServletContext擷取路徑

這個說的很清除,但是不建議使用相對路徑。後面的架構會自己處理類似的路徑,而不依賴與具體的伺服器。如spring架構,甚至隐藏自己的路徑。

https://blog.csdn.net/bbb695480667/article/details/53838321#commentBox

這篇寫的也不錯。

建議

都寫成

絕對路徑

(某些情況下使用相對路徑更監簡單,不用用代碼擷取路徑),絕對路徑的URL的協定名,主機域名,端口,這些

靠代碼來動态擷取

。(代碼規範由JavaEE提供,是以具有

通用性

)

前端的form表單怎麼寫?
1.現在目前jsp頁面中寫:

<%@ page language="java" contentType="text/html; charset=UTF-8"

    pageEncoding="UTF-8"%>

<head>

<%

    String path = request.getContextPath();

    // 獲得項目完全路徑(假設你的項目叫MyApp,那麼獲得到的位址就是http://localhost:8080/MyApp/):

    String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()

            + path + "/";

%>

</head>
2.然後在form表單中這樣寫:
<form action="<%=bashPath%>login.jsp" method="post">
	    username:<input type="text" value="" name="username" id="username"/>	<br>
		password:<input type="password" value="" name="password" id=""/><br>
		<input type="submit" value="submit" name="" id=""/>
</form>
3.這樣伺服器端:http://localhost:8080/MyApp/login.jsp就收到了使用者名和密碼。
如果是sevlet則把login.jsp換成loginServlet
http://localhost:8080/MyApp/loginServlet
           
後端的轉發和重定向方法怎麼寫?
重定向是給浏覽器位址讓浏覽器去找自己的資源,是以這種情況下必須給全部的URL。即

完全URL

這個時候的

/

代表了外部路徑

http:localhost:8080

,是以需要給出項目名,寫成:

/MyApp/login.jsp

的樣子。
/*
 * 重定向有三種路徑書寫方式
 * 		1.絕對路徑
 * 		2.以"/"開頭的相對路徑
 * 		3.不以"/"開頭的相對路徑
 */
public class RedirectServlet extends HttpServlet {
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.sendRedirect("http://localhost:8080/javaee/jsp/b.jsp");
		/*
		 * 2.以"/"開頭的相對路徑
		 * 		此時,/代表整個web工程的路徑,即http://localhost:8080/
		 */
//		response.sendRedirect("/javaee/jsp/b.jsp");
		/*
		 * 3.不以"/"開頭的相對路徑
		 * 		此時是相對于目前資源的相對路徑
		 * 		目前資源路徑為:http://localhost:8080/javaee/RedirectServlet
		 * 		即表示:RedirectServlet在路徑http://localhost:8080/javaee之下
		 * 		而b.jsp在http://localhost:8080/javaee/jsp/b.jsp
		 * 		是以最終位址寫為:jsp/b.jsp
		 */
//		response.sendRedirect("jsp/b.jsp");
		
	}
 
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}
 
}

           

轉發不同,轉發是内部找内部的資源,是以使用絕對的URL伺服器是不認識的。是以使用相對路徑。

因為這個時候是在項目内部,是以

/

的含義是

目前項目内部的資源根路徑(不是檔案系統根路徑)

,也就是從外部看

http://localhost:8080/MyApp/

這個位址。
/*
 * 伺服器端的路徑不能是絕對路徑,隻能是相對路徑,也分為以/開頭和不以/開頭兩種
 * 		1.以"/"開頭的相對路徑
 * 		2.不以"/"開頭的相對路徑
 */
public class DispatcherServlet extends HttpServlet {
 
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		/*
		 * 1.以"/"開頭的相對路徑
		 * 		此時,/代表目前web項目,即:http://localhost:8080/javaee
		 */
//		request.getRequestDispatcher("/jsp/b.jsp").forward(request, response);
		/*
		 * 2.不以"/"開頭的相對路徑
		 * 		相對于目前資源的相對路徑
		 * 	此時,目前資源的路徑為:http://localhost:8080/javaee/DispatcherServlet
		 *  是以要轉發去的資源的路徑以:http://localhost:8080/javaee開頭
		 */
		request.getRequestDispatcher("jsp/b.jsp").forward(request, response);
	}
 
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}
           

改進,轉發用ServletContext擷取路徑

/*
 * ServletContext擷取資源必須是相對路徑,不能是絕對路徑,但不管是以/開頭,還是不以/開頭,
 * 都是相對于目前資源的相對路徑
 * 
 */
public class ServletContextServlet extends HttpServlet {
 
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		String path1 = this.getServletContext().getRealPath("/a.properties");
		String path2 = this.getServletContext().getRealPath("a.properties");
		System.out.println(path1);
		System.out.println(path2);
		//輸出的位址一樣
	}
 
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}
 
}
//上面是規則,下面是代碼:
           

下面以一個管理系統為例進行說明:

該管理系統沒有注冊功能,就是管理者進行操作添加管理者進而得到使用者名和密碼。

sc為學生選課管理系統的縮寫。

//1.通路http://localhost:8080/sc頁面
//預設的,web.xml設定的歡迎頁面是http://localhost:8080/sc/login.jsp
//2.使用者輸入使用者名和密碼,然後發送到
//http://localhost:8080/sc/LoginController
//3.Controller進行後端的使用者名和密碼校驗,
//如果成功則重定向使用者到http://localhost:8080/sc/index.jsp
//失敗則重定向到http://localhost:8080/sc/login.jsp。
public class ServletContextServlet extends HttpServlet {
 
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
	
		
		
	}
 
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);

//此時的index.jsp和login.jsp都在

		
	}
 
}