在問題以前咱們先來了解一下什麼是URL,URI以及QueryString,以下圖1所示:html
圖1:URL-URI-QueryStringjava
URL:是全球資源定位符的英文縮寫,如上 其中localhost:是指Domain(IP或者主機名),8080:是端口 Web服務通常是80,8080是本身測試是候用的,避免和和瀏覽器的端口衝突。
ROOT:是ContentPath,就是虛擬路徑,若是是tomcat服務器對象的是servlet.xml配置文件中的<Context path=」/ROOT」 /> 若是沒有配置這一個tomcat默認的是path就是ROOT。
Servlet:就是ServletPath的信息,就是和web.xml中的<url-pattern>相對應的,用來查找Servlet。
GetSpecialInfos:就是要請求的文件了。
category=土特產:就是QueryString,至關於用get提交的參數。
URI(Universal Resource Identifier, 簡稱"URI"):是Web上可用的每種資源。經過URI進行定位。通常是服務器本身使用。
知道了URL,URI和QueryString,咱們就能夠來試一試他們的編碼問題了,看下面一個Java Servlet程序:web
import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.wl.util.SpecialInfoToJson; import org.wl.util.StringUtils; /** * Servlet implementation class GetSpecialInfo */ public class GetSpecialInfos extends HttpServlet { private static final long serialVersionUID = 1L; private static final Logger log = LogManager.getLogger(); /** * @see HttpServlet#HttpServlet() */ public GetSpecialInfos() { super(); // TODO Auto-generated constructor stub } /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); log.info(request.getCharacterEncoding()); request.setCharacterEncoding("utf-8"); log.info(request.getCharacterEncoding()); log.info(request.getQueryString()); System.out.println(); String category = request.getParameter("category"); if(StringUtils.isNullOrEmpty(category)) { response.getWriter().append("category is null"); return; } log.info(category); // category = new String(category.getBytes("iso-8859-1"),"utf-8"); // category = new String(category.getBytes("iso-8859-1"),"gbk"); // log.info(category); response.getWriter().append(SpecialInfoToJson.getCategoryInfo(category)); } }
我用的是tomcat服務器,若是要進行簡單測試,能夠把log語句換爲System.out.println();輸出直接到控制檯,避免配置log4j2。能夠把最後的response.getWriter().append(SpecialInfoToJson.getCategoryInfo(category));去掉。apache
直接經過瀏覽器訪問:http://localhost:8080/market/GetSpecialInfos?category=土特產數組
把market換爲您的工程名字。瀏覽器
經過IE瀏覽器訪問控制檯的輸出:tomcat
null服務器
22:02:58.492 INFO org.wl.app.GetSpecialInfos 44 doPost - utf-8app
22:02:58.492 INFO org.wl.app.GetSpecialInfos 45 doPost - category=ÍÁÌزúpost
22:02:58.492 INFO org.wl.app.GetSpecialInfos 52 doPost - ÍÁÌزú
經過Firefox或者Google瀏覽器訪問控制檯的輸出(忽略了部分輸出):
null
utf-8
category=%E5%9C%9F%E7%89%B9%E4%BA%A7
åç¹äº§
如今還暫時猜想不出是什麼意思,沒有關係咱們先把把被註釋掉的代碼
category = new String(category.getBytes("iso-8859-1"),"utf-8");去掉註釋,在從新運行。
發現用Firefox或者Google瀏覽器訪問的控制檯的輸出爲:
null
utf-8
category=%E5%9C%9F%E7%89%B9%E4%BA%A7
åç¹äº§
土特產
用IE訪問控制檯的輸出爲:
null
22:43:56.614 INFO org.wl.app.GetSpecialInfos 44 doPost - utf-8
22:43:56.614 INFO org.wl.app.GetSpecialInfos 45 doPost - category=ÍÁÌزú
22:43:56.614 INFO org.wl.app.GetSpecialInfos 53 doPost - ÍÁÌزú
22:43:56.614 INFO org.wl.app.GetSpecialInfos 56 doPost - ���ز�
說明Firefox和Google對於QueryString的編碼格式是utf-8。而IE對於QueryString的編碼確定不是utf-8。
咱們在把category = new String(category.getBytes("iso-8859-1"),"utf-8");註釋掉。
把 category = new String(category.getBytes("iso-8859-1"),"gbk");的註釋去掉。從新運行,而後經過IE
Firefox、Google瀏覽器來訪問。
控制檯的輸出爲IE正常了,Firefox和Google亂碼了。說明IE用的是gbk或者以其兼容的編碼方式(gb2312等)
對QueryString進行編碼的。
下面咱們從新來看一看這一句:category = new String(category.getBytes("iso-8859-1"),"utf-8");
咱們爲何要category.getBytes("iso-8859-1"),用iso-8859-1這一編碼來獲得字節數組。是由於對於QueryString來講,若是沒有中請求頭(header)中設置contentType,在tomcat的servlet.xml配置文件中也沒有設置<Connector URIEncoding=」utf-8」 uesBodyEncodingForURI=」true」 />這樣的配置。那麼就會使用iso-8859-1對QueryString進行編碼。咱們的request.setCharacterEncoding("utf-8");這一句一直輸出的是null,說明瀏覽器並無設置contentType。咱們也沒有配置服務器,因此就使用的是iso-8859-1對QueryString進行的編碼。
同時咱們發現request.setCharacterEncoding("utf-8");這一句好像沒有用,對於get方式提交的(包括,url參數,和表單經過get方法提交)的確沒有做用,可是對於post提交的是用用的。若是有興趣能夠試一試。
注意:必須同時設定了contentType和uesBodyEncodingForURI=」true」纔會使用contentType的方式對QueryString就像解碼。