有没有办法将UTF-8与app引擎一起使用?

我正在寻找关于app引擎如何处理字符编码的一些解释。 我正在研究服务器在应用程序引擎上的客户端 – 服务器应用程序。

这是一个从头开始构建的新应用程序,因此我们在任何地方都使用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”,但这并没有改变任何东西。

提前致谢,

我看到你应该做的两件事。

1) 在appengine-web.xml中将系统属性(如果使用它)设置为utf8

      

好的,上面是我的,但文档建议如下:

    

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用于日语内容,我没有遇到麻烦。 我还没有使用filter或setContentType。 我正在使用上面的gwt和#1并且它有效。

找到了解决它的方法。 这就是我做的方式:

  • 使用“application / json; charset = UTF-8”作为内容类型。 或者,将响应字符集设置为“UTF-8”(两者都可以正常工作,不需要同时执行这两个操作)。

  • Base64编码的输入字符串不是ASCII安全的,并且是UTF-8。 否则,当他们到达servlet时,他们会转换为ISO-8859-1。

  • 使用resp.getWriter()而不是resp.getOutputStream()来打印JSON响应。

在满足所有条件后,我终于能够将UTF-8输出回客户端。

这不是GAE特有的,但如果你发现它很有用:我自己创建了filter:

在web.xml中

  charsetencoding mypackage.CharsetEncodingFilter  ...  charsetencoding /*  

(将filter映射片段放在filter映射的开头,并检查您的url模式。

 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 { } } 

解决方法(安全)

这些答案中没有任何一个对我有用,所以我编写了这个类来编码UTF-Strings到ASCII-Strings (使用AsciiEncoder.encode(yourString)替换所有不在ASCII表中的字符,其中包含其表号,前面跟着一个标记) AsciiEncoder.encode(yourString)

然后可以使用AsciiEncoder.decode(yourAsciiEncodedString)将String 解码回UTF

 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 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; } } 

希望这有助于某人。