我正在寻找有关应用引擎如何处理字符编码的一些解释。我正在开发一个客户端 - 服务器应用程序,其中服务器位于应用程序引擎上。
这是一个从头开始构建的新应用程序,因此我们在任何地方都使用UTF-8。客户端通过POST,x-www-form-urlencoded向服务器发送一些字符串。我收到它们并回复它们。当客户收回它时,它是ISO-8859-1! POST到blobstore时我也看到这种行为,参数发送为UTF-8,multipart / form-data编码。
为了记录,我在Wireshark中看到了这一点。所以我100%确定我发送UTF-8并收到ISO-8859-1。另外,我没有看到mojibake:ISO-8859-1编码的字符串非常好。这也不是误解内容类型的问题。这不是客户。一路走来正确地认识到我正在发送UTF-8参数,但出于某种原因将它们转换为ISO-8859-1。
我认为ISO-8859-1是GAE servlet的默认字符编码。我的问题是,有没有办法告诉GAE不要转换为ISO-8859-1,而是在任何地方使用UTF-8?
假设servlet做了这样的事情:
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
resp.setContentType("application/json");
String name = req.getParameter("name");
String json = "{\"name\":\"" + name + "\"}";
resp.getOutputStream().print(json);
}
我尝试将响应的字符编码设置为“UTF-8”,但这并没有改变任何内容。
提前致谢,
答案 0 :(得分:17)
我看到你应该做的两件事。
1)在appengine-web.xml中将系统属性(如果使用的话)设置为utf8
<system-properties>
<property name="java.util.logging.config.file" value="WEB-INF/logging.properties" />
<property name="file.encoding" value="UTF-8" />
<property name="DEFAULT_ENCODING" value="UTF-8" />
</system-properties>
好的以上就是我所拥有的,但文档建议如下:
<env-variables>
<env-var name="DEFAULT_ENCODING" value="UTF-8" />
</env-variables>
https://developers.google.com/appengine/docs/java/config/appconfig
2)在设置内容类型时指定编码,否则它将恢复为默认值
内容类型可以包括所使用的字符编码类型 例如,text / html;字符集= ISO-8859-4。
我试试
resp.setContentType("application/json; charset=UTF-8");
您还可以尝试使用编写器直接为其设置内容类型。
http://docs.oracle.com/javaee/1.3/api/javax/servlet/ServletResponse.html#getWriter%28%29
http://docs.oracle.com/javaee/1.3/api/javax/servlet/ServletResponse.html#setContentType(java.lang.String)
对于它的价值,我需要utf8用于日语内容,我没有遇到任何麻烦。我还没有使用过滤器或setContentType。我正在使用上面的gwt和#1,它可以工作。
答案 1 :(得分:7)
找到一种解决方法。我就这样做了:
使用“application / json; charset = UTF-8”作为内容类型。或者,将响应字符集设置为“UTF-8”(两者都可以正常工作,无需同时执行这两种操作)。
Base64编码的输入字符串不是ASCII安全的,并且是UTF-8。否则,当他们到达servlet时,他们会转换为ISO-8859-1。
使用resp.getWriter()而不是resp.getOutputStream()来打印JSON响应。
在满足所有条件后,我终于能够将UTF-8输出回客户端。
答案 2 :(得分:1)
这不是GAE特有的,但如果你发现它很有用:我自己创建过滤器:
在web.xml中
<filter>
<filter-name>charsetencoding</filter-name>
<filter-class>mypackage.CharsetEncodingFilter</filter-class>
</filter>
...
<filter-mapping>
<filter-name>charsetencoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
(将过滤器映射片段放在过滤器映射的开头,并检查你的url-pattern。
并且
public class CharsetEncodingFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
req.setCharacterEncoding("UTF-8");
chain.doFilter(req, res);
res.setCharacterEncoding("UTF-8");
}
public void destroy() { }
public void init(FilterConfig filterConfig) throws ServletException { }
}
答案 3 :(得分:0)
这些答案中没有任何一个对我有用,所以我将这个类编写为将UTF-Strings编码为ASCII-Strings (用ASCII表替换所有不在ASCII表中的字符,使用AsciiEncoder.encode(yourString)
然后可以使用AsciiEncoder.decode(yourAsciiEncodedString)
将解码回UTF 。
package <your_package>;
import java.util.ArrayList;
/**
* Created by Micha F. aka Peracutor.
* 04.06.2017
*/
public class AsciiEncoder {
public static final char MARK = '%'; //use whatever ASCII-char you like (should be occurring not often in regular text)
public static String encode(String s) {
StringBuilder result = new StringBuilder(s.length() + 4 * 10); //buffer for 10 special characters (4 additional chars for every special char that gets replaced)
for (char c : s.toCharArray()) {
if ((int) c > 127 || c == MARK) {
result.append(MARK).append((int) c).append(MARK);
} else {
result.append(c);
}
}
return result.toString();
}
public static String decode(String s) {
int lastMark = -1;
ArrayList<Character> chars = new ArrayList<>();
try {
//noinspection InfiniteLoopStatement
while (true) {
String charString = s.substring(lastMark = s.indexOf(MARK, lastMark + 1) + 1, lastMark = s.indexOf(MARK, lastMark));
char c = (char) Integer.parseInt(charString);
chars.add(c);
}
} catch (IndexOutOfBoundsException | NumberFormatException ignored) {}
for (char c : chars) {
s = s.replace("" + MARK + ((int) c) + MARK, String.valueOf(c));
}
return s;
}
}
希望这有助于某人。