Servlet概念
server applet 運(yùn)行在服務(wù)器上的小程序
Servlet就是一個(gè)接口,定義了Java類被瀏覽器訪問到(tomcat識(shí)別)的規(guī)則
將來我們自定義一個(gè)類,實(shí)現(xiàn)Servlet接口,復(fù)寫方法
快速入門
創(chuàng)建JavaEE項(xiàng)目
定義一個(gè)類,實(shí)現(xiàn)Servlet接口
實(shí)現(xiàn)接口中的抽象方法
配置Servlet:在web.xml中配置
<!--配置Servlet-->
[Java] 純文本查看 復(fù)制代碼
?
01
02
03
04
05
06
07
08
09
10
11
12
13
<servlet>
<servlet-name>
demo01
</servlet-name>
<servlet-class>
cn.itcast.web.servlet.ServletDemo01
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>demo01</servlet-name>
<url-pattern>/demo01</url-pattern>
</servlet-mapping>
注:一般在IDEA中配置Tmocatd的Application context為/項(xiàng)目名稱,再調(diào)用時(shí)需要用localhost:8080/項(xiàng)目名稱/....
Servlet的執(zhí)行原理
當(dāng)服務(wù)器接受到客戶端瀏覽器的請求后,會(huì)解析請求URL路徑,獲取訪問的Servlet的資源路徑
查找web.xml,是否有對應(yīng)的<url-pattern>標(biāo)簽內(nèi)容
通過servlet-pattern找到servlet-name,又通過name找到資源的class全類名.
tomcat將類加載進(jìn)內(nèi)存,通過反射創(chuàng)建對象并調(diào)用service方法
Servlet中的生命周期
init方法-創(chuàng)建
初始化方法,在Servlet被創(chuàng)建時(shí)執(zhí)行,只會(huì)執(zhí)行一次
- Servlet什么時(shí)候被創(chuàng)建?
*默認(rèn)情況下,第一次被訪問時(shí),Servlet被創(chuàng)建
*可以在web.xml中配置創(chuàng)建時(shí)機(jī)
<servlet>
<load-on-startup>
0/正值:服務(wù)器啟動(dòng)時(shí)創(chuàng)建,值越大優(yōu)先級越小,一般從2開始,因?yàn)?被tomcat占用了
負(fù)值:第一次被訪問時(shí)創(chuàng)建
</load-on-startup>
</servlet>
- Servlet在服務(wù)器中只有一個(gè)對象,所以說Servlet是單例的
*多個(gè)用戶同時(shí)訪問時(shí),可能存在線程安全問題
*解決方案:盡量不要在Servlet中定義成員變量,而是使用局部變量;即使定義了成員變量,也不要對其修改值
service方法-提供服務(wù)
每一次Servlet被訪問一次則執(zhí)行一次
destory方法-銷毀
Servlet被殺死(服務(wù)器正常關(guān)閉)時(shí)執(zhí)行一次
一般用于釋放資源
ServletConfig方法 獲取ServletConfig對象
ServletInfo方法 獲取ServletInfo,如版本.作者,信息等,但一般不實(shí)現(xiàn)該方法
Servlet 3.0注解配置
-[ ] 好處:支持注解配置,可以不需要web.xml了-[ ] 步驟
創(chuàng)建JavaEE項(xiàng)目,選擇Servlet的版本3.0以上,可以不創(chuàng)建web.xml
定義一個(gè)類,實(shí)現(xiàn)Servlet接口
復(fù)寫方法
在類上使用@WebServlet注解進(jìn)行配置
@WebServlet("資源路徑")
IDEA和tomcat的相關(guān)配置
[ ]IDEA會(huì)為每一個(gè)tomcat部署項(xiàng)目單獨(dú)建立一份配置文件
啟動(dòng)后服務(wù)器控制臺(tái)有輸出Log:
Using CATALINA_BASE: "C:\Users\Mcdull\.IntelliJIdea2017.3\system\tomcat\Tomcat_8_5_31_webServer_2"
在Edit Configure下就可以修改配置文件和虛擬目錄
工作空間項(xiàng)目和tomcat部署的web項(xiàng)目
tomcat真正訪問的是"tomcat部署的web項(xiàng)目","tomcat部署的web項(xiàng)目"對應(yīng)著"工作空間項(xiàng)目"的web目錄下的所有資源
!!!!理解
采用的部署方式為第三種,在config/catalina/下部署
打開Using CATALINA_BASE路徑,可以找到config/catalina/day13_servlet.xml
打開servlet.xml,<Context docBase="E:\Projects\webServer\out\artifacts\day13_servlet_war_exploded" \>
里面指明了tomcat項(xiàng)目的路徑
WEB-INFO目錄下的資源不能被瀏覽器直接訪問
斷點(diǎn)調(diào)試
打斷點(diǎn),后用debug模式啟動(dòng)服務(wù)器
Servlet結(jié)構(gòu)體系
Servlet的實(shí)現(xiàn)類: GenericServlet(抽象類)-->HttpServlet(抽象類)
GenericServlet
GenericServlet將除了servic()以外的方法都空實(shí)現(xiàn)
將來定義Servlet時(shí)可以繼承GericServlet,只需實(shí)現(xiàn)servic類即可.
其他類也可以重寫HttpServlet
-[ ] 實(shí)際上做項(xiàng)目時(shí),我們一般使用GenericServlet的子類HttpServlet,因?yàn)镠ttpServlet封裝了Http協(xié)議
不使用HttpServlet時(shí),service方法需要實(shí)現(xiàn)的功能
判斷用戶的請求方式(get/post...)
String method = req.getMethod();
if("GET".equals(method)){//get方式獲取數(shù)據(jù)邏輯操作}
else if("POST".equals(methos){//post方式獲取數(shù)據(jù)邏輯操作}
HttpService 將判斷請求方式封裝起來,并提供doGet()和doPost()方法,分別寫在兩個(gè)邏輯體中
1.定義類繼承HttpServlet類
2.重寫doGet/doPost/...方法
[Java] 純文本查看 復(fù)制代碼
?
1
2
3
4
5
6
7
8
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp){
System.out.println("doGet...");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp){
System.out.println("doGet...");
}
Servlet urlpattern相關(guān)配置
1.urlpattern:Servlet訪問路徑可以有配置多個(gè)
一個(gè)Servlet可以定義多個(gè)訪問路徑,在注解中使用{"路徑1","路徑2"...}來配置
2.urlpattern:Servlet路徑的定義規(guī)則
1)./xxx 以這種方式為主
2)./xxx/xxx
3).*.后綴名
[強(qiáng)制!]開發(fā)中后綴名只能用*.do或*.action
HTTP概念
Hyper Text Transfer Protocol:超文本傳輸協(xié)議
傳輸協(xié)議:定義了客戶端和服務(wù)器端通信時(shí)發(fā)送數(shù)據(jù)的格式
特點(diǎn):
1). 基于TCP/IP的高級協(xié)議
2). HTTP的默認(rèn)端口號為80
當(dāng)訪問資源時(shí),如果服務(wù)器端口號為80,則可以省略
3). 基于請求/響應(yīng)模型的:一次請求對應(yīng)一次響應(yīng)
4). 無狀態(tài)的:每次請求之間相互獨(dú)立,不能交互數(shù)據(jù)
歷史版本:
1.0版本:每一次請求都需要建立一個(gè)連接
1.1版本:復(fù)用連接
請求消息數(shù)據(jù)格式
請求行
格式
請求行格式:
請求方式 請求url 請求協(xié)議/版本
例: GET /login.html http/1.1
請求方式
HTTP協(xié)議中有7種請求方式,常用的有2種
*GET:
1.請求參數(shù)在請求行中,在url后
2.請求的url長度是有限制的
3.不太安全
*POST:
1.請求參數(shù)在請求體中
2.請求的url長度沒有限制
3.相對安全
請求頭-瀏覽器告訴服務(wù)器一些信息
格式
請求頭格式:
請求頭名稱:請求頭值
請求頭名稱
常見的請求頭:
1.User-Agent**:瀏覽器告訴服務(wù)器,訪問者使用的瀏覽器版本信息
*可以在服務(wù)器端獲取該頭信息,解決瀏覽器兼容性問
2.Referer**:告訴服務(wù)器,當(dāng)前請求從哪里來(發(fā)起請求的頁面)
*例:Referer:http://localhost:8080/day_14/login.html
*作用:
1)防盜鏈:
if(referer.equals()){操作}
else{"想看嗎?來XXX網(wǎng)站吧!"}
2)統(tǒng)計(jì)工作:
統(tǒng)計(jì)工作:統(tǒng)計(jì)請求來源
if(refer.eauals("百度"){百度++}
else if(){}...
3.Connection:告訴服務(wù)器連接的狀態(tài)(是否可服用)
4.Host:請求主機(jī)的地址
5.Accept:告訴服務(wù)器,作為瀏覽器可以解析什么格式的文件
請求空行-用于分割POST請求的請求頭和請求體
空行
請求體(正文)-封裝post請求消息的請求參數(shù)
格式
參數(shù)名=參數(shù)值
響應(yīng)消息數(shù)據(jù)格式
響應(yīng)行
組成
協(xié)議/版本 響應(yīng)狀態(tài)碼 狀態(tài)碼的描述
響應(yīng)狀態(tài)碼:服務(wù)器高速客戶端瀏覽器本次請求和響應(yīng)的一個(gè)狀態(tài)
分類:
1xx: 服務(wù)器接收客戶端消息,沒有接收完成,等待一段時(shí)間后,發(fā)送1xx
2xx: 成功 代表狀態(tài)碼:200
3xx: 重定向 代表狀態(tài)碼:302(重定向) 304(訪問緩存)
4xx: 客戶端錯(cuò)誤 代表狀態(tài)碼:404(請求路徑錯(cuò)誤) 405(請求方式?jīng)]有對應(yīng)的doXXX方法)
5xx: 服務(wù)器錯(cuò)誤 代表狀態(tài)碼:500(服務(wù)器內(nèi)部出現(xiàn)異常)
響應(yīng)頭
格式
頭名稱:值
常見的響應(yīng)頭
1.Content-Type:服務(wù)器告訴客戶端響應(yīng)體數(shù)據(jù)格式以及編碼格式
例:Content-Type:text/html;charset=UTF-8
2.Content-disposition:服務(wù)器告訴客戶端以什么格式打開響應(yīng)體數(shù)據(jù)
*值:
*in-line:默認(rèn)值,在當(dāng)前頁面內(nèi)打開
*attachment;filename=xxx:以附件形式打開響應(yīng)體.文件下載
響應(yīng)空行
響應(yīng)體:傳輸?shù)臄?shù)據(jù)
響應(yīng)字符串格式Request對象Request和Response對象的原理
1.tomcat服務(wù)器會(huì)根據(jù)請求url中的資源路徑,創(chuàng)建對應(yīng)的Servlet對象
2.tomcat服務(wù)器會(huì)創(chuàng)建request和response對象;request對象中封裝消息數(shù)據(jù)
3.tomcat將request和response兩個(gè)對象傳遞給service方法,并調(diào)用service方法
4.程序員可以通過request對象來獲取請求消息數(shù)據(jù);可以通過response對象來設(shè)置響應(yīng)數(shù)據(jù)
5.tomcat在給瀏覽器作出響應(yīng)之前,會(huì)從response對象中獲取消息響應(yīng)數(shù)據(jù)并響應(yīng)給瀏覽器
注意:
1) request和response對象是由服務(wù)器創(chuàng)建的,我們來使用它們
2) request對象是來獲取請求消息,response對象來設(shè)置響應(yīng)消息
Requset對象的繼承結(jié)構(gòu)
ServletRequset(接口)->HttpServletReqest(接口)->RequestFacade(tomcat寫的實(shí)現(xiàn)類)
Request對象的功能獲取請求消息數(shù)據(jù)
1.獲取請求行數(shù)據(jù)
-請求行數(shù)據(jù): GET /day14/demo01?name=zhangsan HTTP/1.1
-獲取方法:
1)獲取請求方式: GET
*String getMethod()
2)獲取虛擬目錄**: /day14
*String getContextPath()
3)獲取Servlet路徑 /demo1
*String getServletPath()
4)獲取請求參數(shù) /name=zhangsan
*String getQueryString()
5)獲取請求的URI**: /day14/demo1
*String getRquestURI :/day14/demo1
*StringBuffer getRequestURL: http://localhost/day14/demo1
6)獲取瀏覽器的協(xié)議及版本 HTTP/1.1
*String getProtocol()
7)獲取客戶機(jī)的IP地址
*String getRemoteAddr()
注意:
URL:統(tǒng)一資源定位符 http://localhost//day14/demo1
URI:統(tǒng)一資源標(biāo)識(shí)符
day14/demo1
URL的范圍比URI的范圍小
2.獲取請求頭數(shù)據(jù)
1) String getHeader(String name):通過請求頭名稱獲取請求頭的值
2) Enumeration<String> getHeadernames():獲取所有請求頭的名稱
Enumberation 和 Iterator類似:
hasMoreElement() <--> hasNext()用于判斷
nextElement() <--> next() 用于獲取下一下元素
3.獲取請求體數(shù)據(jù)只有POST請求方式,才有請求體,在請求體中封裝了POST請求的請求參數(shù)
步驟:
1).獲取流對象
*BufferedReader getReader():獲取字符輸入流
*ServletInputStream getInputStream():獲取字節(jié)輸入流
2).從流對象中獲取數(shù)據(jù)
4.總結(jié):常用的方法
1)獲取虛擬目錄:getContextPath()
2)獲取請求URI:getRequestURI()/getRequestURL()
3)獲取請求頭:getHeader(String name)
==其他功能==
==1.獲取請求參數(shù)(通用方式)==
1)String getParameter(String name):根據(jù)參數(shù)名稱獲取參數(shù)值
2)String[] getParameterValues(String name): 根據(jù)參數(shù)名稱獲取參數(shù)值的數(shù)組,多用于復(fù)選框
如:hobby=xx&hobby=game
3)Enumeration<String> getParameterNames():獲取所有請求的參數(shù)名稱
4)Map<String,String[]> getParameterMap():獲取所有參數(shù)的map集合
- 中文亂碼問題
*get方式: tomcat8 已經(jīng)將get方式亂碼問題解決了
*post方式: 會(huì)亂碼
解決:在獲取參數(shù)前,設(shè)置request編碼
request.setCharacterEncoding("utf-8")
==2.請求轉(zhuǎn)發(fā):一種在服務(wù)器內(nèi)部的資源跳轉(zhuǎn)的方式==
步驟
1)通過request對象獲取請求轉(zhuǎn)發(fā)器對象:RequestDispatcher getRequestDispatcher(String path)
2)使用RequestDispatcher對象來進(jìn)行轉(zhuǎn)發(fā):forward(ServletRequest request,ServletResponse)
特點(diǎn)
1) 瀏覽器地址欄路徑不發(fā)生變化2) 只能轉(zhuǎn)發(fā)至當(dāng)前服務(wù)器的內(nèi)部資源中3) 轉(zhuǎn)發(fā)是一次請求
==3.數(shù)據(jù)共享==
域?qū)ο?一個(gè)有作用范圍的對象,可以在范圍內(nèi)共享數(shù)據(jù)
request域:代表一次請求的范圍,一般用于請求轉(zhuǎn)發(fā)的多個(gè)資源中去共享數(shù)據(jù)
request資源共享方法
1) void setAttribute(String name ,Object obj) :存儲(chǔ)數(shù)據(jù)2) Object getAttribute(String name) 通過鍵來獲取值3) void removeAttribute(String name) 通過鍵來移除鍵值對
==4.獲取ServletContext對象==
-ServletContext getServletContext()
BeanUtils
用于封裝JavaBean
JavaBean
JavaBean:標(biāo)準(zhǔn)的Java類
類必須被public修飾
必須提供空參的構(gòu)造器
成員變量必須使用private修飾
提供公共的setter和getter方法
JavaBean的功能:封裝數(shù)據(jù)
概念
成員變量
屬性:setter和getter方法截取后的產(chǎn)物
例如:getUsername()-->Username-->username大部分情況下屬性和成員變量是一樣的
BeanUtils的方法
1.setProperty(javaBean,"屬性名","值")
2.getProperty(javaBean,"屬性名")
3.populate(javaBean,屬性集map)
Response對象
功能:設(shè)置響應(yīng)消息
設(shè)置響應(yīng)行
設(shè)置響應(yīng)頭
設(shè)置響應(yīng)體
設(shè)置響應(yīng)行1.格式HTTP/1.1 200 ok2.設(shè)置狀態(tài)碼setStatus(int sc)
設(shè)置響應(yīng)頭
setHeader(String name, String value)
設(shè)置響應(yīng)體
使用步驟
1.獲取輸出流 *字符輸出流:PrintWriter getWriter() *字節(jié)輸出流:ServletOutputStream getOutputStream()2.使用輸出流將數(shù)據(jù)輸出到客戶端瀏覽器
案例完成重定向(redirect)
代碼實(shí)現(xiàn)
//1.設(shè)置狀態(tài)碼為 302response.setStatues(302);//2.設(shè)置響應(yīng)頭locationresponse.setHeader("location","/虛擬路徑/資源路徑")
簡單的重定向方法
resonpse.sendRedirect("/虛擬路徑/資源路徑")
重定向的特點(diǎn)
1. 地址欄發(fā)生變化2. 重定向可以訪問其他服務(wù)器的資源3. 重定向是兩次請求
路徑寫法:
1.相對路徑: 通過相對路徑不可以確定唯一資源 * 以 ./開頭 表示當(dāng)前路徑 * 以 ../開頭 表示后退一級 *規(guī)則: 找到當(dāng)前資源和目標(biāo)資源之間的相對位置關(guān)系 2.絕對路徑: 絕對路徑可以確定唯一資源 在這里可以寫為/虛擬路徑/資源路徑
在瀏覽器輸出字符數(shù)據(jù)
代碼實(shí)現(xiàn)
//1.獲取字符輸出流PrintWriter pw = resp.getWriter();//2.向?yàn)g覽器寫出字符數(shù)據(jù)pw.write("<h1>你好,response</h1>");此實(shí)現(xiàn)會(huì)出現(xiàn)亂碼,因?yàn)楂@取的流的默認(rèn)編碼為IOS-8859-1
亂碼問題
上一個(gè)代碼實(shí)現(xiàn)會(huì)出現(xiàn)亂碼問題
解決方法:在獲取流之前設(shè)置編碼和web解碼方式
//1.設(shè)置response的編碼格式(默認(rèn)為IOS-8859-1)
//response.setCharacterEncoding("編碼格式")
//2.使用response設(shè)置響應(yīng)頭,要求使用特定的編碼格式去解碼
response.setHeader("content-type","text/html;charset=編碼格式")
簡單方法:
response.setContentType("text/html;charset=編碼格式")
注意:使用語句2,就可以設(shè)置編碼格式,和瀏覽器的解碼格式.第1步就可以不用寫了
作者:黑馬程序員JavaEE培訓(xùn)學(xué)院
首發(fā):http://java.itheima.com/