第五部分 Servlet 進(jìn)階

常用對象

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)請求就可以了

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,506評論 19 139
  • 從三月份找實(shí)習(xí)到現(xiàn)在,面了一些公司,掛了不少,但最終還是拿到小米、百度、阿里、京東、新浪、CVTE、樂視家的研發(fā)崗...
    時(shí)芥藍(lán)閱讀 42,759評論 11 349
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 47,254評論 6 342
  • 一、ServerLet是什么?什么是CGI程序? 答:ServerLet是運(yùn)用在web服務(wù)器或運(yùn)用服務(wù)器上的程序作...
    歸來的良人閱讀 1,480評論 1 10

友情鏈接更多精彩內(nèi)容