当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《如何正确解码传递给servlet的unicode参数》经验,为你挑选了3个好方法。

假设我有:

Yahoo!

我已经确认external_title将编码Yahoo!%E2%84%A2并传递给SERVLET.如果SERVLET我在做:

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

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

所以我认为我发送到浏览器的编码是错误的(确实如此Content-type: text/html; charset=ISO-8859-1).我改为SERVLET:

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

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

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



1> bobince..:

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

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

(Servlet 2.3中有request.setCharacterEncoding,但它不影响查询字符串解析,如果之前已经读过一个参数,可能是其他一些框架元素,它根本不起作用.)

因此,您需要使用特定于容器的方法来获取正确的UTF-8,通常涉及server.xml中的内容.这对于分发应该在任何地方工作的Web应用程序来说非常糟糕 对于Tomcat,请参阅http://wiki.apache.org/tomcat/FAQ/CharacterEncoding以及Tomcat 的"URIEncoding",编码过滤器和request.setCharacterEncoding之间的区别.


感谢您的解释.至少我知道我并不疯狂.我在寻找解决方案时尝试了request.setCharacterEncoding(),正如你所说,它似乎没有做任何事来帮助解决我的问题.
`getParameter`旨在为您解码输入 - 浏览器在提交时使用百分比编码表单值,因此您必须解码它们以获取用户的输入.必须有一些编码用于将输入中的字节转换为字符,并且浏览器并不总是使用相同的编码.不幸的是Servlet会为你选择一个,它选择不好,它不会让你覆盖那个选择 - 不像`URLDecoder.decode`没有`enc`参数.
如果你想要原始URL中的百分比编码内容,使用`getQueryString()`并自己解析它而不是让Servlet这样做.

2> 小智..:

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

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


自己处理查询字符串是处理`getParameter`中的问题的一个好主意,但是这不太正确:它应该在将组件分开之后进行URL解码*,而不是之前.上面的代码在参数(编码为`%26`)或参数名称中的`=`(`%3D`)中使用`&`字符时会失败.

3> Mr_and_Mrs_D..:

有办法在java中做(没有摆弄server.xml)

不工作 :

protected static final String CHARSET_FOR_URL_ENCODING = "UTF-8";

String uname = request.getParameter("name");
System.out.println(uname);
// ÏηγÏÏÏÏη
uname = request.getQueryString();
System.out.println(uname);
// name=%CF%84%CE%B7%CE%B3%CF%81%CF%84%CF%83%CF%82%CE%B7
uname = URLDecoder.decode(request.getParameter("name"),
        CHARSET_FOR_URL_ENCODING);
System.out.println(uname);
// ÏηγÏÏÏÏη // !!!!!!!!!!!!!!!!!!!!!!!!!!!
uname = URLDecoder.decode(
        "name=%CF%84%CE%B7%CE%B3%CF%81%CF%84%CF%83%CF%82%CE%B7",
        CHARSET_FOR_URL_ENCODING);
System.out.println("query string decoded : " + uname);
// query string decoded : name=????????
uname = URLDecoder.decode(new String(request.getParameter("name")
        .getBytes()), CHARSET_FOR_URL_ENCODING);
System.out.println(uname);
// ÏηγÏÏÏÏη // !!!!!!!!!!!!!!!!!!!!!!!!!!!

作品:

final String name = URLDecoder
        .decode(new String(request.getParameter("name").getBytes(
                "iso-8859-1")), CHARSET_FOR_URL_ENCODING);
System.out.println(name);
// ????????

工作但如果默认编码会中断!= utf-8 - 尝试这样做(省略对decode()的调用,不需要):

final String name = new String(request.getParameter("name").getBytes("iso-8859-1"),
        CHARSET_FOR_URL_ENCODING);

正如我上面所说,如果server.xml被搞砸了如下:

 

(注意URIEncoding="UTF-8")上面的代码会中断(导致getBytes("iso-8859-1")应该读取getBytes("UTF-8")).因此,对于防弹解决方案,您必须获取URIEncoding属性的值.遗憾的是,这似乎是容器特定的 - 甚至更糟糕的容器版本.对于tomcat 7,您需要以下内容:

import javax.management.AttributeNotFoundException;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanException;
import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.ReflectionException;

import org.apache.catalina.Server;
import org.apache.catalina.Service;
import org.apache.catalina.connector.Connector;

public class Controller extends HttpServlet {

    // ...
    static String CHARSET_FOR_URI_ENCODING; // the `URIEncoding` attribute
    static {
        MBeanServer mBeanServer = MBeanServerFactory.findMBeanServer(null).get(
            0);
        ObjectName name = null;
        try {
            name = new ObjectName("Catalina", "type", "Server");
        } catch (MalformedObjectNameException e1) {
            e1.printStackTrace();
        }
        Server server = null;
        try {
            server = (Server) mBeanServer.getAttribute(name, "managedResource");
        } catch (AttributeNotFoundException | InstanceNotFoundException
                | MBeanException | ReflectionException e) {
            e.printStackTrace();
        }
        Service[] services = server.findServices();
        for (Service service : services) {
            for (Connector connector : service.findConnectors()) {
                System.out.println(connector);
                String uriEncoding = connector.getURIEncoding();
                System.out.println("URIEncoding : " + uriEncoding);
                boolean use = connector.getUseBodyEncodingForURI();
                // TODO : if(use && connector.get uri enc...)
                CHARSET_FOR_URI_ENCODING = uriEncoding;
                // ProtocolHandler protocolHandler = connector
                // .getProtocolHandler();
                // if (protocolHandler instanceof Http11Protocol
                // || protocolHandler instanceof Http11AprProtocol
                // || protocolHandler instanceof Http11NioProtocol) {
                // int serverPort = connector.getPort();
                // System.out.println("HTTP Port: " + connector.getPort());
                // }
            }
        }
    }
}

而且你还需要为多个连接器调整它(检查注释掉的部分).然后你会使用类似的东西:

new String(parameter.getBytes(CHARSET_FOR_URI_ENCODING), CHARSET_FOR_URL_ENCODING);

如果使用CHARSET_FOR_URI_ENCODING进行解码,则可能会失败(IIUC)parameter = request.getParameter("name");,因此使用getBytes()得到的字节不是原始字节(这就是为什么默认使用"iso-8859-1" - 它将保留字节).您可以通过手动解析以下行中的查询字符串来解决所有问题:

URLDecoder.decode(request.getQueryString().split("=")[1],
        CHARSET_FOR_URL_ENCODING);

我仍然在寻找在那里提到,在文档中的位置request.getParameter("name")并调用URLDecoder.decode() 返回而不是%CF%84%CE%B7%CE%B3%CF%81%CF%84%CF%83%CF%82%CE%B7字符串?源中的链接将非常感激.
另外,我怎样才能将字符串作为参数的值传递%CE =>看评论: parameter=%25CE

推荐阅读
oDavid_仔o_880
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有