0

这一直让我发疯。

所以我有一个(非常简单的 vanilla servlet 3)网络应用程序。当我在eclipse中运行它时一切都很好。除其他外,我可以使用 Unicode(希腊)用户名注册一个帐户,然后以站点管理员身​​份登录并访问用户的个人资料。当我将战争导出到 $CATALINA_HOME\webapps,启动$CATALINA_HOME\bin\startup.bat,在浏览器中打开站点,以管理员身份登录并尝试访问用户配置文件时,用户名等显示为空白。in和 in 中
的文件仅在 (in ) 行中有所不同:...\apache-tomcat-7.0.32\conf...\eclipse_workspaces\javaEE\Servers\Tomcat v7.0 Server at localhost-configserver.xml

<Context docBase="ted2012" path="/ted2012" reloadable="true" 
source="org.eclipse.jst.jee.server:ted2012"/>

这是一个日食的事情。

配置文件 servlet 中的 doGet 方法(精简):

protected void doGet(HttpServletRequest request,
        HttpServletResponse response) throws ServletException, IOException {

    final String username = Helpers.decodeRequest(request
            .getParameter("user"));
    if (username != null) {
        User user = null;
        try {
            System.out
                    .println("ProfileController.doGet() user name DECODED : "
                            + username);
            user = userService.getUserWithUsername(username); // THIS FAILS
            System.out.println("ProfileController.doGet() user : " + user);
            request.setAttribute("userToShow", user);
        } catch (ServiceExDBFailure e) {
            log.debug("ProfileController::doGet", e);
            request.setAttribute("ErrorString", e.getMessage());
        }
        sc.getRequestDispatcher(OTHERPROFILE_JSP)
                .forward(request, response);
        return;
    } else {
        //does not apply
    }
}

解码方法是:

public static String decodeRequest(String parameter)
        throws UnsupportedEncodingException {
    if (parameter == null)
        return null;
    System.out.println("decode - request.getBytes(\"iso-8859-1\"):"
            + new String(parameter.getBytes("iso-8859-1")));
    System.out.println("decode - request.getBytes(\"iso-8859-1\") BYTES:"
            + parameter.getBytes("iso-8859-1"));
    for (byte iterable_element : parameter.getBytes("iso-8859-1")) {
        System.out.println(iterable_element);
    }
    System.out.println("decode - request.getBytes(\"UTF-8\"):"
            + new String(parameter.getBytes(CHARSET_FOR_URL_ENCODING))); // UTF-8
    return URLDecoder.decode(new String(parameter.getBytes("iso-8859-1")),
            CHARSET_FOR_URL_ENCODING);
}

虽然 db 调用是:

            statement = conn.prepareStatement(query);
            statement.setString(1, username);
            System.out.println("ελληναρα");
            System.out.println(statement);
            set = statement.executeQuery();
            if (set.next()) {
                User user = new User();
                // user.setId(set.getInt("ID"));
                user.setUsername(set.getString("username"));
                user.setName(set.getString("name"));
                user.setSurname(set.getString("surname"));
                user.setPassword(set.getString("password"));
                user.setEmail(set.getString("email"));
                user.setRole(RolesENUM.values()[set.getInt("role")]);
                return user; // if the set is empty null is returned
            }

Tomcat 打印:

decode - request.getBytes("iso-8859-1"):╧à╧â╧ä╬╡╧?╬╣╬▒
decode - request.getBytes("iso-8859-1") BYTES:[B@529b9ed
-49
-123
-49
-125
-49
-124
-50
-75
-49
-127
-50
-71
-50
-79
decode - request.getBytes("UTF-8"):├?┬à├?┬â├?┬ä├Ä┬╡├?┬?├Ä┬╣├Ä┬▒
ProfileController.doGet() user name DECODED : ╧à╧â╧ä╬╡╧?╬╣╬▒
com.mysql.jdbc.JDBC4PreparedStatement@766d7940: SELECT * FROM users WHERE username='╧à╧â╧ä╬╡╧?╬╣╬▒'
????????
ProfileController.doGet() user : null

而 Eclipse 打印:

decode - request.getBytes("iso-8859-1"):υστερια
decode - request.getBytes("iso-8859-1") BYTES:[B@4b6a6bdf
-49
-123
-49
-125
-49
-124
-50
-75
-49
-127
-50
-71
-50
-79
decode - request.getBytes("UTF-8"):ÏÏÏεÏια
ProfileController.doGet() user name DECODED : υστερια
com.mysql.jdbc.JDBC4PreparedStatement@37d02427: SELECT * FROM users WHERE username='υστερια'
ελληναρα
ProfileController.doGet() user : com.ted.domain.User@63144ceb

我相信由于某种原因,到达数据库的查询是疯狂的 - 请注意,在 eclipse 中的哪个位置打印 ελληναρα 在 tomcat 打印 ???????? 而 unicode 用户名 (υστερια) 打印为 ╧à╧â╧ä╬╡╧?╬╣╬▒ 而不是 ?????????。

所以问题是 - Eclipse 部署和 tomcat 部署之间有什么变化?为什么数据库返回 null ?我真的真的试图徒劳地调试这个

帮助

编辑:更换线路 statement.setString(1, username);没有statement.setString(1, "υστερια");失败。因此,当这条线运行时,字节被弄乱了 - 请注意,尽管字节是一一相同的

EDIT2:本地主机上的 Tomcat v7.0 服务器 Eclipse 启动 VM args(为便于阅读而拆分):

-Dcatalina.base="C:\Dropbox\eclipse_workspaces\javaEE\.metadata\.plugins
\org.eclipse.wst.server.core\tmp1" 
-Dcatalina.home="C:\_\apache-tomcat-7.0.32" 
-Dwtp.deploy="C:\Dropbox\eclipse_workspaces\javaEE\.metadata\.plugins\org.eclipse.wst.server.core\tmp1\wtpwebapps" 
-Djava.endorsed.dirs="C:\_\apache-tomcat-7.0.32\endorsed"

注意应用程序的启动是动态创建的

编辑 2013.03.30:这现在在github 上-在这里查看我更一般的问题

4

1 回答 1

0

这终于在这里得到了回答。

答案的要点是,我 Eclipse 将 UTF-8 和 Tomcat 作为默认编码,windows-1252所以当我调用 new String() 而不指定用于将 byte[] 转换为 chars 的编码时。正在做

new String(parameter.getBytes("iso-8859-1"), "UTF-8");

解决了这个问题——如果tomcat在

request.getParameter("user") // url decoding is performed by tomcat - using the
// URIEncoding from server.xml or by default ISO-8859

默认情况下不会使用 ISO-8859 作为另一种编码(比如 ASCII)可能(在 Java 7 nio 之前行为未定义且不可控制)替换不可解码的字符,?因此parameter字符串将被损坏(请参阅ISO-8859-1 编码和二进制数据保存) .

因此,对 tomcat 表示敬意,因为它默认使用 ISO-8859 执行转换,request.getParameter()而对 Java ee 规范的人来说,他们甚至没有在文档中提到 getParameter 将执行 URL 解码,更不用说让我们指定编码,覆盖 server.xml .

于 2014-03-26T13:26:42.917 回答