如何正确解码传递给 servlet 的 unicode 参数

2022-09-01 05:40:48

假设我有:

<a href="http://www.yahoo.com/" target="_yahoo" 
    title="Yahoo!&#8482;" onclick="return gateway(this);">Yahoo!</a>
<script type="text/javascript">
function gateway(lnk) {
    window.open(SERVLET +
        '?external_link=' + encodeURIComponent(lnk.href) +
        '&external_target=' + encodeURIComponent(lnk.target) +
        '&external_title=' + encodeURIComponent(lnk.title));
    return false;
}
</script>

我已确认被编码为并传递给 .如果在我做:external_titleYahoo!%E2%84%A2SERVLETSERVLET

Writer writer = response.getWriter();
writer.write(request.getParameter("external_title"));

我在浏览器中得到了Yahoo!“¢。如果我手动将浏览器字符编码切换到UTF-8,它将更改为Yahoo!TM(这就是我想要的)。

所以我认为我发送到浏览器的编码是错误的(它是)。我改成了:Content-type: text/html; charset=ISO-8859-1SERVLET

response.setContentType("text/html; charset=utf-8");
Writer writer = response.getWriter();
writer.write(request.getParameter("external_title"));

现在浏览器字符编码是UTF-8,但它输出Yahoo!â¢,我根本无法让浏览器呈现正确的字符。

我的问题是:是否有某种和/或和/或其他东西的组合会导致Yahoo!TM出现在输出中?Content-typenew String(request.getParameter("external_title").getBytes(), "UTF-8");SERVLET


答案 1

你快到了。EncodeURIComponent 正确地编码为 UTF-8,这是您今天应该始终在 URL 中使用的。

问题在于,提交的查询字符串在进入服务器端脚本的过程中被肢解了,因为 getParameter() 使用 ISO-8559-1 而不是 UTF-8。这源于古代,在网络确定使用UTF-8作为URI / IRI之前,但是相当可悲的是Servlet规范尚未更新以匹配现实,或者至少为其提供可靠的,受支持的选项。

(Servlet 2.3 中有 request.setCharacterEncoding,但它不会影响查询字符串解析,如果以前读取过单个参数,可能是由其他框架元素读取的,则它根本不起作用。

因此,您需要使用特定于容器的方法来获得正确的UTF-8,通常涉及服务器.xml中的内容。这对于分发应该在任何地方工作的Web应用程序来说完全很糟糕。对于Tomcat,请参阅 https://cwiki.apache.org/confluence/display/TOMCAT/Character+Encoding 以及Tomcat的“URIEncoding”,Encoding Filter和request.setCharacterEncoding之间的区别


答案 2

我遇到了同样的问题,并使用URLDecoder()解码并提取了我的参数后解决了它。Request.getQueryString()

String[] Parameters = URLDecoder.decode(Request.getQueryString(), 'UTF-8')
                       .splitat('&');

推荐