大家思考一下最后面的那个输出可以得到正确的结果吗?为什么?
下面我们来讨论 ,通过http协议下的url传输后,编码转化问题。
首先说明的是本人本地默认编码是gbk。
我们只用Servlet,不使用任何框架比如spring(因为使用框架时,框架也有一套自己自己的机制)如下代码
public class HttpEncode extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String str = req.getQueryString();
System.out.println(req.getCharacterEncoding());
String encode = null;
try {
encode = req.getParameter("encode");
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(str);
System.out.println(encode);
}
}
我们分别用jetty(版本6.1)和resin(版本3.1.8)下容器,测试如下请求 127.0.0.1/test encode=%B9%FE 其中%B9%FE为GBk的编码的汉字”哈“
jetty容器下输出为 www.2cto.com
null
encode=%B9%FE
resin下为:
null
encode=%B9%FE
null
换做127.0.0.1/test encode=%E5%93%88 ,utf8编码的”哈“
jetty和resin下都输出如下
null
encode=%E5%93%88
哈
为什么会是这样?
我们拿jetty分析,在jetty的源码中,
public String getParameter(String name)
{
if (!_paramsExtracted)
extractParameters();
return (String) _parameters.getValue(name, 0);
}
对应的
extractParameters(); 部分代码
if (_queryEncoding==null)
_uri.decodeQueryTo(_baseParameters);
然后
public void decodeQueryTo(MultiMap parameters)
{
if (_query==_fragment)
return;
_utf8b.reset();
UrlEncoded.decodeUtf8To(_raw,_query+1,_fragment-_query-1,parameters,_utf8b);
}
也就是如果_queryEncoding为null时,默认是用utf8进行解码的。而resin也不例外。
jetty中_queryEncoding的值可以通过org.mortbay.jetty.Request.queryEncoding 这个属性给赋值而resin采用的是req.getCharacterEncoding()中的值为标准。
要想在jetty下 127.0.0.1/test encode=%B9%FE,获取到正确的字符,代码如下
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String str = req.getQueryString();
System.out.println(req.getCharacterEncoding());
req.setAttribute("org.mortbay.jetty.Request.queryEncoding", "gbk");
String encode = null;
try {
encode = req.getParameter("encode");
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(str);
System.out.println(encode);
}
resin下只需要
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String str = req.getQueryString();
req.setCharacterEncoding("gbk");
System.out.println(req.getCharacterEncoding());
String encode = null;
try {
encode = req.getParameter("encode");
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(str);
System.out.println(encode);
}
通过上面想说明的是,不同的容器,默认编码的策略是不一致的。只要我们了解编码的基础知识。通过一些封装就很容易掌控这个局面。
摘自 成就梦想