Servlet中request請求Get和Post方法以及亂碼解決

codingcoge發表於2018-06-09

前言:

傳遞的請求引數如何獲取

GET方式: 引數放在URI後面
 POST方式: 引數放在實體內容中

後臺獲取前臺資料方法:

獲取GET方式引數:
request.getQueryString();
獲取POST方式引數:
request.getInputStream();

但是以上兩種不通用,而且獲取到的引數還需要進一步地解析。
request.getParameter代替。

核心的API:
request.getParameter("引數名");  根據引數名獲取引數值(注意,只能獲取一個值的引數)
request.getParameterValue("引數名“);根據引數名獲取引數值(可以獲取多個值的引數)
request.getParameterNames();   獲取所有引數名稱列表  
request.setCharacterEncoding("utf-8");修改實體內容編碼格式。

注意:

request.setCharacterEncoding可以設定Response容器的實體內部  
編碼格式,而對URL(GET)編碼無效。先了解,下面會解釋。

Html前臺form表單輸入框:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="/haha/dd" method="Get">
使用者名稱:<input type="text" name="name" /><br/>
密碼:<input type="password" name="password" /><br/>
性別:
<input type="radio" name="性別" value="男"/>男
<input type="radio" name="性別" value="女"/>女<br/>
愛好:<br/>
<input type="checkbox" name="喜好" value="籃球"/>籃球<br/>
<input type="checkbox" name="喜好" value="足球"/>足球<br/>
<input type="checkbox" name="喜好" value="月球"/>月球<br/>

隱藏域:<input type="hidden" name="hiden" value="001" /><br/>
籍貫:
<select name="jiguan">
    <option value="廣東">廣東</option>
    <option value="廣西">廣西</option>
    <option value="湖南">湖南</option>
 </select>
<br/>
個人簡介:
<textarea rows="5" cols="10" name="area"></textarea><br/>
<input type="submit" value="提交"/>
</form>
******************************************************************************
<form action="/haha/dd" method="Post">
使用者名稱:<input type="text" name="name" /><br/>
密碼:<input type="password" name="password" /><br/>
性別:
<input type="radio" name="性別" value="男"/>男
<input type="radio" name="性別" value="女"/>女<br/>
愛好:
<input type="checkbox" name="喜好" value="籃球"/>籃球<br/>
<input type="checkbox" name="喜好" value="足球"/>足球<br/>
<input type="checkbox" name="喜好" value="月球"/>月球<br/>

隱藏域:<input type="hidden" name="hiden" value="002" /><br/>
籍貫:
<select name="jiguan">
    <option value="廣東">廣東</option>
    <option value="廣西">廣西</option>
    <option value="湖南">湖南</option>
 </select>
<br/>
個人簡介:
<textarea rows="5" cols="10" name="area"></textarea><br/>
<input type="submit" value="提交"/>
</form>
</body>
</html>

servlet後臺接受:

package a;

import java.io.IOException;
import java.util.Enumeration;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/dd")
public class dd extends HttpServlet {
    private static final long serialVersionUID = 1L;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println(request.getMethod());
        Enumeration<String> enumeration=request.getParameterNames();
        while(enumeration.hasMoreElements()) {
            String name=enumeration.nextElement();
            if("喜好".equals(name)) {
                String[] str=request.getParameterValues(name);
                System.out.println(name+": ");
                for(String string:str) {
                    System.out.println(string);
                }
            }else {
                System.out.println(name+": "+request.getParameter(name));
            }
        }
    }
    
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        this.doGet(request,response);
    }
}

亂碼問題:

request中,在servlet中呼叫Request的getParameter方法返回的  
是 字串(“中國”),方法內部拿到數字後要轉成字元,一定要查碼錶  
由於request的設計者是外國人,所以預設查的是他們常用的ISO8859-1  
這就是請求資料產生亂碼的根源。

注意:

  1. Tomcat8以上版本預設編碼格式是UTF-8
  2. HttpServletRequest和HttpServletResponse容器預設編碼格式是iso-8859-1

Get和Post解碼格式:

request容器儲存的是瀏覽器的資料,一般是UTF-8格式。
request的方法如:getParameter解碼格式會根據Get和Post來設定解碼格式。因為Get和Post的取值放在不同地方。所以要分開考慮。


1. Get是URL解碼方式。預設解碼格式是Tomcat8編碼格式。所以URL解碼是UTF-8,
覆蓋掉了request容器解碼格式
2. Post是實體內容解碼方式。預設解碼格式是request編碼格式。與Tomcat8編碼格式無關

POST:

在測試中發現,tomcat伺服器中Response容器預設以ISO8859-1的編碼解析資料,因此如果需要在引數中解析中文,需要設定

request.setCharacterEncoding("utf-8");

注意:要寫在request.getParameter前面

  • 設定引數查詢的編碼
  • 該方法只能對Response容器的請求實體內容的資料編碼起作用。POST提交的資料在實體內容中,所以該方法對POST方法有效!
  • GET方法的引數放在URI後面,所以對GET方式無效!!!

Get:

雖然 Response容器預設以ISO8859-1的編碼解析資料
但是對於get請求提交的資料,在不同版本的tomcat中有不同的處理方式,在tomcat8及以上的版本,伺服器預設以utf-8的編碼方式處理請求引數

辦法一:tomcat版本8以上不用指定編碼格式,預設utf-8

而對於tomcat8以下的版本,伺服器會預設以ISO8859-1的編碼方式處理請求引數

方法二:編碼二次轉換 推薦

注意:

utf-8-》iso-8859-1》utf-8   原樣
utf-8-》GBK-》utf-8         亂碼

具體可以參考這篇:
https://blog.csdn.net/qq_38409944/article/details/80637345

現在基本都是Tomcat8以上版本 ,所以不存在編碼問題,而如果是Tomcat8以下版本解決方案:

手動解碼:String name =   
new String(name.getBytes("iso-8859-1"),"utf-8");

方法三:設定指定解碼URL的編碼格式:URIEncoding=”UTF-8″ 不推薦 依賴伺服器,有時候沒法設定伺服器

另外,在tomcat目錄下的/conf中的server.xml中我們也可以手動配置tomcat預設的編碼方式,在 <Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>這段程式碼中新增一個URIEncoding引數,可以配置tomcat的預設編碼方式。

<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443" URIEncoding="UTF-8"/>

但是不推薦。

方法四:請求引數的編碼方式要採用請求體的編碼方式 不推薦 依賴伺服器,有時候沒法設定伺服器

useBodyEncodingForURI=true是說,。當useBodyEncodingForURI=true時,若請求體採用utf-8解析,則請求引數也要採用utf-8來解析。

server.html:
<Connector port="8080" protocol="HTTP/1.1"   connectionTimeout="20000"   redirectPort="8443" useBodyEncodingForURI="true" />
Servlet:
doGet(){
request.setCharacterEncoding("utf-8");
}

分析:request.setCharacterEncoding("utf-8");只是作用於實體內部,意思就是說對Post有效,對Get無效。
但是設定useBodyEncodingForURI="true"後URL解碼格式和實體內容解碼格式一樣。
注意:如果只是設定useBodyEncodingForURI="true那get URL解碼格式就是預設iso-8859-1,因為實體內部預設是這個解碼格式,即使Tomcat版本8以上預設編碼格式為UTF-8也會被iso-8859-1覆蓋掉。

總結:

  1. 中文建議post而不是get
  2. Tomcat8版本以上預設是UTF-8對GET方法來說,對POST無效,
    因為request.getParameter預設呼叫·iso-8859-1·
  3. get方式引數存放在請求資料包的請求行的URI欄位中,以?開始以param=value&parame2=value2的形式附加在URI欄位之後。
    而Post是放在實體內部。
  4. 而request.setCharacterEncoding(charset);只對訊息體中的資料起作用,對於URI欄位中的引數不起作用。預設作用於POST,對POST無效。 當使用request.setCharacterEncoding(charset);時,只能解決表單方法為POST的中文亂碼情況,而方法為GET的依然為亂碼。
  5. request.setCharacterEncoding(“UTF-8”);
  6. useBodyEncodingForURI=”true”目的是URL解碼格式和實體內部解碼格式相同。
  7. 如果使用JS程式設計時,在瀏覽器可以使用encodeURIComponent函式對中文引數進行編碼後再拼裝引數。

參考:
https://blog.csdn.net/sinat_26503455/article/details/53584139
https://www.cnblogs.com/keyi/p/6365649.html
https://blog.csdn.net/hackersaillen/article/details/46965357


相關文章