1

我遇到了一个关于错误 URI 编码的奇怪问题,不胜感激!

该项目使用 JSP、Servlet、Jquery、Tomcat 6。

JSP 中的字符集设置为 UTF-8,所有 Tomcat 连接器都使用 URIEncoding=UTF-8,并且我还使用此处描述的字符编码过滤器。此外,我在元标记中设置了 contentType,我的浏览器正确检测到它。

在使用 Jquery 的 Ajax 调用中,我在我想用作 URL 参数的术语上使用 encodeURIComponent(),然后使用 $.param() 序列化整个参数集。在被调用的 servlet 中,这些参数使用 Java.net.URLDecoder.decode(term, "UTF-8") 正确解码。

在某些地方,我从 JSP 中的参数映射生成 href 元素的 URL。每个参数值在 JSP 端使用 Java.net.URLEncoder.encode(value, "UTF-8") 进行编码,但随后以与之前相同的方式对其进行解码会导致特殊字符损坏。相反,我必须在 JSP 中将其编码为“ISO-8859-2”,然后在 servlet 中将其正确解码为“UTF-8”。

一个澄清的例子:术语“überfall”是通过Javascript(%C3%BCberfall)进行URIEncoded并发送到servlet进行解码和处理,这是有效的。将其传递回 JSP 后,我会将其编码为 UTF-8 并构建 URL,例如:

<a href="/myWebapp/servletPath?term=%C3%BCberfall">Click here</a>

但是,单击此链接会将参数作为“%C3%83%C2%BCberfall”发送到解码为“überfall”的 servlet。当不进行编码时也会发生同样的情况。

当使用“ISO-8859-2”进行编码时,我得到:

<a href="/myWebapp/servletPath?term=%FCberfall">Click here</a>

单击此链接时,我可以在 Wireshark 中观察到 %C3%BCberfall 作为参数发送,该参数再次解码为“überfall”!

谁能告诉我我错过了什么?

编辑:在 Firebug 中观察网络选项卡时,我意识到通过使用

$.param({term : encodeURIComponent(term)}); 

该术语被 UTF-8 编码两次,导致“%25C3%25BCberfall”,即百分比符号也是百分比编码的。类似地,如果我对参数映射中的每个值调用 encode(term, "UTF-8") 两次,它对我有用。

编码一次而不解码字符串会再次导致“überfall”。

4

2 回答 2

1

Java 在内部使用什么编码?你开始你的应用程序

-Dfile.encoding=utf-8

请澄清“JSP 中的参数映射”的定义位置。它是来自一些持久性数据存储还是代码中以文字形式给出的字符串?

关于正在发生的事情的一些想法,这可能会有所帮助:

ü是当一个UTF-8编码ü被读取时出现的结果ISO-8859-1,当每个字节都被自己解码时。是 a 的两个字节%C3%BC的 URI 编码表示。我认为这是正在发生的事情:UTF-8UTF-8 ü

%C3%BC错误解码为 →ü被编码为 →%C3%83%C2%BC然后再次被解码为 →ü所以你最终得到überfall.

所以我猜,您使用错误的编码来解码 URI 编码的字符串。这可能与 Java/JVM 使用的内部编码有关:

默认情况下,如果 JRE 7 安装程序识别出主机操作系统仅支持欧洲语言,它会安装欧洲语言版本。

于 2012-07-16T14:10:28.257 回答
1

我想我现在肯定解决了这个问题。

按照 Jontro 的评论,我对所有 URL 参数值进行了一次编码,并删除了手动 servlet 端解码。

在 servlet中给我的 Firebug 的 Network 选项卡中发送ü应该看起来像。Java 使用 -Dfile.encoding 参数绝对设置为“UTF-8”内部编码。我将问题追溯到这样的 request.getParameter() 方法。request.getQueryString 没问题,但是在提取实际参数时它失败了:%C3%BCü

request.getCharacterEncoding()) => UTF-8
request.getContentType() => null
request.getQueryString() => from=0&resultCount=10&sortAsc=true&searchType=quick&term=%C3%BC
request.getParameter("term") => ü
Charset.defaultCharset() => UTF-8
OutputStreamWriter.getEncoding() => UTF8
new String(request.getParameter("term").getBytes(), UTF-8) => ü
System.getProperty("file.encoding ") => UTF-8

通过查看实现 request.getParameter() 的 Tomcat 和 Coyote 的来源,我发现了问题:来自连接器的 URIEncoding 始终为空,在这种情况下,它默认为 org.apache.coyote.Constants.DEFAULT_CHARACTER_ENCODING,即“ISO- 8859-1”就像 Wolfram 所说的那样。

长话短说:我的错是在 Tomcat 的 conf 目录中编辑 server.xml,只有在服务器视图中创建新服务器时才会将其加载到 Eclipse 中!之后,必须编辑 Servers 项目中的单独 server.xml。这样做后,连接器设置正确加载,一切正常。

感谢您的评论!希望这可以帮助某人...

于 2012-07-20T08:55:08.727 回答