这让我疯了。
所以我有一个(非常简单的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"
答案 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。