日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

Servlet一次乱码排查后的总结

發(fā)布時(shí)間:2025/3/21 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Servlet一次乱码排查后的总结 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

為什么80%的碼農(nóng)都做不了架構(gòu)師?>>> ??

由來(lái)

在寫一個(gè)小小的表單提交功能的時(shí)候,出現(xiàn)了亂碼,很奇怪request上來(lái)的參數(shù)全部是亂碼,而從數(shù)據(jù)庫(kù)查詢出來(lái)的中文顯示到頁(yè)面正常,鎖定肯定是request對(duì)象那里出了問(wèn)題。后來(lái)經(jīng)過(guò)排查,發(fā)現(xiàn)是我封裝的框架中出了問(wèn)題,總結(jié)為在setCharacterEncoding方法之前,調(diào)用了getParameter方法,導(dǎo)致字符集改變失敗。沒(méi)看過(guò)Tomcat實(shí)現(xiàn)Servlet的源碼,貌似是一旦調(diào)用getParameter方法Request的參數(shù)就會(huì)全部被解析,從而再調(diào)用setCharacterEncoding就無(wú)效了。

原理解析

其實(shí)編碼問(wèn)題本質(zhì)還是兩點(diǎn):

  • 瀏覽器在封裝Http請(qǐng)求的時(shí)候的編碼和服務(wù)器在解析Http請(qǐng)求編碼不一致
  • 服務(wù)器返回?cái)?shù)據(jù)的時(shí)候編碼和瀏覽器解析不同。
  • 那么我們就從這兩點(diǎn)入手解析。

    瀏覽器請(qǐng)求

    在點(diǎn)擊提交表單的那一刻,瀏覽器把表單內(nèi)容封裝成一個(gè)Http請(qǐng)求,數(shù)據(jù)通過(guò)a=1&b=2這樣的形式直接請(qǐng)求服務(wù)器,表單值會(huì)被瀏覽器最一次urlencode,對(duì)于不同的請(qǐng)求方式編碼不同:

    Get和Post請(qǐng)求

    瀏覽器會(huì)讀取頁(yè)面的編碼(頁(yè)面編碼會(huì)在Content-type頭中體現(xiàn)),用此編碼對(duì)表單值做urlencode,那么到服務(wù)器的編碼方式就是你Content-Type里的編碼。很多通過(guò)JS提交表單為了規(guī)避瀏覽器的urlencode帶來(lái)的編碼混淆,會(huì)對(duì)數(shù)據(jù)首先做一次urlencode,這樣在服務(wù)器上做一次urldecode既可(因?yàn)閖s做完urlencode后內(nèi)容為ASCII字符,所以這樣的字符無(wú)論瀏覽器用什么編碼解碼出來(lái)都是一樣的)

    AJAX請(qǐng)求

    在Jquery中AJAX請(qǐng)求全部使用utf8編碼封裝請(qǐng)求,如果你的頁(yè)面和項(xiàng)目用的非utf8編碼,一定會(huì)出現(xiàn)亂碼

    瀏覽器地址欄直接輸入帶參數(shù)的地址

    這種情況就比較復(fù)雜,不同的瀏覽器編碼也不相同。Chrome之類的瀏覽器默認(rèn)使用utf8編碼(urlencode),而IE則使用GBK(死變態(tài)IE!!!)。

    服務(wù)器端解碼

    對(duì)于服務(wù)器端我在此只討論Servlet。

    Get請(qǐng)求

    對(duì)于Get請(qǐng)求,有兩種方式解碼:

  • 在Servlet容器中設(shè)置,例如Tomcat設(shè)置URIEncoding="UTF-8",就會(huì)對(duì)Get請(qǐng)求用utf8解碼(貌似Tomcat7會(huì)報(bào)無(wú)效,具體解決請(qǐng)百度,反正我不同這種方法)
  • String name = new String(request.getParameter("name").getBytes("iso-8859-1"),"GBK"));第一個(gè)編碼就是你Servlet容器(例如Tomcat)里設(shè)置的編碼,默認(rèn)iso-8859-1,第二個(gè)參數(shù)就是你瀏覽器使用的編碼格式。如果你用表單提交,那這個(gè)編碼就是頁(yè)面的編碼(Content-Type里的charset=XXX),如果你直接用瀏覽器地址欄里敲,恭喜你,你得判斷userAgent來(lái)使用不同編碼了。這也是我為啥不提倡第一種方式,因?yàn)樗龅綖g覽器直接敲出來(lái)的參數(shù)就非常不靈活。
  • 至于為什么要使用getBytes("iso-8859-1"),是因?yàn)樵谀銥g覽器用某種編碼后,Servlet容器自作多情給你用iso-8859-1解碼了一下,如果你設(shè)置了URIEncoding="UTF-8"它就會(huì)用utf8給你解碼,運(yùn)氣好你瀏覽器用的也是這種編碼,那解出來(lái)就直接用了,所以在ISO-8859-1的情況下你得再“原路返回”到二進(jìn)制,重新用正確的編碼解碼一下。

    Post請(qǐng)求和Ajax請(qǐng)求

    Post請(qǐng)求就比較簡(jiǎn)單一點(diǎn)了,同樣你可以使用Get請(qǐng)求中的方法2來(lái)解決,不過(guò)比較麻煩,這時(shí)候我們就可以使用Servlet里的方法request.setCharacterEncoding方法設(shè)置你的解碼類型,例如你的頁(yè)面編碼是utf8,表單則urlencode成utf8了,那么你在調(diào)用getParameter方法之前(記住,一定要之前!!在第一次調(diào)用getParameter之前!)使用setCharacterEncoding方法。 Ajax請(qǐng)求同理。

    響應(yīng)請(qǐng)求

    響應(yīng)也是相同道理,這回輪到服務(wù)器做編碼,瀏覽器做解碼。只需要設(shè)置response.setCharacterEncoding,就會(huì)自動(dòng)在響應(yīng)頭的Content-Type中加入charset=XXX,返回的內(nèi)容就可以被正常解析啦~

    我想我說(shuō)的相對(duì)比較清楚了,網(wǎng)上很多解決亂碼的帖子都只是講你加上某句代碼就會(huì)解決,這樣是不科學(xué)的,一定也要知道原理,也要知道每句代碼背后做了哪些工作。其實(shí)我們?cè)诓僮鱄ttpServlet對(duì)象的時(shí)候,本質(zhì)上是對(duì)Http頭的一些信息做修改。

    如果有什么問(wèn)題或者理解錯(cuò)誤的地方,歡迎指正討論。

    轉(zhuǎn)載于:https://my.oschina.net/looly/blog/287255

    總結(jié)

    以上是生活随笔為你收集整理的Servlet一次乱码排查后的总结的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。