一、doGet()與doPost()
我們在TestServlet類中重寫doGet()、doPost()、service()。
import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class TestServlet extends HttpServlet{ public TestServlet() {}; @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("doPost"); } @Override protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("sevice"); } @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("doGet"); } }
同時在WebContent創建一個Test.html文件
<!DOCTYPE html> <!-- http://localhost:8080/TestServlet/Test.html --> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <!--表單提交調用servlet --> <!-- http://localhost:8080/TestServlet/TestServlet.html --> <form name = f1 action = "/TestServlet/TestServlet.html" method = "get"> username:<input type = "text" name = "username"></input> pwd:<input type = "password" name = "pwd"></input> <input type = "submit" value = "提交"> </form> </body> </html>
我們點擊提交按鈕會發現控制台輸出sevice,說明調用的service()方法。
我們看下API中關於service()方法的介紹:接收標准的HTTP請求,並將其
發送到此類中定義的doXXX方法,不需要重寫這個方法。
也就是說請求會先傳遞到service()中,在由其發送給doXXX方法。
只要service()被重寫了,請求就會一直傳遞給service().
我們將service()方法注釋
再來提交信息,看下會執行那個方法。
可以看4到此時執行的是doGet,這時因為在form中設置了method=“get”,
代表提交方式為get,請求先提交給service(),然后再由其轉發給對應的doXXX方法。
<form name = f1 action = "/TestServlet/TestServlet.html" method = "get">
由於設置了提交方式為get,所以是執行給doGet()。
doGet調用時我會發現在地址欄顯示傳遞給servlet的數據:
這樣是不安全的,而且采用get方式傳遞的數據有大小限制,后面跟隨的信息字節不能超過1.3k。
我們來看下API中對doGet()的敘述:
由服務器調用,以允許servlet處理get請求,重寫此方法時,讀取請求數據、
寫入響應頭、獲取響應的寫入器或輸出流對象,最后寫入響應數據。
如果將"get"設置為“post”,則會執行doPost()方法。
采用post傳遞數據不會在URL上顯示出來,有一定的安全性。
而且post可以傳遞的數據理論上是無限大的。
二、Servlet生命周期
2.1實例化一個Servlet
創建一個servlet實例
2..2調用Init()
調用一次。
2.3調用service方法(doGet、doPost)
被調用多次,每次請求調用。
2.4調用destory方法。
調用一次銷毀Servlet
我們創建一個TestServlet類,繼承HTTPServlet。
重寫里面的intI()、doget() doPost() destroy() 並添加一個無參構造器。
HTML采用上述代碼。
import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class TestServlet extends HttpServlet{ public TestServlet() { System.out.println("TestServlet"); }; @Override public void init() throws ServletException { System.out.println("Init"); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("doPost"); } @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("doGet"); } @Override public void destroy() { System.out.println("destroy"); } }
然后將項目添加到Tomcat上。
點擊提交我們會發現控制台中打印的信息:
一開始首先實例化一個Servlet,然后初始化,我們提交數據時調用對應的servlet方法(doGet或doPost)。
我們繼續刷新會發現控制台繼續打印doGet,但實例化和初始化只調用一次,有請求是調用則調用doGet方法。
最后我們將Tomcat停止運行,會發現控制會輸出destroy,此時servlet被銷毀了。
三、獲取初始化參數
首先在web.xml文件中配置初始化參數。
初始化參數分為:局部初始化,只有當前Servlet可以獲取其參數。
全局初始化:所有Servlet都可以獲取其參數。
我們首先要在web.xml中設置初始參數信息。
<context-param> <!-- 設置全局參數 --> <param-name>context-param</param-name> <param-value>localhost:3306/mydatabase</param-value> </context-param> <servlet> <servlet-name>firstServlet</servlet-name> <servlet-class>com.servlet.firstServlet.TestServlet</servlet-class> <init-param> <!-- 設置局部初始化參數 --> <param-name>initParam</param-name> <!-- 設置參數名稱和值 --> <param-value>initParam</param-value> <!-- 該初始化參數是設置在當前這個Servlet下的--> </init-param> <!-- 所以也只有當前Servlet可以獲取到--> </servlet> <servlet-mapping> <servlet-name>firstServlet</servlet-name> <url-pattern>/TestServlet.html</url-pattern> </servlet-mapping>
設置好了參數,我們來獲取參數。
import java.io.IOException; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class TestParam extends HttpServlet{ private String initParam = null; private String contextParam = null; @Override public void init() throws ServletException {
//獲取初始化參數,和全局參數 this.initParam = this.getInitParameter("initParam"); this.contextParam = this.getServletContext().getInitParameter("context-param"); } @Override //在doGet中輸出參數。 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("initparam:"+initParam); System.out.println("contextParam:"+contextParam); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doGet(req, resp);//調用doGet方法 } }
初始化之后我們提交數據就會調用doGet方法,將獲取到的初始化參數打印出來。
四、頁面跳轉
4.1請求重定向
請求重定向,即進行頁面跳轉。
需要用到void sendRedirect(java.lang.String location)
當location是帶有/的話,將被解釋為容器的根,
即此時的地址會被解釋為localhost:8080+location。
例如localtion為"/fail.htm",此時跳轉的地址位localhost:8080/fail.html
當沒有‘/’時,將解釋為相對於當前請求的URL地址。
例如localtion為"fail.htm",此時跳轉的是localhost:8080/項目名/fail.html
使用指定的重定向URL向客戶端發送臨時重定向響應。
獲取表達數據采用getParameter(Stringz name),
import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class TestServlet extends HttpServlet{ private String initParam = null; private String contextParam = null; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//獲取HTML中設置了 name = "username" 標簽的數據 String name = req.getParameter("username");//獲取表單提交的數據, //如果輸入框的內容等於百度則跳轉到百度,其他跳轉到fail.html if("baidu".equals(name)) //跳轉到百度 resp.sendRedirect("http://www.baidu.com"); else //跳轉到當前工程WebContext目錄下的fail.html resp.sendRedirect("fail.html"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doGet(req, resp); } }
采用重定向的跳轉方法,不共享request的信息。
當username輸入框的為百度時則跳轉到百度首頁,
其他的輸入跳轉到當前項目WebContent下的fail.html
重定向時地址欄會顯示重定向資源的路徑。
4.2請求轉發:將當前請求轉發到另一個資源處理。
請求轉發時我們需要用到一個接口 RequestDispatcher。
TequestDispatcher:接收客戶端請求,並將請求發送到服務器上的其他資源(如servlet、html文件或jsp文件)。
主要方法:
void forward(ServletRequest request, ServletResponse response)
將請求轉發到服務器上另一資源,request為客戶端對Servlet的請求的request對象,
response為表示servlet返回到客戶端的響應的servletResponse對象
那么要想調用轉發,我們必須向獲取一個實現了RequestDispatcher接口的對象。
這時可以request下的RequestDispatcher getRequestDispatcher(java.lang.String path)方法
該方法獲取一個RequestDispathcher對象,path為指定資源的路徑名,可以為相對路徑,
當為相對路徑時必須是相對當前Servlet而言的。
請求轉發只能在本應用資源下,不能先請求重定向那樣跨應用(重定向到百度)。
import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class TestServlet extends HttpServlet{ private PrintStream out = System.out; private String initParam = null; private String contextParam = null; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter out = resp.getWriter();
out.println("servlet.."); //設置資源路徑 RequestDispatcher rd = req.getRequestDispatcher("fail.html"); //轉發,由於是攜帶req、resp轉發的,所以轉發后的資源可以獲取其數據。 rd.forward(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doGet(req, resp); } }
但提交表單,進入doGet()方法后,會轉發請求到指定的資源。
我們會發現請求轉發並沒有像重定向那樣將URL變為fail.html,這時因為此時轉發的是請求。
而且當前servlet輸出的信息(“servlet..”)也沒有打印出來,
轉發就相當於將事情交給另外一個人去處理。自己不插手了。
4.3請求包含:將其他資源的響應結果包含到當前Servlet中。
請求包含和請求轉發都是RequestDispatcher中定義的方法。
所以都是首先獲取RequestDispatcher對象,然后調用對應方法。
請求包含是調用的是void include(ServletRequest request, ServletResponse response)
import java.io.IOException; import java.io.PrintStream; import java.io.PrintWriter; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class TestServlet extends HttpServlet{ // private PrintStream out = System.out; private String initParam = null; private String contextParam = null; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { PrintWriter out = resp.getWriter(); out.println("servlet"); //設置資源路徑 RequestDispatcher rd = req.getRequestDispatcher("/fail.html"); //轉發,由於是攜帶req、resp轉發的servlet..,所以轉發后的資源可以獲取其數據。 rd.include(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doGet(req, resp); } }
請求包含的url也不會發生變化,並且包含了fail.htm界面。
如果沒有servlet,界面上會顯示html所代表的內容,即Fail。
但當前界面將fail.htm的代碼包含進來了,破壞了html的結構,
所以顯示的是servlet+html代碼。
包含是當前Servlet將另外一個資源及其處理流程包含進來。
轉發時當前Servlet將事情交給另外一個資源去完成。
請求轉發與請求包含的區別可參閱:https://blog.csdn.net/u013425438/article/details/81606248