- M:model 模型 負責各個功能,javaBean
- V:View 視圖,顯示和用戶交互
- C:controller 控制器 負責分發:將視圖和模型對應起來,接受請求,並將改請求跳轉模型,模型進行處理,然後將處理結果在經過控制器返回給視圖。
controller 一般都是使用Servelet實現控制器,
Servelet:是一個Java 類,處理請求和發送響應的一個過程,爲了實現動態頁面(開發一個Java程序向瀏覽器輸出數據)而衍生出來的,符合一定的規範,也就是說如果一個類符合一定規範,那麼這個類就是一個Servelet這個類就是
- 必須繼承javax.servelet.http.HttpServelet
- 重寫其中的doGet() 或者 doPost() 方法
- doGet() 接受並處理所有get提交方式的請求
- doPost() 接受並處理所有post提交方式的請求
public class WelcomeServlet2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doGet(req, resp);
System.out.println("do get 2");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
System.out.println("do post 2");
}
}
理解這個得前提是理解一些http協議,和B/S 模式(瀏覽器/服務器),瀏覽器/服務器,瀏覽器通過網址來訪問服務器
Tomacat和servlet的關係:
Tomcat是Web應用服務器,是一個Servlet/JSP 容器,Tomcat作爲Servlet容器,負責處理客戶請求,把請求傳送給Servelt,並將servlet的響應傳送會客戶,而servlet是一種運行在支持Java語言的服務器上的組件,Servlet至於常見的應用是擴展Java web 服務器功能。
瀏覽器發送的是一個請求文本,接受到的也是一個響應文本,
以上的步驟是:
- Tomcat將http請求文本接受並解析,然後封裝爲HttpServeltRequest類型的request對象,所以有的HTTP頭數據可以通過request對象調用對應的方法查看到。
- Tomcat 同時要響應的信息封裝爲HttpServletResponse類型的request對象,通過設置response 屬性就是控制輸出到瀏覽器的內容,然後將response 交給Tomcat,tomcat就會將其變爲響應文本的格式發送給瀏覽器
Java Servlet API 就是Servlet容器(tomcat)和servlet之間的接口,它定義了servlet各種方法,還定義了servlet容器傳送給servlet的對象類,其中最重要的就是ServletRequest和ServletResponse,所以我們在編寫servlet 的時候,需要實現servlet接口,按照其規範來操作。
Servelet的使用
Servelet2.5: 必須配置web.xml
Servelet3.0 :@WebServlet
第一種配置文件的方式:
web.xml 內容:
View 種的標籤:
<a href="WelcomeServlet">
WelcomeServlet
</a>
上面當點擊view 中的
後面會發送的事情如下:
- Web 項目會在web.xml中 根據 servlet-mapping 種的 url-pattern 標籤進行路徑的匹配,匹配之後
- 尋找在 1 中尋找在 servlet 中的的 servlet-name 和servlet-mapping 中的 servlet-name 具有相同的名字。
- 然後servlet 中 servlet-class 指定的類就是點擊鏈接後找到的對應的servelet
以上的執行過程:
- 編寫一個類,集成HttpServlet
- 重寫doGet 和 doPost
- web.xml 中的映射關係
項目中的web和src 都是項目的根目錄,當index發出一個請求的時候,首先會在web目錄下找對應的響應,然後再去src目錄下掃描對應的響應。
如果講url改爲,<a href="a/WelcomeServlet2"> 在web目錄或者src目錄找a目錄,然後再a目錄中找對應的響應
jsp中的/ 代表服務器的根路徑
web.xml 中的/ 代表項目的根路徑
servlet生命週期: 加載(servlet 容器自動處理) -> 初始化-> 服務(重點) -> 銷燬 -> 卸載(servlet 容器自動處理)
服務: 抽象service()方法 (doGet doPost)
初始化: init()方法,該方法在servlet 被加載並實例化以後執行
銷燬: destroy servlet 被系統回收的時候會執行
第一次訪問servlet的時候,init 和 service 都會觸發(可以設置爲服務器啓動的時候觸發
@WebServlet(value = "/WelcomeServlet", loadOnStartup = 1)
),當第二次觸發的時候就只會觸發service,調用幾次就會觸發 幾次 service,當在關閉服務器的時候就會去調用 destroy 方法,
Servlet API, 由兩個軟件包組成,對應於HTTP協議的軟件包,以及非HTTP協議意外的其他軟件包,我們學習的servlet,是爲javax.servlet.http 包中的類和接口,是基礎的http協議。
servlet 的繼承關係
HttpServlet在實現Servlet接口時,覆寫了service方法,該方法體內的代碼會自動判斷用戶的請求方式,如爲GET請求,則調用HttpServlet的doGet方法,如爲Post請求,則調用doPost方法。因此,開發人員在編寫Servlet時,通常只需要覆寫doGet或doPost方法,而不要去覆寫service方法。
HttpServlet繼承了GenaricServlet方法,這是一個通用的Servlet接口實現的抽象通用類,而Servlet接口有以下幾個方法
void init(ServletConfig var1) throws ServletException;
ServletConfig getServletConfig();
void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
String getServletInfo();
void destroy();
這裏可以看見servlet生命週期的三個關鍵方法,init、service、destroy還有就是 getServletConfig()方法來獲取ServletConfig對象,ServletConfig對象可以獲取到Servlet的一些信息,ServletName、ServletContext、InitParameter、InitParameterNames、通過查看ServletConfig這個接口就可以知道
public interface ServletConfig {
String getServletName();
ServletContext getServletContext();
String getInitParameter(String var1);
Enumeration<String> getInitParameterNames();
此外GenericServlet除了實現Servlet接口外,還實現了ServletConfig接口,那樣,就可以直接獲取ServletContext了。
GenericServlet中實現了Servlet 中的實現了Servlet 中的方法,但是可以發現有的方法實現了2遍,有空實現
public void init(ServletConfig config) throws ServletException {
this.config = config;
this.init();
}
public void init() throws ServletException {
}
這樣的實現是有一定的好處的,在正常初始化的時候(並不需要重寫用戶的init方法及加上用戶的邏輯)當繼承了GenericServlet的時候就會調用帶有參數的init方法,並將config賦值,上面可以看見還有一個getServletConfig的方法,在其他地方也就可以獲取得到這個congfig並使用,但是當用戶需要重寫nit方法及加上用戶的邏輯的時候,如果沒有這個init() 方法,那麼在GenericServlet 中就不會再去執行init(config) 方法了(被重寫了),所以在其他地方執行getServletConfig獲取到的就是null 了,而由這個init() 方法就可以避免這個問題了,因爲用戶重寫的init()方法是而不是init(config),所以在GenericServlet中init(cofig) 方法還是可以初始化config 的。
public abstract void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
這個方法並沒有被實現,且參數還是ServletRequest,ServletResponse。並沒有跟http相關對象掛鉤,所以我們接着往下面看。
繼續看HttpServlet 實現類:繼承了GenericServlet類,通過我們上面的推測,這個類主要的功能肯定是實現service方法的各種細節和設計。並且通過類名可以知道,該類就跟http掛鉤了。
該方法中就做一件事情,就是將ServletRequest和ServletResponse這兩個對象強轉爲HttpServletRequest和HttpServletResponse對象。爲什麼能這樣轉?首先要知道req、res是什麼類型,通過打印System.out.println(req),可以知道,req實際上的類型是org.apache.catalina.connector.RequestFacade
httpServletRequest和HttpServletResponse對象之後,在調用
service(HttpServletRequest req, HttpServletResponse resp)方法, 而這個方法就是會判斷請求來的具體是哪個方法,沒每種的處理方法也是不一樣的,我們常用的就是get,post,所以這裏就回到了我們上面編寫servlet時的情況,繼承httpServlet,而只要重寫兩個方法,一個doGet,一個doPost,其實就是service方法會調用這兩個方法中的一個(看請求方式)。
3.0 的方式給當前servlet設置初始值,但是隻是屬於當前的某一個servlet,無法爲整個web容器設置初始化參數,任然需要在web.xml 中配置。
<context-param>
<param-name>param-name</param-name>
<param-value>param-value</param-value>
</context-param>
httpServletRequest 中的方法通request 中的方法是一致的, 如, setAttribute(), getCookies(), getMethod()
相同的 httpServletResponse 也是的。
幾個重點的對象。ServletConfig、ServletContext,request、response
ServletConfig :
getServletName(); //獲取servlet的名稱,也就是我們在web.xml中配置的servlet-name
getServletContext(); //獲取ServletContext對象,該對象的作用看下面講解
getInitParameter(String); //獲取在servlet中初始化參數的值。這裏注意與全局初始化參數的區分。這個獲取的只是在該servlet下的初始化參數,web.xml 中的配置:
使用:
ServletContext
獲取途徑:getServletContext(); 、getServletConfig().getServletContext();
tomcat爲每個web項目都創建一個ServletContext實例,tomcat在啓動時創建,服務器關閉時銷燬,在一個web項目中共享數據,管理web項目資源,爲整個web配置公共信息等,通俗點講,就是一個web項目,就存在一個ServletContext實例,每個Servlet讀可以訪問到它。
web項目中共享數據,
setAttribute(String name, Object obj) 在web項目範圍內存放內容,以便讓在web項目中所有的servlet讀能訪問到
getAttribute(String name) 通過指定名稱獲得內容
removeAttribute(String name) 通過指定名稱移除內容
整個web項目初始化參數 //這個就是全局初始化參數,每個Servlet中都能獲取到該初始化值
getInitPatameter(String name) //通過指定名稱獲取初始化值
getInitParameterNames() //獲得枚舉類型
web.xml 配置 整個web項目的初始化,需要通過web.xml 配置
request 對象
request就是將請求文本封裝而成的對象,所以通過request能獲得請求文本中的所有內容,請求頭、請求體、請求行 。
String getHeader(java.lang.String name) 獲得指定頭內容String【】
long getDateHeader(java.lang.String name) 獲得指定頭內容Date
int getIntHeader(java.lang.String name) 獲得指定頭內容int
Enumeration getHeaders(java.lang.String name) 獲得指定名稱所有內容
3請求體的獲取 -- 請求參數的獲取
分兩種,一種get請求,一種post請求
get請求參數:http://localhost:8080/test01/MyServlet?username=jack&password=1234
post請求參數: <form method="post"><input type="text" name="username">
String request.getParameter(String) 獲得指定名稱,一個請求參數值。
String[] request.getParameterValues(String) 獲得指定名稱,所有請求參數值。例如:checkbox、select等
Map<String , String[]> request.getParameterMap() 獲得所有的請求參數
4請求轉發
request.getRequestDispatcher(String path).forward(request,response); //path:轉發後跳轉的頁面,這裏不管用不用"/"開頭,都是以web項目根開始,因爲這是請求轉發,請求轉發只侷限與在同一個web項目下使用,所以這裏一直都是從web項目根下開始的,
web項目根:
開發:G:\Workspaces\test01\WebRoot\..
運行時:D:\java\tomcat\apache-tomcat-7.0.53\webapps\test01\..
web站點根:
運行時:D:\java\tomcat\apache-tomcat-7.0.53\webapps\..
從這裏可以看出,web項目根就是從該web項目名開始,所以我們請求轉發時,只需要接着項目名後面需要訪問的路徑寫就行了,
特點:瀏覽器中url不會改變,也就是瀏覽器不知道服務器做了什麼,是服務器幫我們跳轉頁面的,並且在轉發後的頁面,能夠繼續使用原先的request,因爲是原先的request,所以request域中的屬性都可以繼續獲取到。
response對象
常用的一個方法:response.setHeader(java.lang.String name, java.lang.String value) 設置指定的頭,一般常用。