1. 程式人生 > >Get 與Post 請求資料亂碼處理

Get 與Post 請求資料亂碼處理

Get 與Post 請求方式下中文資料的響應處理

1. 前言

某交流群
Just now

提問者:
    Get 請求,中文亂碼怎麼處理?
熱心人:
    對request 設定編碼格式為UTF-8 能解決。
    就是下面這樣
    request.setCharacterEncoding(“UTF-8”);
    response.setCharacterEncoding(“UTF-8”);

Soon

提問者:
    這樣不行,獲取資料還是亂碼的。

    WTF,N 先生心想著,之前就是靠著上面那兩行程式碼行(keng)走(meng)天(guai)下(pian)的。不行嗎?我得試試。

2. 模擬Get/Post 請求與響應

2.1 新建一個Servlet 測試編碼轉換

    新建一個Java Web Project,在src 下新建package 命名為pers.niaonao.servlet,在此包新建Servlet 命名為GetPostServlet,用作處理前臺模擬的請求。配置GetPostServlet 到專案配置檔案web.xml。編寫index.jsp 用作前端頁面模擬傳送Get/Post 請求。
2.1.1 web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <servlet>
<servlet-name>GetPostServlet</servlet-name> <servlet-class>pers.niaonao.servlet.GetPostServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>GetPostServlet</servlet-name> <url-pattern>/GetPostServlet</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>

2.2 新建一個JSP 模擬請求

2.2.1 index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
</head>
<body>
<hr>
模擬Get 請求
<form action="GetPostServlet" method="get">
    賬戶:<input type="text" name="name"/><br>
    密碼:<input type="password" name="password"/><br>
    <input type="submit" value="提交Get 請求"/>
</form>
<hr>
模擬Post 請求
<form action="GetPostServlet" method="post">
    賬戶:<input type="text" name="name"/><br>
    密碼:<input type="password" name="password"/><br>
    <input type="submit" value="提交Post 請求"/>
</form>
</body>
</html>

    頁面請求資料有兩個欄位name 和password,使name 傳遞中文資料,password 為英文字母或阿拉伯數字等。
    後臺響應前臺發出的請求,並獲取請求攜帶的資料name、password,做編碼轉換,使能正常獲取中文資料。
    下面是Servlet 的處理。
2.2.2 GetPostServlet.java

package pers.niaonao.servlet;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;

public class GetPostServlet extends HttpServlet {

    public final String UTF_8 = "UTF-8";
    public final String ISO_8859_1 = "ISO-8859-1";

    /**
     * 字串編碼轉換方法
     * @param str 字串
     * @param sourceCharset 源編碼
     * @param targetCharset 目標編碼
     * @return
     * @throws UnsupportedEncodingException
     */
    public String changeCharset(String str, String sourceCharset, String targetCharset) throws UnsupportedEncodingException {
        if (str == null) {
            return null;
        }
        //用舊的字元編碼解碼字串。解碼可能會出現異常。
        byte[] bs = str.getBytes(sourceCharset);
        //用新的字元編碼生成字串
        return new String(bs, targetCharset);
    }

    /**
     * Get 請求響應方法
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String name = request.getParameter("name");
        String password = request.getParameter("password");
        //處理亂碼,將通過Get 方式請求資料使用UTF-8 編碼解析
        name = changeCharset(name, ISO_8859_1, UTF_8);
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("<br>$$$ GetServlet 處理後:$$$<br>name: " + name + "<br>password: " + password);

        //設定response
        response.setCharacterEncoding(UTF_8);
        response.setContentType("text/html");
        //輸出文字到瀏覽器
        response.getWriter().printf(stringBuilder.toString());
    }

    /**
     * Post 請求響應方法
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
        //處理亂碼,將通過Post 方式請求資料使用UTF-8 編碼解析
        request.setCharacterEncoding(UTF_8);
        String name = request.getParameter("name");
        String password = request.getParameter("password");
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("<br>$$$ PostServlet 處理後:$$$<br>name: " + name + "<br>password: " + password);

        //設定response
        response.setCharacterEncoding(UTF_8);
        response.setContentType("text/html");
        //輸出文字到瀏覽器
        response.getWriter().printf(stringBuilder.toString());
    }
}

    通過Tomcat 部署一下,執行專案,訪問index.jsp,在頁面輸入資料並請求Servlet 來測試。
    測試結果如下,可以看到兩種請求方式下的中文亂碼問題都能被解決。
    另外對於Get 請求使用request.setCharacterEncoding(“utf-8”); 確實不能正確處理中文亂碼問題。

圖2-1、index.jsp 前端頁面圖
這是一張圖片
圖2-2、Get 請求響應圖
這是一張圖片
圖2-3、Post 請求響應圖
這是一張圖片

3. 簡單總結

3.1 Get 請求方式

    Tomcat 預設的編碼為ISO-8859-1,所以Get 請求亂碼問題可以通過修改Tomcat 預設配置編碼為UTF-8 來處理。但不建議那樣處理。
    從上面的栗子中可以看到,這裡仍然是通過程式碼處理。此處用了一個字串編碼轉換的方法。將請求的資料從編碼ISO-8859-1 轉換為UTF-8 編碼下的資料即可。

    /**
     * 字串編碼轉換方法
     * @param str 字串
     * @param sourceCharset 源編碼
     * @param targetCharset 目標編碼
     * @return
     * @throws UnsupportedEncodingException
     */
    public String changeCharset(String str, String sourceCharset, String targetCharset) throws UnsupportedEncodingException {
        if (str == null) {
            return null;
        }
        //用舊的字元編碼解碼字串。解碼可能會出現異常。
        byte[] bs = str.getBytes(sourceCharset);
        //用新的字元編碼生成字串
        return new String(bs, targetCharset);
    }

3.2 Post 請求方式

    而Post 則直接對request 物件設定編碼格式為UTF-8 即可。相應的響應物件response 也可以設定編碼格式為UTF-8。

request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");

更多亂碼問題的處理方式