在问题以前咱们先来了解一下什么是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就像解码。