寫這麼久的Web多少都會遇到亂碼的問題,不論是Web頁面的的亂碼、收到Client資訊的亂碼或是連你的log console的曾出現亂嗎,今天我們就來整理這些問題
簡單說就是編碼與解碼使用不同的字元集,比如說你在編輯文件的時候使用UTF-8編碼,但是在讀取檔案的時候使用BIG5的方式。
由於intellij會自動的偵測你的charset設定轉換編碼,所以先用nopad++編輯檔案用big5的編碼存檔。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Garbled</title>
</head>
<body>
哈囉你好~~~
</body>
</html>
啟動tomcat,訪問Garbled.html
這是因為文件是使用big5進行儲存,瀏覽器是從meta這個tag標籤來決定使用什麼編碼進行decoding,修正後就可以讀到正確的文字了。
@WebServlet("/DemoConsoleGarbledServlet")
public class DemoConsoleGarbledServlet extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res){
System.out.println("訪問DemoConsoleGarbledServlet");
}
}
啟動tomcat,訪問DemoConsoleGarbledServlet,查看server console出現亂碼
這是因為java編譯與加載.class檔案時使用的編碼不同,我們可以透過VM option設定D-file.encoding=UTF-8,就可以解決這個問題
相關logging編碼設定檔可以參考Tomcat/conf/logging.properties
留意meta charset設為big5
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="big5">
<title>RequestFormGet</title>
</head>
<body>
<form action="HandleForm" method="get">
<label for="username">姓名:</label>
<input type="text" id="username" name="username" required><br><br>
<input type="submit" value="送出">
</form>
</body>
</html>
建立HandleFormServlet
@WebServlet("/HandleFormGet")
public class HandleFormServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response){
System.out.println("=====HandleFormGet=====");
System.out.println(request.getParameter("username"));
}
}
輸入劉德華後送出
後端log
當我們在meta設置為big5後,送出的get請求會對傳送參數以big5進行URL encode,兒而在tomcat預設是以UTF-8進行解碼,若要修改這個設置,我們可以到下面設定檔進行修改,一般不建議這樣做,html亦維持UTF-8編碼。
設置如下
html內容同上,修改為Post
HandleFormServlet增加doPost方法
@WebServlet("/HandleForm")
public class HandleFormGetServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("=====HandleFormPost=====");
//req.setCharacterEncoding("big5");
System.out.println(req.getParameter("username"));
}
}
輸入劉德華後送出
後端console
由於前端使用big5進行request body編碼,但後端使用UTF-8進行解析,故出現亂碼。只要在提取資料前設置request的編碼在提取數據就可以解決該問題。
create DemoResponseGarbledServlet
@WebServlet("/DemoResponseGarbledServlet")
public class DemoResponseGarbledServlet extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
//設置response body使用UTF-8進行編碼
//resp.setCharacterEncoding("UTF-8");
//告訴client瀏覽器解析的編碼
//resp.setContentType("text/html;charset=UTF-8");
resp.getWriter().write("哈囉DemoResponseGarbledServlet~~");
}
}
由於瀏覽器收到response訊息時未收到解析編碼的訊息,故用OS預設編碼進行解析,可以透過設定setCharacterEncoding與setContentType來解決此問題。