JavaWeb-Servlet
Servlet是和平臺無關的伺服器端元件,執行在Servlet容器中。Servlet容器負責Servlet和客戶的通訊以及呼叫Servlet的方法,Servlet和客戶的通訊採用“請求/響應”的模式。
Servlet可完成的功能:
- 建立並返回基於客戶請求的動態HTML頁面
- 建立可嵌入到現有HTML頁面中的部分HTML頁面
- 與其他伺服器資源進行通訊
Tomcat就是Servlet容器
- 可以用來建立Servlet,並呼叫Servlet的相關生命週期方法
Servlet生命週期方法:
- 構造器方法:第一次請求Servlet時,建立Servlet的例項,呼叫構造器(只被呼叫一次)
- init方法:只被呼叫一次,建立好例項後立即被呼叫,用於初始化當前Servlet
- service方法:被多次呼叫,每次請求都會呼叫service方法,實際用於響應請求的
- destroy方法:只被嗲用一次,在當前Servlet所在的web應用被解除安裝前呼叫,用於釋放當前Servlet所佔用的資源
<load-on-startup>1</load-on-startup>
這個標籤引數可以指定Servlet被建立的時機
- 配置在Servlet節點中
- 若為負數,則在第一次請求時被建立,若為0或正數,則在當前web應用被Servlet容器載入時建立例項,且數越小越早被建立
ServletConfig:儲存了Servlet的各項配置,並且可以獲取ServletContex物件
ServletContext:
- 可以由ServletConfig獲取
- 代表當前web應用,可以認為ServletCOntext是當前web應用的一個大管家
- 獲取當前web應用的某一個檔案的絕對路徑,檔案在伺服器上的路徑,而不是部署前的路徑
getRealPath() - 獲取當前web應用名稱
getContextPath() - 獲取當前web應用的某一個檔案對應的輸入流
getResourceAsStream(String path):path的/為當前應用的根目錄
HTTP的會話方式:
- 建立連線
- 發出請求資訊
- 回送響應資訊
- 斷開連線
Get請求和Post請求
- 在瀏覽器位址列輸入某個URL地址或單繼網頁上的一個超連結時,瀏覽器發出的HTTP請求為GET
- 如果網頁中的form表單元素的method屬性被設定為GET,瀏覽器提交這個form表單時生成的HTTP請求為GET
- 使用GET方式傳送的資料量一般限制在1kb以下
Post方式傳遞引數
- post請求方式主要用於向web伺服器端程式提交form表單中的資料,form表單的mehtod設定為post
- post方式將各個表單欄位元素及其資料作為http訊息的實體內容傳送給web伺服器,傳送的資料量要比使用get方式傳送的資料量大得多
響應狀態碼含義: - 200:請求成功
- 302:請求重定向
- 304:請求資源沒有改變,訪問本地快取
- 404:請求資源不存在,通常是使用者路徑編寫錯誤,也可能是伺服器資源已經刪除
- 500:伺服器內部錯誤,通常程式拋異常
Java反射機制
- 在執行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法。
- 對於任意一個物件,都能夠呼叫他的任意一個方法和屬性
- 想要使用反射,必須獲取位元組碼檔案
獲取位元組碼檔案的方式
- Object類的getClass方法
- 靜態屬性 class
- class類中靜態方法forName
反射中獲取私有屬性
- getDeclaredField()
- setAccessable(true)
反射中獲取私有方法
- getDeclaredMethod()
- setAccessable(true)
Servlet中的init()方法和destroy()方法
- init()方法:在Servlet建立的時候呼叫,也可以通過配置在伺服器一啟動就開始呼叫。具體方法是:在web.xml中配置選項,<load-on-startup>標籤可以設定優先順序,填寫數字代表優先順序
- service方法():每一次請求的的時候進行呼叫,每次傳送請求都會呼叫service方法();
- destroy()方法:當servlet被銷燬的時候呼叫,當伺服器關閉的時候呼叫
Servlet訪問流程

image.png
init()方法引數介紹
public void init(ServletConfig servletConfig) throws ServletException { }
servletConfig 可以獲取一些配置資訊
1.可以獲取Servlet名稱 web.xml
2.獲取web.xml中的初始化引數
3.獲取ServletContext
url-patten匹配形式
-
完全匹配
就是在web.xml中的url-patten必須跟要在位址列寫的完全一致才可以
目錄匹配
類似於導包時候的 .
*,只要在前面寫好目錄,不管具體的檔案是什麼,最終都能訪問到目錄下的servlet-
副檔名匹配
// *.myxq
只要副檔名是.myxq結尾的都可以被訪問到
url-patten預設值與靜態資源的訪問流程
- 如果都沒有匹配到url-patten,就會找預設,預設的名稱就是<servletname>對應的Servlet。<url-pattern>/</url-pattern>
靜態資源載入過程
- 在path後面寫的靜態資源名稱index.html或者其他的.html他都是會找url-pattern當中有沒有匹配的內容
- 如果有,就載入對應的servlet,如果沒有就自己到配置當中找預設的url-pattern
- 如果自己配置檔案當中沒有預設的,就會找全域性配置預設的url-pattern
- 在全域性配置當中有一個預設的url-pattern, 對應的default的Servlet
- defaultServlet內部會到當前訪問的工程根目錄當中去找對應的名稱的靜態資源,如果有,就把裡面的內容逐行輸出,響應給瀏覽器
- 如果沒有,就會報404錯誤
使用註解建立Servlet
@WebServlet("/myServlet)
- 這個相當於一個註解
- 相當於在程式碼上添加了一個小外掛
- 貼上這個註解以後,就不用再去做配置檔案,系統自動做
- 括號當中的內容就是url-pattern的內容,要在位址列當中path後面跟的內容
doGet()方法
- 當get請求時會呼叫該方法
doPost()方法
- 當post請求時會呼叫該方法
當一個Servlet類繼承自HttpServlet時,如果複寫了父類的Service方法,那麼不管是通過post方式提交請求還是get方式提交請求,都會直接呼叫Service方法。即,一旦寫了Service方法,就不會呼叫doPost和doGet方法。

image.png

image.png
ServletContext物件
- 代表web應用的上下文物件,一個web應用只有一個ServletContext物件
- 裡面封裝的都是web應用資訊
- 一個ServletContext對應一個應用
生命週期 - 伺服器啟動就會被建立
- 伺服器關閉銷燬
如何獲得上下文
- 通過init()方法當中一個引數ServletConfig來獲取
@Override public void init(ServletConfig config) throws ServletException { ServletContext servletContext=config.getServletContext(); System.out.println(servletContext); }
ServletContext 獲取檔案路徑
ServletContext context=this.getServletContext(); String realPath =context.getRealPath("WEB-INF/b.txt"); System.out.println(realpath); //使用類載入器,獲取位元組碼的路徑 //到位元組碼目錄中載入資源 String path=OneServlet.class.getClassLoader().getResource(""); System.out.println(path);
ServletContext是一個域物件,是指能夠儲存資料
- 作用範圍:整個web應用,所有的web資源都i可以進行存取資料,資料是可以共享的
如何王ServletContext裡面寫資料: - contex.setAttribute(String name,Object object)
取資料
- context.getAttribute(String name)
刪除指定值
- context.removeAttribute(String name)
只要是一個域物件,裡面都有這幾個方法
Response物件
學習response主要就是學習通過response設定響應行,響應頭,響應體
response響應過程:
- 傳送一個請求時,會找到tomcat引擎
- 引擎會找到相應的web應用,並且會建立request物件和response物件
- 找到應用後,會執行應用的web.xml再去根據url-pattern的內容建立Servlet物件
- 並且會呼叫Servlet物件的service方法,並且把建立的request物件和response物件傳入到方法當中
- 拿到response物件後,可以往響應當中寫入一些自己給客戶端的內容
- 寫的內容是存到一個response緩衝區當中
- 當方法執行結束之後,tomcat就會從response緩衝區當中取出資料

設定響應行
- response.setState(int code) 設定狀態碼
設定響應頭
-
主要有add和set兩個方法
image.png
response重定向
- 訪問兩次伺服器,第一次是人為的去訪問,第二次是自動訪問
- 瀏覽器地址兩次發生了變化
設定重定向
response.setHeader("location","另一個servlet");
另一種重定向方法
response.sendRedirect("另一個servlet");
定時重新整理也是一種重定向
response.setHeader("refresh","另一個servlet")
設定響應體
-
通過write方法
response.getWrite().write(要寫的內容)
預設情況下寫的中文內容會亂碼,因為寫的內容在存到緩衝區中使用的是ISO8859編碼,不支援中文。
如何解決中文亂碼問題
在存之前設定存放的編碼,response.setCharacterEncoding
告知瀏覽器使用的是utf-8編碼
緩衝區及瀏覽器都有自己的編碼格式,當更改了緩衝區編碼方式仍然出現中文亂碼時,應該更改瀏覽器的編碼方式。
//設定緩衝區的編碼格式 resp.setCharacterEncoding("utf-8"); //在響應中主動告訴瀏覽器通過什麼樣的編碼格式接受 resp.setHeader("Content-Type","text/html;charset=UTF-8");
上述兩行程式碼可以通過如下一行程式碼替換
response.setContentType("text/html;charset=UTF-8");
設定編碼格式要在設定內容之前完成,

image.png
-
通過outputstream方法可以完成讀取圖片等媒體資源
主要就是檔案讀取操作,需要注意的一點就是對檔案的訪問操作,通過檔名訪問檔案時,檔案的路徑在idea中需要注意,通過idea做動態網站,檔案位置並非放置在tomcat瀏覽器中,而是在下圖中的左側out資料夾下,也就是說,通過getRealPath獲取到的路徑是E:\project\javaproject\ThirdWeb\out\artifacts\ThirdWeb_war_exploded
所以通過getRealPath獲取路徑之後,想直接訪問靜態資源,可以把資源直接放在_war_exploded根目錄下面

image.png
getWrite()和outputstream不能同時存在。
下載檔案
-
通過a標籤
直接使用a標籤可以下載檔案,但是下載的檔案只能是壓縮檔案等,圖片和mp4等型別的檔案是不能夠下載下來的,當點選下載這些檔案時,瀏覽器會去解析這些檔案。
-
通過傳送請求的方式下載檔案
該方式不能識別出所有的檔案型別,因此需要設定檔案型別。
設定下載檔案型別
- 設定mimeType
- 告訴瀏覽器以附件的形式開啟
@WebServlet("/DownloadServlet2") public class DownloadServlet2 extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String name=req.getParameter("filename"); String path = this.getServletContext().getRealPath(name); System.out.println(path); String mimeType = this.getServletContext().getMimeType(name); //設定mimetype resp.setContentType(mimeType); //告訴瀏覽器以附件的形式開啟 resp.setHeader("Content-Disposition","attachment;filename="+name); //根據path載入檔案 FileInputStream in = new FileInputStream(path); ServletOutputStream servletOutputStream = resp.getOutputStream(); byte[] buffer = new byte[1024]; int len=0; while ((len=in.read(buffer))!=-1) { servletOutputStream.write(buffer); } in.close(); } }
Request

image.png
-
請求行
1.獲取請求方式
request.getMethod();
2.請求資源url uri
request.getRequestURL();
request.getRequestURI();
下圖中第一個是URL
第二個是URI
image.png
3.獲取get請求引數
request.getQueryString();
這裡獲取到的都是請求的引數資訊
image.png
4.獲取當前web應用名稱
request.getContentPath();
獲取到的是當前工程的名字
請求頭
1.獲取所有請求頭名稱
Enumeration<String> headerNames=request.getHeaderNames(); while(headerNames.hasMoreElements()) System.out.println("name="+headerNames.nextElements());
請求體
1.獲取一個值
request.getParameterValue();
2.獲取多個值
request.getParameterValues();
3.獲取所有請求引數名稱
request.getParameterNames();
4.獲取所有請求引數
request.getParameterMap();
get和post方式如何選擇
1.傳送的引數不需要寫到資料庫用get方式
2.傳送的引數需要儲存到資料庫用post
renquest請求轉發
請求轉發跟重定向的區別在於,請求轉發是直接通過一個找另一個,不需要返回再重新找。

image.png
實現轉發
1.通過請求物件獲取一個轉發器request.getRequestDispatcher(String path)
返回一個RequestDispatcher
2.通過轉發器進行轉發
呼叫轉發器的forward()方法進行轉發
disp.forward(req,rep)

image.png
request域物件
1.在一次請求過程當中存在的且共享
客戶端地址與伺服器端地址
- 客戶端地址
客戶端訪問伺服器使用的地址
伺服器外部地址
寫的時候要寫上web應用的名稱/應用名稱/資源 - 伺服器地址
服務內部當中使用的地址
不需要寫web應用名稱/資源名稱
cookie與Session
會話技術
什麼是會話
- 使用者點開一個瀏覽器
- 點選多個超連結,訪問多個web資源
- 再關閉瀏覽器,整個過程稱之為一個會話
解決什麼問題
- 保持各個客戶端自己的資料
- 存臨時資料
Session技術
Session域當一個瀏覽器訪問伺服器建立,關閉伺服器或過期時,銷燬Session域物件。
將資料儲存到伺服器,安全性相對好,增加伺服器壓力
會為每個客戶端都建立一塊記憶體空間儲存客戶的資料,但客戶端需要每次都攜帶一個標識ID去伺服器中尋找屬於自己的記憶體空間。所以說Sesssion的實現是基於Cookie。Session需要藉助於Cookie儲存客戶的唯一性標識JSESSIONID。
獲取Session物件
//方法內部判斷該客戶端是否在伺服器端已經存在Session //有則不建立,否則新建立session物件 HttpSession session=request.getSession(); String id=session.getId();
Session物件生命週期
建立:第一次執行request.getSession()時建立
銷燬:
- 伺服器關閉時
- session過期或者失效(預設30分鐘) ,從不操作伺服器端的資源開始計時
- 手動銷燬session(session.invalidate())
cookie技術
資料儲存在客戶端本地,減少伺服器端壓力,安全性不好,客戶端可以清除cookie

image.png
伺服器如何把cookie寫給客戶端
- 建立cookie(會以響應頭的形式傳送給客戶端;只能儲存非中文的字串)
Cookie cookie=new Cookie(String cookieName,String cookieValue) - 向客戶端傳送cookie
response.addCookie(cookie名稱) - 訪問
- cookie預設儲存時間
- 設定cookie的攜帶路徑
- 刪除cookie
預設cookie的生命週期是會話級別,開啟瀏覽器和關閉瀏覽器為一次會話,如果不設定持久化時間,cookie會儲存在瀏覽器記憶體,瀏覽器關閉,cookie資訊銷燬
設定cookie的持久化時間需要在傳送cookie之前進行。cookie.setMaxAge(60); 單位時間是秒,過期cookie自動銷燬
- 設定cookie的攜帶路徑
意思是在訪問某一個資源時,要不要先攜帶cookie資訊
如果不設定攜帶路徑,預設情況下會在訪問建立cookie的web資源相同的路徑都攜帶cookie資訊(比如建立cookie的servlet檔案在一個目錄下,那麼在servlet的上級檔案目錄中的所有web資源都會存在該cookie資訊)
設定路徑方式
cookie.setPath(String path); - cookie.setPath("/CookiePro/cookieServlet") 只有訪問該servlet才攜帶cookie資訊
- cookie.setPath("/CookiePao") 只要在該工程下,都會攜帶cookie資訊
- cookie.setPath("/"); 只要訪問該伺服器,都會攜帶cookie資訊
刪除cookie:建立一個重名的cookie,設定cookie的存活時間為0
伺服器如何獲取客戶端攜帶的cookie
- 通過request物件的getCookie()方法
- 獲取的是所有的cookie
- 進行遍歷,找出自己名稱的那一個