1. 程式人生 > >javaweb中表單post和get提交方式出現亂碼原因

javaweb中表單post和get提交方式出現亂碼原因

最近在學javaweb遇到了亂碼問題,一直不太明白其中的具體原因,看了這篇文章明白了不少。感覺很有用所以把它轉載過來,方便以後檢視。

一、問題:

        編碼問題是JAVA初學者在web開發過程中經常會遇到問題,網上也有大量相關的文章介紹,但其中很多文章並沒有對URL中使用了中文等非ASCII的字 符造成伺服器後臺程式解析出現亂碼的問題作出準確的解釋和說明。本文將詳細介紹由於在URL中使用了中文等非ASCII的字元造成亂碼的問題。


2、出現亂碼問題的原因主要是以下幾方面:
(1)、瀏覽器:我們的客戶端(瀏覽器)本身並沒有遵循URI編碼的規範(http://www.w3.org/International/O-URL-code.html

)。
(2)、Servlet伺服器:Servlet伺服器的沒有正確配置。
(3)、開發人員並不瞭解Servlet的規範和API的含義。

二、基礎知識:
1、一個http請求經過的幾個環節:
瀏覽器(ie firefox)【get/post】------------>Servlet伺服器------------------------------->瀏覽器顯示
                               編碼                 解碼成unicode,然後將顯示的內容編碼        解碼
(1) 瀏覽器把URL(以及post提交的內容)經過編碼後傳送給伺服器。
(2) 這裡的Servlet伺服器實際上指的是由Servlet伺服器提供的servlet實現ServletRequestWrapper,不同應用伺服器的 servlet實現不同,這些servlet的實現把這些內容解碼轉換為unicode,處理完畢後,然後再把結果(即網頁)編碼返回給瀏覽器。
(3) 瀏覽器按照指定的編碼顯示該網頁。

        當對字串進行編碼和解碼的時候都涉及到字符集,通常使用的字符集為ISO8859-1、GBK、UTF-8、UNICODE。


2、URL的組成:
域名:埠/contextPath/servletPath/pathInfo?queryString
說明:

1、ContextPath是在Servlet伺服器的配置檔案中指定的。
對於weblogic:
contextPath是在應用的weblogic.xml中配置。
 <context-root>/</context-root>
 
對於tomcat:
contextPath是在server.xml中配置。
<Context path="/" docBase="D:/server/blog.war" debug="5" reloadable="true" crossContext="true"/>

對於jboos:
contextPath是在應用的jboss-web.xml中配置。
<jboss-web>
    <context-root>/</context-root>
</jboss-web>

2、ServletPath是在應用的web.xml中配置。
<servlet-mapping>
    <servlet-name>Example</servlet-name>
    <url-pattern>/example/*</url-pattern>
</servlet-mapping>

2、Servlet API
我們使用以下servlet API獲得URL的值及引數。
request.getParameter("name");         // 獲得queryString的引數值(來自於get和post),其值經過Servlet伺服器URL Decode過的
request.getPathInfo();                // 注意:pathinfo返回的字串是經過Servlet伺服器URL Decode過的。
requestURI = request.getRequestURI(); // 內容為:contextPath/servletPath/pathinfo 瀏覽器提交過來的原始資料,未被Servlet伺服器URL Decode過。


3、開發人員必須清楚的servlet規範:
(1) HttpServletRequest.setCharacterEncoding()方法 僅僅只適用於設定post提交的request body的編碼而不是設定get方法提交的queryString的編碼。該方法告訴應用伺服器應該採用什麼編碼解析post傳過來的內容。很多文章並沒 有說明這一點。
(2) HttpServletRequest.getPathInfo()返回的結果是由Servlet伺服器解碼(decode)過的。
(3) HttpServletRequest.getRequestURI()返回的字串沒有被Servlet伺服器decoded過。
(4) POST提交的資料是作為request body的一部分。
(5) 網頁的Http頭中ContentType("text/html; charset=GBK")的作用:
   (a) 告訴瀏覽器網頁中資料是什麼編碼;
   (b) 表單提交時,通常瀏覽器會根據ContentType指定的charset對錶單中的資料編碼,然後傳送給伺服器的。
   這裡需要注意的是:這裡所說的ContentType是指http頭的ContentType,而不是在網頁中meta中的ContentType。


三、下面我們分別從瀏覽器和應用伺服器來舉例說明:
URL:http://localhost:8080/example/中國?name=中國
漢字   編碼      二進位制表示
中國   UTF-8     0xe4 0xb8 0xad 0xe5 0x9b 0xbd[-28, -72, -83, -27, -101, -67]
中國   GBK       0xd6 0xd0 0xb9 0xfa[-42, -48, -71, -6]
中國   ISO8859-1 0x3f,0x3f[63, 63]資訊失去


(一)、瀏覽器
1、GET方式提交,瀏覽器會對URL進行URL encode,然後傳送給伺服器。
(1) 對於中文IE,如果在高階選項中選中總以UTF-8傳送(預設方式),則PathInfo是URL Encode是按照UTF-8編碼,QueryString是按照GBK編碼。
http://localhost:8080/example/中國?name=中國
實際上提交是:
GET /example/%E4%B8%AD%E5%9B%BD?name=%D6%D0%B9%FA

(1) 對於中文IE,如果在高階選項中取消總以UTF-8傳送,則PathInfo和QueryString是URL encode按照GBK編碼。
實際上提交是:
GET /example/%D6%D0%B9%FA?name=%D6%D0%B9%FA

(3) 對於中文firefox,則pathInfo和queryString都是URL encode按照GBK編碼。
實際上提交是:
GET /example/%D6%D0%B9%FA?name=%D6%D0%B9%FA

很顯然,不同的瀏覽器以及同一瀏覽器的不同設定,會影響最終URL中PathInfo的編碼。對於中文的IE和FIREFOX都是採用GBK編碼QueryString。

小結:解決方案:
1、URL中如果含有中文等非ASCII字元,則瀏覽器會對它們進行URLEncode。為了避免瀏覽器採用了我們不希望的編碼,所以最好不要在URL中直接使用非ASCII字元,而採用URL Encode編碼過的字串%.
比如:
URL:http://localhost:8080/example/中國?name=中國
建議:
URL:http://localhost:8080/example/%D6%D0%B9%FA?name=%D6%D0%B9%FA

2、我們建議URL中PathInfo和QueryString採用相同的編碼,這樣對伺服器端處理的時候會更加簡單。

2、還有一個問題,我發現很多程式設計師並不明白URL Encode是需要指定字符集的。

2、 POST提交
        對於POST方式,表單中的引數值對是通過request body傳送給伺服器,此時瀏覽器會根據網頁的ContentType("text/html; charset=GBK")中指定的編碼進行對錶單中的資料進行編碼,然後發給伺服器。
在伺服器端的程式中我們可以通過Request.setCharacterEncoding() 設定編碼,然後通過request.getParameter獲得正確的資料。

解決方案:
1、從最簡單,所需代價最小來看,我們對URL以及網頁中的編碼使用統一的編碼對我們來說是比較合適的。
如果不使用統一編碼的話,我們就需要在程式中做一些編碼轉換的事情。這也是我們為什麼看到有網路上大量的資料介紹如何對亂碼進行處理,其中很多解決方案都只是一時的權宜之計,沒有從根本上解決問題。


(二)、Servlet伺服器
        Servlet伺服器實現的Servlet遇到URL和POST提交的資料中含有%的字串,它會按照指定的字符集解碼。下面兩個Servlet方法返回的結果都是經過解碼的:
request.getParameter("name"); 
request.getPathInfo();

這裡所說的"指定的字符集"是在應用伺服器的配置檔案中配置。

(1) tomcat伺服器
對於tomcat伺服器,該檔案是server.xml
<Connector port="8080" protocol="HTTP/1.1" 
               maxThreads="150" connectionTimeout="20000" 
               redirectPort="8443" URIEncoding="GBK"/>
URIEncoding告訴伺服器servlet解碼URL時採用的編碼。

<Connector port="8080" ... useBodyEncodingForURI="true" />
useBodyEncodingForURI告訴伺服器解碼URL時候需要採用request body指定的編碼。

(2) weblogic伺服器
對於weblogic伺服器,該檔案是weblogic.xml 
<input-charset>
  <java-charset-name>GBK</java-charset-name>
</input-charset>

(三)瀏覽器顯示
        瀏覽器根據http頭中的ContentType("text/html; charset=GBK"),指定的字符集來解碼伺服器傳送過來的位元組流。我們可以呼叫 HttpServletResponse.setContentType()設定http頭的ContentType。



相關推薦

javaweb中表postget提交方式出現亂碼原因

最近在學javaweb遇到了亂碼問題,一直不太明白其中的具體原因,看了這篇文章明白了不少。感覺很有用所以把它轉載過來,方便以後檢視。 一、問題:         編碼問題是JAVA初學者在web開發過程中經常會遇到問題,網上也有大量相關的文章介紹,但其中很

在JSP中,使用get提交方式出現亂碼時,為什麼要使用new String(s.getBytes("iso-8859-1"),"utf-8");?

最近在學JSP,在學習處理get方式提交資料出現亂碼問題的時候,對其中的一個解決方法new String(s.getBytes("iso-8859-1"),"utf-8");產生了疑問,就是為什麼要使用s.getBytes("iso-8859-1")?   當時只這樣想

form表postget提交方式分析以及產生的亂碼問題

Form提供了兩種資料傳輸的方式——get和post。雖然它們都是資料的提交方式,但是在實際傳輸時確有很大的不同,並且可能會對資料產生嚴重的影響。雖然為了方便的得到變數值,Web容器已經遮蔽了二者的一些差異,但是瞭解二者的差異在以後的程式設計也會很有幫助的。 Form中的g

關於HttpClient4.3.*的PostGet提交亂碼問題

無語了都,整了好久,網上各種答案,幾乎都是不行的,在apache的官網和一件網友的資料,現在OK了,分享如下: 這個原因是伺服器導致的,伺服器比如tomcat接收get方法預設使用的是ISO-8859-1編碼,而瀏覽器傳送時文字編碼是和頁面編碼保持一致的,如果頁面是使用u

關於java中 get提交方式亂碼問題

文字 問題 block eth 重新 clas 指定 原因 getpara 這個原因是服務器導致的,服務器比如tomcat接收get方法默認使用的是ISO-8859-1編碼,而瀏覽器發送時文字編碼是和頁面編碼保持一致的,如果頁面是使用utf-8 編碼 get方法文字自然是

Get提交方式中文亂碼

Get提交方式中文亂碼   今天在servlet使用中,在Get方法中獲取提交的中文引數,發現是亂碼,我用的是Tomcat7。   在Tomcat9中: get方式的引數是放在請求頭中,而Tomcat9對請求頭的解碼方式預設是utf8,所以get方式不會中文亂碼。 post方式的引數是放在請求體中,而Tom

form表getpost兩種提交方式的區別

name bsp inpu get div post input 普通 表單 一、form表單中get和post兩種提交方式的區別?   1.get提交表單中的內容在鏈接處是可見的。post不可見   2.post相比於get是安全的   3.post不收限制大小,get有

提交Form表POSTGET方式的傳值問題。

<form action="${pageContext.request.contextPath }/UserServlet?id=123" method="get"> userame:<input type="text" name="username"&

HTML提交方式postget區別(實驗)

des url action 通過 性別 清除數據 map pass pack HTML提交方式post和get區別(實驗) 一、post和get區別 get提交,提交的信息都顯示在地址欄中。 post提交,提交的信息不顯示地址欄中,顯示在消息體中。 二、客戶端代碼

簡述Get提交方式Post提交方式有哪些不同

表單的提交方式GET與POSTGET方法用來從Web伺服器獲取資訊(如文件,圖表,資料庫查詢結果等)。當在瀏覽器中直接輸入URL,或單擊一個hyperlink時候,就向Web伺服器發出了一個GET請求。GET請求可以在URL後面新增一些引數,所謂的查詢串(query stri

java使用PostGet方式提交Http請求通用

很多api提供了java的post,get方式呼叫返回結果的介面,以下記錄基礎通用的傳送請求並接收返回引數的方式:package com.taray.test; import java.io.BufferedReader; import java.io.IOException

Android中postget提交方式【三種】

向伺服器提交資料有兩種方式,post和get。兩者的區別主要有三點,安全性、長度限制、資料結構。其中get請求安全性相比較而言較差,資料長度受瀏覽器位址列限制,沒有方法體。兩種都是較為重要的資料提交方式。現簡單介紹一下三種post和get的提交方式。無論是哪種方法實現post和get,get 的訪問路徑都

Html 表提交時,使用POSTGET

Name 屬性如果要正確地被提交,每個輸入欄位必須設定一個 name 屬性。本例只會提交 "Last name" 輸入欄位:例項<form action="action_page.php"> First name:<br> <input type="text" value="Mi

Android Volley框架的幾種post提交請求方式探究POSTGET提交

首先簡單描述一下Google的Android開發團隊在2013年推出的一個網路通訊框架Volley.它的設計目標是進行資料量不大,但通訊頻繁的網路操作,而對於大資料量的網路操作,比如下載檔案等,Volley的表現就不盡如人意。 在app開發中,我們最常見的就是從app客戶端

提交postget方法區別

本文轉載於:猿2048網站表單提交post和get方法區別 表象不同,get把提交的資料url可以看到,post看不到

Post提交Get提交的區別

顯示 改變 color 多個 自身 height 數據 action 協議 表單提交中get和post的區別 1. get: 把表單內各個字段均顯示在URL中。 post:把表單內各個字段和內容放在html的header內一起傳遞給action所指的url,用戶看不

【轉載】form表的兩種提交方式,submitbutton的用法

按鈕 type ssid login false tex .get ons 轉載 1.當輸入用戶名和密碼為空的時候,需要判斷。這時候就用到了校驗用戶名和密碼,這個需要在jsp的前端頁面寫;有兩種方法,一種是用submit提交。一種是用button提交。方法一:在jsp的前端

Http (java)的postget方式

inf log href www param client get char comm 用java發送post和get請求的兩種方式 1.URL 2.httpclient 第一種方式: URL形式發送請求 第二種方式: commons-httpclient-3.1.jar;

HttpClient用PostGet帶引數提交幫助類

  轉載自https://blog.csdn.net/nevergiveuplzl/article/details/52304266 import java.util.ArrayList;  import java.util.List;  import java

Tomcat設定postget最大提交

<Connector port="8080" maxThreads="150" minSpareThreads="25" maxSpareThreads="75" <span style="color:#cc0000;">maxParamet