解決Request獲取請(qǐng)求數(shù)據(jù)中文亂碼問題
Tomcat在7以及更低版本時(shí),解析中文的字符集默認(rèn)為ISO-8859-1,并且是在底層寫死的,所以瀏覽器發(fā)送Get請(qǐng)求或者時(shí)Post請(qǐng)求時(shí),字符集格式不匹配,從而引發(fā)中文亂碼。
但是Tomcat更新到8版本后,默認(rèn)字符集就更換為了UTF-8。
一、當(dāng)Request請(qǐng)求字母時(shí),輸出正常
package com.huanle.web; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * @author 歡了 * @version 1.0 */ @WebServlet("/req3") public class RequestDemo3 extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("==========字母情況下==========="); String username = request.getParameter("username"); System.out.println(username); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
啟動(dòng)Tomcat 在輸入框 姓名里 輸入字母abc
點(diǎn)擊提交跳轉(zhuǎn)到上面代碼開始執(zhí)行
控制臺(tái)打印abc
一切正常
二、當(dāng)Request請(qǐng)求參數(shù)為漢字時(shí)
啟動(dòng)Tomcat 在姓名框中輸入中文 張三
跳轉(zhuǎn)頁面
看控制臺(tái)的輸出
輸入的張三在控制臺(tái)里呈現(xiàn)的就是亂碼
三、使用偽代碼了解亂碼的形成
解決亂碼問題之前,首先我們要了解亂碼的形成。
我們寫一個(gè)測(cè)試類,里面用到了URL編碼,我們先了解一下;
URL編碼
- 1. 將字符串按照編碼格式轉(zhuǎn)為二進(jìn)制
- 2.每個(gè)字節(jié)轉(zhuǎn)為2個(gè)16進(jìn)制數(shù),并在前面加上 %
例如 張三
假設(shè)瀏覽器給Tomcat發(fā)送的字符集格式為UTF-8,即編碼格式為UTF-8;Tomcat也用UTF-8來接收,即解碼格式也為UTF-8,那么就可以正常的接收到 "張三" 。
但是由于tomcat的默認(rèn)解碼是ISO-8859-1,并且還是底層是寫死的,就只能走下面示例tomcatDecode對(duì)象(亂碼)。
tomcatDecode對(duì)象直接轉(zhuǎn)UTF-8雖然會(huì)出問題,但是底層的二進(jìn)制是不會(huì)變的,我們就有了一個(gè)思路:
先將tomcatDecode的解碼%E5%BC%A0%E4%B8%89 轉(zhuǎn)為字節(jié)數(shù)組(-27 -68 -96 -28 -72 -119)
再將字節(jié)數(shù)組轉(zhuǎn)為字符串。
package com.huanle.web; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.net.URLEncoder; /** * @author 歡了 * @version 1.0 * * 演示瀏覽器的URL編碼 和 tomcat的URL解碼 * 以及解決默認(rèn)tomcat字符集中文亂碼 */ public class UrlDemo { public static void main(String[] args) throws UnsupportedEncodingException { String username = "張三"; //URL編碼 String encode = URLEncoder.encode(username, "UTF-8"); System.out.println(encode);//%E5%BC%A0%E4%B8%89 //URL解碼 String decode = URLDecoder.decode(encode, "UTF-8"); System.out.println(decode);//張三 //但是tomcat的默認(rèn)解碼是ISO-8859-1,并且底層是寫死的 String tomcatDecode = URLDecoder.decode(encode, "ISO-8859-1"); System.out.println(tomcatDecode); /** * 解決get請(qǐng)求的中文亂碼 * 將tomcat的亂碼,先用tomcat默認(rèn)的字符集ISO-8859-1轉(zhuǎn)為字節(jié)數(shù)組 編碼 * 再將字節(jié)數(shù)組轉(zhuǎn)為字符串 解碼 * */ byte[] bytes = tomcatDecode.getBytes("ISO-8859-1"); //可以先遍歷看一下 for (byte b : bytes) { System.out.print(b + " "); }//-27 -68 -96 -28 -72 -119 //換行 System.out.println(); //將這些十進(jìn)制轉(zhuǎn)為字符串 String s = new String(bytes, "UTF-8"); System.out.println(s);//張三 } }
最終的結(jié)果如下:
四、Request請(qǐng)求參數(shù)中文亂碼-Post請(qǐng)求解決方案
講完上面的案例,大家也就知道為什么中文會(huì)出現(xiàn)亂碼了,我們就在代碼中解決
因?yàn)镻ost是通過流的getReader()方法來傳輸數(shù)據(jù),只需要改變流的編碼格式為utf-8即可
我們需要用到一個(gè)方法 setCharacterEncoding(""); //這里的參數(shù)是編碼格式
啟動(dòng)Tomcat 姓名為 張三
跳轉(zhuǎn)頁面后沒有顯示請(qǐng)求參數(shù) ,所以是Post請(qǐng)求
package com.huanle.web; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * @author 歡了 * @version 1.0 * * 中文亂碼解決方案 */ @WebServlet("/req4") public class RequestDemo4 extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1.先解決亂碼問題Post,因?yàn)镻ost是通過流getReader()方法 傳輸數(shù)據(jù),改變流的編碼格式為utf-8 request.setCharacterEncoding("utf-8"); //2.獲取username System.out.println("==========獲取username========="); String username = request.getParameter("username"); System.out.println("解決后" + username); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
輸出正常! 解決~
五、Request請(qǐng)求參數(shù)中文亂碼-Get請(qǐng)求解決方案
get請(qǐng)求就很像我們舉得測(cè)試類里的例子
先將亂碼的數(shù)據(jù)轉(zhuǎn)成字節(jié)數(shù)組
再將字節(jié)數(shù)組轉(zhuǎn)成字符串
package com.huanle.web; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * @author 歡了 * @version 1.0 * * 中文亂碼解決方案 */ @WebServlet("/req4") public class RequestDemo5 extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1.獲取username System.out.println("==========獲取username========="); String username = request.getParameter("username"); System.out.println("解決前:" + username); //2.解決亂碼問題Get Get是通過getQueryString // 亂碼原因,tomcat進(jìn)行URL解碼的時(shí)候用的是ISO-8859-1的字符集,和頁面字符集不匹配 // 解決方案: // 2.1 先將亂碼的數(shù)據(jù)轉(zhuǎn)成字節(jié)數(shù)組 // 2.2 再將字節(jié)數(shù)組轉(zhuǎn)成字符串 byte[] bytes = username.getBytes("ISO-8859-1"); String s = new String(bytes, "UTF-8"); System.out.println("解決后:" + s); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
啟動(dòng)Tomcat
跳轉(zhuǎn)頁面,有顯示參數(shù),表明是Get請(qǐng)求
輸出正常!解決~
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java通過數(shù)據(jù)庫表生成實(shí)體類詳細(xì)過程
這篇文章主要介紹了Java通過數(shù)據(jù)庫表生成實(shí)體類,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2023-02-02springBoot?之spring.factories擴(kuò)展機(jī)制示例解析
這篇文章主要為大家介紹了springBoot?之spring.factories擴(kuò)展機(jī)制示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04Spring容器注冊(cè)組件實(shí)現(xiàn)過程解析
這篇文章主要介紹了Spring容器注冊(cè)組件實(shí)現(xiàn)過程解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-03-03Java中的非對(duì)稱加密算法原理與實(shí)現(xiàn)方式
在當(dāng)今的信息時(shí)代,數(shù)據(jù)安全已經(jīng)成為了一個(gè)至關(guān)重要的問題,加密技術(shù)作為保障信息安全的重要手段,受到了廣泛的應(yīng)用和關(guān)注,本篇文章將詳細(xì)介紹Java中的非對(duì)稱加密算法原理及其實(shí)現(xiàn)方式,需要的朋友可以參考下2023-12-12java遠(yuǎn)程連接調(diào)用Rabbitmq的實(shí)例代碼
本篇文章主要介紹了java遠(yuǎn)程連接調(diào)用Rabbitmq的實(shí)例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-07-07Mybatis數(shù)據(jù)批量插入如何實(shí)現(xiàn)
這篇文章主要介紹了Mybatis數(shù)據(jù)批量插入如何實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-07-07spring-boot-autoconfigure模塊用法詳解
autoconfigure就是自動(dòng)配置的意思,spring-boot通過spring-boot-autoconfigure體現(xiàn)了"約定優(yōu)于配置"這一設(shè)計(jì)原則,而spring-boot-autoconfigure主要用到了spring.factories和幾個(gè)常用的注解條件來實(shí)現(xiàn)自動(dòng)配置,思路很清晰也很簡單,感興趣的朋友跟隨小編一起看看吧2022-11-11Java并發(fā)編程之Semaphore(信號(hào)量)詳解及實(shí)例
這篇文章主要介紹了Java并發(fā)編程之Semaphore(信號(hào)量)詳解及實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-06-06