常用對象
ServletConfig:用來獲取Servlet的初始化參數(shù),web容器向當(dāng)前servlet傳遞的信息
初始化值:初始化的值只是讓這個(gè)servlet有了值,并會顯示在哪里,并需調(diào)用方法獲取


ServletContext
? ? ? 用來獲取Servlet的上下文對象,是web容器的一個(gè)大管家(可以獲取所有servlet,所以servlet也可以操縱它)

獲取servletContext: ? ?ServletConfig.getServletContext()
1.可以獲取全局的初始化參數(shù)(不再具體的某個(gè)servlet中)
2.ServletContext對象所保存的數(shù)據(jù)可以被所有的servlet共享
getInitParameter()獲取servlet的全局初始化參數(shù)
getInitParameterNames()返回全局初始化名字的枚舉
getResoutceAsStream(String parh) 獲取文件信息返回的是輸入流 ?沒什么用
getRealPath(" ") ? 獲取服務(wù)器路徑
ServletConfig和ServletContext主要區(qū)別:
1.一個(gè)ServletConfig對應(yīng)一個(gè)servlet,獲取單個(gè)servlet的初始化參數(shù)
2.ServletContext是全局的,一個(gè)對應(yīng)ServletContext對應(yīng)多個(gè)servlet,操作的是初始化數(shù)據(jù)是定義在每一個(gè)servlet之外的
表單數(shù)據(jù)Request,
Response常用方法??
HttpServletRequest ? 封裝著一次用戶請求(所有的請求參數(shù)都封裝在內(nèi))
HttpServletResponse ?用服務(wù)器向網(wǎng)頁進(jìn)行相應(yīng)數(shù)據(jù)(內(nèi)有字節(jié)流和字符流)
HttpServletRequest常用方法
1.四個(gè)獲取請求參數(shù)的方法
2.域?qū)傩缘乃膫€(gè)方法
3.轉(zhuǎn)發(fā)
4.獲取請求相關(guān)路徑
getRequestURL() ?獲取請求的URL ?http://localhost:8080/工程名/訪問路徑
getRequestURI() URL去掉協(xié)議和主機(jī) ? ? ? ? ? ? ?/工程名/訪問路徑(可能是某個(gè)文件夾或直接暴漏)
getContextPath() ? 獲取當(dāng)前web應(yīng)用的根路徑 ? ? ?/工程名
getRemoteAddr() 獲取客戶端地址
比如訪問路徑是 /aaa/bb/dd/*
getServletPath() ?獲取訪問路徑的精確部分 ? ?/aaa/bb/dd
getPathInfo() ? 獲取請求路徑的非精確部分 ??/*
HttpServletResponse常用方法
以流的形式發(fā)送到客戶端
getWriter() ? 用于獲取專門向?yàn)g覽器輸出字符數(shù)據(jù)的標(biāo)準(zhǔn)輸出流 PrintWriter
addCookie(Cookie cookie) 增加cookie
獲取請求參數(shù)的方法

getParameter("name"):您可以調(diào)用 request.getParameter() 方法來獲取表單參數(shù)的值。
name表示的是表單中的name屬性的值(返回值是字符串)
getParameterValues():如果參數(shù)出現(xiàn)一次以上,則調(diào)用該方法,并返回多個(gè)值,例如復(fù)選框(每個(gè)選項(xiàng)的name值要相同)

getParameterNames():如果您想要得到當(dāng)前請求中的所有參數(shù)的完整列表,則調(diào)用該方法。

getParameterMap(): 獲取請求的map集合

? ? ? 很多情況下,需要傳遞一些信息,從瀏覽器到 Web 服務(wù)器,最終到后臺程序。瀏覽器使用兩種方法可將這些信息傳遞到 Web 服務(wù)器,分別為 GET 方法和 POST 方法。(html寫到WebContent中)
注意:如何將html的表單數(shù)據(jù)關(guān)聯(lián)servlet(也就是提交html之后跳轉(zhuǎn)到servlet網(wǎng)頁),表單元素中有一個(gè)action屬性,它表示的是表單在結(jié)束也就是提交后執(zhí)行的動作(調(diào)轉(zhuǎn)到哪里),所以把a(bǔ)ction的值設(shè)置為想要跳轉(zhuǎn)的servlet類對應(yīng)的訪問路徑,就可以實(shí)現(xiàn)跳轉(zhuǎn)了(類與表單的get和post要相對應(yīng)),html的數(shù)據(jù)經(jīng)過提交就把對應(yīng)的數(shù)據(jù)通過name=value方式或數(shù)據(jù)包的方式傳給了跳轉(zhuǎn)到的servlet對應(yīng)的網(wǎng)頁地址欄頭,servlet通過網(wǎng)頁地址欄或數(shù)據(jù)包進(jìn)行獲?。總€(gè)servlet只有一個(gè)訪問地址(網(wǎng)頁),所以每個(gè)servlet知道應(yīng)該獲取哪個(gè)網(wǎng)頁里的信息)

get請求類似于信封,post請求類似于信,信封上數(shù)據(jù)量少,速度快,并且不適合傳遞敏感信息,信上內(nèi)容數(shù)據(jù)多,但是速度慢,適合傳遞敏感信息
在實(shí)際開發(fā)的過程當(dāng)中大多數(shù)使用的都是post請求,默認(rèn)的請求方式是get
1.doGet()用于處理表單里的get請求(或未指定請求)

Get請求的數(shù)據(jù)會隨著瀏覽器的地址一起發(fā)送到后臺服務(wù)器,用戶可以看到請求的數(shù)據(jù)

doPost()方法傳遞數(shù)據(jù)的形式,Post請求的數(shù)據(jù)會打成一個(gè)數(shù)據(jù)包隨著請求頭一起發(fā)送到服務(wù)器用戶不可見?。

域?qū)傩?/h4>
在request存在一塊用于存放數(shù)據(jù)的空間,該數(shù)據(jù)只在當(dāng)前request請求中訪問,只要請求存在就可以獲取請求域中指定屬性的值,其主要就是為了實(shí)現(xiàn)數(shù)據(jù)傳遞的
1.setAttribute(name,value)
name:綁定名稱
value:綁定的值
2.removeAttribute(name) 移除綁定的屬性
3.getAttribute(name) 獲取指定屬性?
4.若添加多個(gè)數(shù)據(jù),轉(zhuǎn)發(fā)到的jsp/servlet獲取方式 ? 獲取所有屬性
?Enumeration <String> names=request.getAttributeNames() ??
while(names.hasMoreElements){
String name=names.nextElement();
String ele=request.getAttribut(name)
}
請求轉(zhuǎn)發(fā)與重定向
可以在servlet和servlet/servlet和jsp/jsp和jsp間發(fā)生
解決邏輯和頁面顯示在jsp,邏輯處理在servlet
請求轉(zhuǎn)發(fā)與重定向的理解

類似介紹對象
轉(zhuǎn)發(fā):瀏覽器想和資源1處對象,資源1覺得不是很好但是沒有直接告訴瀏覽器,而是把它介紹給了住在一起的資源2,資源2最終對瀏覽器做出了回應(yīng)。這個(gè)過程瀏覽器只發(fā)送了一次請求,請求的地址沒有發(fā)生變化。
重定向:瀏覽器想和資源1處對象,資源1覺得不是很好就直接告訴了瀏覽器,并介紹瀏覽器去和資源2處對象并把資源2的地址告訴給了瀏覽器,于是瀏覽器去資源2住的地方請求資源2處對象,資源2對瀏覽器做出回應(yīng),這個(gè)過程瀏覽器發(fā)送了兩次請求,并且請求地址也發(fā)生了變化
請求轉(zhuǎn)發(fā):資源1得到請求后,將這個(gè)請求轉(zhuǎn)發(fā)給下一個(gè)資源(可以在這個(gè)請求中通過域?qū)傩蕴砑右恍?shù)據(jù))。(1)只請求一次 ,(2)網(wǎng)址并沒有發(fā)生變化,(3)轉(zhuǎn)發(fā)的過程中攜帶著瀏覽器的請求(因?yàn)檫@一次請求并沒有結(jié)束,所以我們可以把請求添加數(shù)據(jù)后再進(jìn)行轉(zhuǎn)發(fā))(4)只能跳轉(zhuǎn)當(dāng)前應(yīng)用資源
重定向:資源1得到請求后,回應(yīng)給瀏覽器另一個(gè)資源的地址,讓它去請求另一個(gè)資源,瀏覽器請求另一個(gè)資源后得到的回應(yīng)就是最終的回應(yīng)。(1)請求了兩次,(2)網(wǎng)址發(fā)生了變化,可以防止表單重復(fù)提交(3)請求結(jié)束后所存數(shù)據(jù)也就沒有了,因此重定向第一次請求所存數(shù)據(jù)第二次請求中是不存在的(4)不僅可以跳轉(zhuǎn)當(dāng)前應(yīng)用資源,也可以跳轉(zhuǎn)其它應(yīng)用給的資源
實(shí)現(xiàn)轉(zhuǎn)發(fā):
1綁定數(shù)據(jù)request.setAttribute(name,value) ?name:綁定名稱 ?value:綁定的值
value是要存到請求中的值,而name相當(dāng)于map中的key,jsp可通過這個(gè)獲取值
2.獲取轉(zhuǎn)發(fā)器/3.實(shí)現(xiàn)轉(zhuǎn)發(fā)
request.getRequestDispatcher("轉(zhuǎn)發(fā)到的路徑").forward(request,reponse)
獲取綁定數(shù)據(jù)
request.getAttribute(name)
注意:除了使用forward實(shí)現(xiàn)數(shù)據(jù)轉(zhuǎn)發(fā)我們還可以使用include實(shí)現(xiàn)請求轉(zhuǎn)發(fā),兩者對于請求來說都是一樣的,不同點(diǎn)主要實(shí)在響應(yīng)對象中


實(shí)現(xiàn)重定向(少用于數(shù)據(jù)傳輸)
response.sendRedirect("重定向地址")
注:重定向請求發(fā)生改變因此重定向不能在請求中存在數(shù)據(jù),我們可以在重定向的地址中做相應(yīng)的操作實(shí)現(xiàn)數(shù)據(jù)的傳遞 "other?pname=zz&page=23"但是http傳輸數(shù)據(jù)采用的是字節(jié)方式,如果想傳輸漢字到地址欄上,我們需要采用以下方式
name = URLEncoder.encode(name,"UTF-8") ?//將漢字打散成字節(jié),然后傳遞
response.sendRedirect("other?pname="+name)
另一個(gè)servlet
String pname=request.getParameter("pname")
pname=URLDecoder.decode(pname,"UTF-8") //打散后當(dāng)然又要組裝起來
pname=new String(pname.getBytes("ISO8859-1","UTF-8"))
打散和組裝都是更改的http地址的傳輸方式
注:使用這種方法來獲取get請求地址欄的參數(shù)是在地址欄上的參數(shù)是通過字節(jié)方式顯示的時(shí)候,之后如果顯示的是漢字采用正常的轉(zhuǎn)碼就可以了
轉(zhuǎn)發(fā)與重定向的應(yīng)用場景
(1)若需要跳轉(zhuǎn)到其它應(yīng)用使用重定向
(2)防止表單數(shù)據(jù)的重復(fù)提交使用重定向
(3) 轉(zhuǎn)發(fā)一般一個(gè)組件的業(yè)務(wù)沒有處理完成交給下一個(gè)組件去做,而重定向是當(dāng)前組件已經(jīng)把業(yè)務(wù)處理完成之后,跳轉(zhuǎn)到其它組件
注意:轉(zhuǎn)發(fā)過程中,請求和轉(zhuǎn)發(fā)是通過servlet控制的,而響應(yīng)是通過服務(wù)器尋找到對應(yīng)資源自動做出的響應(yīng);重定向過程中,第一次請求和響應(yīng)是通過servlet控制的,而第二次的請求和響應(yīng)是服務(wù)器轉(zhuǎn)到對應(yīng)資源后自動做出的。
關(guān)于get與post請求的中文亂碼的問題
產(chǎn)生原因:瀏覽器輸入漢字(漢字編碼utf-8),瀏覽器會將其傳給服務(wù)器,服務(wù)器默認(rèn)采用iso8859-1編碼對它們進(jìn)行解析,解析后在控制臺顯示。
注:ecplise把編碼改成utf-8
1.修改tomcat下的文件編碼為utf-8(這樣若每個(gè)程序的編碼不同就不可以了)
2.在程序中將請求得到的數(shù)據(jù)改為utf-8的數(shù)據(jù),手動將回應(yīng)的編碼方式改為utf-8
兩種手動方式修改編碼
1.將服務(wù)器的解析編碼的方式更改為utf-8,這樣得到的數(shù)據(jù)就是utf-8了,
req.?setcharacterEncoding("UTF-8") ?這個(gè)必須使用的post提交方式
2.將服務(wù)器解碼后的數(shù)據(jù)轉(zhuǎn)碼為utf-8(get) ?因?yàn)間et傳輸是通過網(wǎng)頁的編碼實(shí)現(xiàn)的,不可更改

回應(yīng)的時(shí)候只能選擇第一種方式,因?yàn)锽/S架構(gòu)在瀏覽器中無法處理數(shù)據(jù)
注解
除了用xml進(jìn)行servlet的匹配,我們還可以使用注解的方式進(jìn)行servlet的匹配
@WebServlet(" 規(guī)則 ")
匹配規(guī)則
1.精確匹配與請求路徑的名稱要一致
2.通配符匹配以/* ?“*”代表“/”后面跟任意一個(gè)值都可以訪問 ??/只會攔截靜態(tài)請求
注意:這時(shí)候工程下若有html文件,通過服務(wù)器訪問html文件也會顯示的是servlet的內(nèi)容,也就是通配符匹配表示的是,通過本服務(wù)器不管運(yùn)行什么文件,都會訪問本servlet內(nèi)容
由于工程可能有多個(gè)模塊,也就是多個(gè)類的servlet,所以正常情況下是不會這么使用的,我們會使用@WebServlet("/emp/*")表示的是emp/后面跟什么都可以,這樣確保了emp下的servlet的訪問地址是什么都可以,而不是所有的servlet的訪問地址是什么都可以
3.后綴匹配*.(do,action ,a,n)注意“*”這里必須寫“*”如果不寫“*”會報(bào)錯(cuò),因?yàn)閟ervlet容器會把該地址作為精確匹配來走,但是使用精確匹配前面必須得有“/”
后綴匹配其實(shí)也就是把工程放到了后綴
三種匹配規(guī)則的優(yōu)先級
精確匹配>通配符匹配>后綴匹配>頁面的路徑
單一控制器
使用單一控制器處理請求(不適用它之前,增刪改查都需要有一個(gè)servlet)
使用單一控制器之后,對同一個(gè)對象的多個(gè)請求可以放在一個(gè)servlet里
這時(shí)候我們使用后綴匹配
@WebServlet("*.do")
獲取*表示的內(nèi)容,通過其代表的內(nèi)容決定走的請求
所以我們要先獲取*表示內(nèi)容
String path=request.getRequestURI() ? //這樣我們就獲得了請求的路徑
也可以使用 ?pathInfo() ? 獲取請求路徑的非精確部分/*
/工程名/請求.后綴
這時(shí)我們想要獲得這個(gè)字符串中請求的內(nèi)容,我們要用到字符串中的方法
path=path.substring(path.lastIndexOf("/")+1,path.lastIndexOf("."))
這樣我們就獲得了請求的內(nèi)容,之后通過equals方法進(jìn)行比較,執(zhí)行響應(yīng)請求就可以了