在java中使用request.getParameter()时为什么字符被破坏?

时间:2009-09-02 04:19:49

标签: java character-encoding request

我在JSP页面中有这样的链接,编码为big5 http://hello/world?name=婀ㄉ 当我在浏览器的URL栏中输入它时,它将被改为类似的东西 http://hello/world?name=%23%24%23 当我们想在jsp页面中获取此参数时,所有字符都已损坏。

我们设置了这个: request.setCharacterEncoding(“UTF-8”),因此所有请求都将转换为UTF8。

但是为什么在这种情况下,它不起作用? 提前谢谢!。

5 个答案:

答案 0 :(得分:14)

当您在浏览器的地址栏中输入URL时,浏览器可能会在URL编码之前转换字符编码。但是,这种行为定义不明确,请参阅我的问题,

Handling Character Encoding in URI on Tomcat

我们主要在较新的浏览器上获得UTF-8和Latin-1,但我们在旧版本中获得各种编码(包括Big5)。因此,最好避免用户直接输入的URL中的非ASCII字符。

如果URL嵌入在JSP中,您可以通过生成它来强制它为UTF-8,

String link = "http://hello/world?name=" + URLEncoder.encode(name, "UTF-8");

在Tomcat上,需要在Connector上指定编码,

<Connector port="8080" URIEncoding="UTF-8"/>

您还需要使用request.setCharacterEncoding("UTF-8")进行正文编码,但在servlet中设置它是不安全的,因为这仅在未处理参数但其他过滤器或阀门可能触发处理时才有效。所以你应该在过滤器中做到这一点。 Tomcat在源代码发布中附带了这样的过滤器。

答案 1 :(得分:8)

为避免摆弄server.xml使用:

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

protected String encodeString(String baseLink, String parameter)
        throws UnsupportedEncodingException {
    return String.format(baseLink + "%s",
            URLEncoder.encode(parameter, CHARSET_FOR_URL_ENCODING));
}
// Used in the servlet code to generate GET requests
response.sendRedirect(encodeString("userlist?name=", name));

要在Tomcat you need to do something like上实际获取这些参数:

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

显然(?)request.getParameter URLDecodes()字符串并将其解释为iso-8859-1 - 或URIEncodingserver.xml设置的任何内容。有关如何从Tomcat 7的URIEncoding获取server.xml字符集的示例,请参阅here

答案 2 :(得分:6)

您不能在网址中包含非ASCII字符 - 您始终需要对它们进行百分比编码。这样做时,浏览器难以渲染它们。如果您以UTF-8编码URL,然后对其进行百分比编码,则渲染效果最佳。对于您的特定网址,这会给http://hello/world?name=%E5%A9%80%E3%84%89(请检查您的浏览器为此特定链接提供的内容)。当您在JSP中获取参数时,您需要显式取消引用它,然后从UTF-8解码它,因为浏览器将按原样发送它。

答案 3 :(得分:0)

我遇到了JBoss 7.0的问题,我认为这个过滤器解决方案也适用于Tomcat:

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

    HttpServletRequest httpRequest = (HttpServletRequest) request;
    HttpServletResponse httpResponse = (HttpServletResponse) response;

    try {
        httpRequest.setCharacterEncoding(MyAppConfig.getAppSetting("System.Character.Encoding"));

        String appServer = MyAppConfig.getAppSetting("System.AppServer");
        if(appServer.equalsIgnoreCase("JBOSS7")) {
            Field requestField = httpRequest.getClass().getDeclaredField("request");
            requestField.setAccessible(true);
            Object requestValue = requestField.get(httpRequest);

            Field coyoteRequestField = requestValue.getClass().getDeclaredField("coyoteRequest");
            coyoteRequestField.setAccessible(true);
            Object coyoteRequestValue = coyoteRequestField.get(requestValue);

            Method getParameters = coyoteRequestValue.getClass().getMethod("getParameters");
            Object parameters = getParameters.invoke(coyoteRequestValue);

            Method setQueryStringEncoding = parameters.getClass().getMethod("setQueryStringEncoding", String.class);
            setQueryStringEncoding.invoke(parameters, MyAppConfig.getAppSetting("System.Character.Encoding"));

            Method setEncoding = parameters.getClass().getMethod("setEncoding", String.class);
            setEncoding.invoke(parameters, MyAppConfig.getAppSetting("System.Character.Encoding"));
        }

    } catch (NoSuchMethodException nsme) {
        System.err.println(nsme.getLocalizedMessage());
        nsme.printStackTrace();
        MyLogger.logException(nsme);
    } catch (InvocationTargetException ite) {
        System.err.println(ite.getLocalizedMessage());
        ite.printStackTrace();
        MyLogger.logException(ite);
    } catch (IllegalAccessException iae) {
        System.err.println(iae.getLocalizedMessage());
        iae.printStackTrace();
        MyLogger.logException(iae);

    } catch(Exception e) {
        TALogger.logException(e);
    }

    try {
        httpResponse.setCharacterEncoding(MyAppConfig.getAppSetting("System.Character.Encoding"));
    } catch(Exception e) {
        MyLogger.logException(e);
    }
}

答案 4 :(得分:0)

我在这个问题上做了很多搜索,所以这可能会帮助那些在tomcat上遇到同样问题的人。这取自http://wiki.apache.org/tomcat/FAQ/CharacterEncoding

(如何在任何地方使用UTF-8)。

  • 设置URIEncoding =&#34; UTF-8&#34;在server.xml中的<Connector>上。参考:HTTP连接器,AJP连接器。
  • 使用字符编码过滤器,默认编码设置为UTF-8
  • 更改所有JSP以在其contentType中包含charset名称。 例如,使用&lt;%@ page contentType =&#34; text / html;字符集= UTF-8&#34; %GT;对于通常的JSP页面,<jsp:directive.page contentType="text/html; charset=UTF-8" />用于XML语法中的页面(也称为JSP文档)。
  • 更改所有servlet以设置响应的内容类型,并在内容类型中包含charset name为UTF-8。 使用response.setContentType(&#34; text / html; charset = UTF-8&#34;)或response.setCharacterEncoding(&#34; UTF-8&#34;)。
  • 更改您使用的任何内容生成库(Velocity,Freemarker等)以使用UTF-8并在其生成的响应的内容类型中指定UTF-8。
  • 在字符编码过滤器或jsp页面有机会将编码设置为UTF-8之前,禁用任何可能读取请求参数的阀门或过滤器。