Webapp在从eclipse运行时表现如预期,而在战争失败时导出

时间:2013-02-16 20:52:51

标签: eclipse unicode tomcat7 war servlet-3.0

这让我疯了。

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

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

这是一个日食。

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

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"

NB the launch for the app is created dynamically

编辑2013.03.30 :现在已经github了 - 请参阅我的更一般性问题here

1 个答案:

答案 0 :(得分:0)

终于回答了here

答案的要点是,当我调用new String()而不指定那些用于转换byte []的编码时,我eclipse有默认编码UTF-8和Tomcat windows-1252所以字符。做

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之前无法控制)用?替换不可解码的字符所以{{ 1}}字符串将被破坏(参见ISO-8859-1 encoding and binary data preservation)。

因此默认情况下使用ISO-8859在其parameter中执行转换以及在Java ee规范中甚至没有提及getParameter将执行URL解码的Java ee规范人员,更不用说让我们了指定编码,覆盖server.xml。