剛開始使用Servlet時,由於web.xml的url-pattern和html中form表單的action的訪問路徑配置不對,老是出現404頁面不存在的錯誤。根本緣由是對Tomcat處理Http請求的過程理解不深。html
Tomcat處理Http請求過程:web
假設來自客戶的請求爲:
http://localhost:8080/TestTomcat/loginSucceed瀏覽器
1) 請求被髮送到本機端口8080,被在那裏偵聽的Coyote HTTP/1.1 Connector得到
2) Connector把該請求交給它所在的Service的Engine來處理,並等待來自Engine的迴應
3) Engine得到請求localhost/TestTomcat/loginSucceed,匹配它所擁有的全部虛擬主機Host
4) Engine匹配到名爲localhost的Host
5) localhost Host得到請求/TestTomcat/loginSucceed,匹配它所擁有的全部Context
6) Host匹配到路徑爲/TestTomcat的Context
7) path="/TestTomcat"的Context得到請求/loginSucceed,在它的mapping table中尋找對應的servlet
8) Context匹配到URL PATTERN爲/loginSucceed的servlet,對應於HelloServlet類
9) 構造HttpServletRequest對象和HttpServletResponse對象,做爲參數調用HelloServlet的doGet或doPost方法
10)Context把執行完了以後的HttpServletResponse對象返回給Host
11)Host把HttpServletResponse對象返回給Engine
12)Engine把HttpServletResponse對象返回給Connector
13)Connector把HttpServletResponse對象返回給客戶browser服務器
對以上過程不理解的能夠查看我轉載的博文:Tomcat工做原理詳解app
從以上過程能夠看出:一個完整的Http URL在Tomcat中被層層剝離,首先經過域名(上面的localhost)匹配虛擬主機,並將/TestTomcat/loginSucceed傳給對應主機;而後主機經過/TestTomcat匹配Context的path,將/loginSucceed傳給特定的Context(其實就是web應用,由於一臺主機上能夠同時運行多個web應用,即爲多個web應用提供服務器的功能);Context根據/loginSucceed來匹配Servlet,經過和url-pattern來匹配。因此咱們在web.xml中的url-pattern中不能帶項目名。而form表單中的action指向的URL是主機名後的部分,如上面的/TestTomcat/loginSucceed,因此此處必定要加上項目名(用來匹配哪一個Context,即web應用)webapp
如下是相似實踐:jsp
我建了個TestTomcat項目,建包com.heyujun.servlet,包下建類HelloServletui
HelloServlet類:url
注意:在類中的URL路徑配置有兩種方法:spa
一、response.sendRedirt("/TestTomcat/loginSucceed1.html");
//此處若是想讓瀏覽器訪問longinSucceed.html文件,必定要加上項目名,和.html;並且這會使瀏覽器顯示的URL改變
二、response.sendRedirt("loginSucceed1.html");若是不想帶上項目名,就直接寫HTML、JSP等文件的名字,必定不要加"/",不要寫成response.sendRedirt("/loginSucceed1.html");
猜想源碼是根據URL前是否有"/",若是有就將緊跟"/"的文件名做爲項目名。若是過寫成response.sendRedirt("/loginSucceed1.html");可能會把loginSucceed1.html做爲項目名,而機器上並不存在該項目,因此報404錯誤
public class HelloWorld extends HttpServlet { private String message; public void init() throws ServletException { // 執行必需的初始化 message = "Hello World"; } public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.sendRedirt("/TestTomcat/loginSucceed1.html"); // response.sendRedirt("loginSucceed1.html"); } public void destroy() { // 什麼也不作 } }
web.xml:
<url-pattern>/loginSucceed</url-pattern>//注意此處必定不要再加上項目路徑即Context的path,並且前面必定要加"/",不然啓動失敗
<?xml version="1.0" encoding="UTF-8"?> <web-app> <welcome-file-list> <welcome-file>welcome.html</welcome-file> <welcome-file>welcome.htm</welcome-file> <welcome-file>welcome.jsp</welcome-file> </welcome-file-list> <servlet> <!-- 類名 --> <servlet-name>HelloServlet</servlet-name> <!-- 所在的包 --> <servlet-class>com.heyujun.servlet.HelloServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>HelloServlet</servlet-name> <!-- 訪問的網址 --> <url-pattern>/loginSucceed</url-pattern>//注意此處必定不要再加上項目路徑即Context的path </servlet-mapping> </web-app>
welcome.html:
下面提交表單的action="/TestTomcat/loginSucceed",我以爲這裏的路徑配置也是和上面同樣有兩種方法,理由同HelloServlet類中所述
一、action="/TestTomcat/loginSucceed"
二、action="loginSucceed"
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>login page</title> </head> <body> <form action="/TestTomcat/loginSucceed"> //注意:此處必定要加上項目路徑即Context的path,用來找特定的webapp,後面的/loginSucceed纔是Servlet對應的url //而web.xml中的 url-pattern就是此處的/loginSucceed First name: <input type="text" name="fname"><br> Last name: <input type="text" name="lname"><br> <input type="submit" value="提交"> </form> </body> </html>