使用Spring的ISO-8859请求的Jetty Utf8Appendable $ NotUtf8Exception

时间:2012-02-03 22:48:08

标签: encoding jetty

远程服务使用ISO-8859-15编码的请求调用我们的Jetty服务器。此特殊请求映射在Spring Controller上。 Jetty无法以正确的方式对请求进行编码,并显示以下异常:

exception=org.eclipse.jetty.util.Utf8Appendable$NotUtf8Exception: Not valid UTF8! byte F6 in state 3}
org.eclipse.jetty.util.Utf8Appendable$NotUtf8Exception: Not valid UTF8! byte F6 in state 3
    at org.eclipse.jetty.util.Utf8Appendable.appendByte(Utf8Appendable.java:168) ~[na:na]
    at org.eclipse.jetty.util.Utf8Appendable.append(Utf8Appendable.java:93) ~[na:na]
    at org.eclipse.jetty.util.UrlEncoded.decodeUtf8To(UrlEncoded.java:506) ~[na:na]
    at org.eclipse.jetty.util.UrlEncoded.decodeTo(UrlEncoded.java:554) ~[na:na]
    at org.eclipse.jetty.server.Request.extractParameters(Request.java:285) ~[na:na]
    at org.eclipse.jetty.server.Request.getParameter(Request.java:695) ~[na:na]
    ....

解决方案

在Spring中,即使整个应用程序使用UTF-8,也可以通过CharacterEncodingFilter强制执行请求编码。异常应该消失。

<filter>
    <filter-name>encoding-filter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
        <param-name>encoding</param-name>
        <param-value>ISO-8859-15</param-value>
    </init-param>
    <init-param>
        <param-name>forceEncoding</param-name>
        <param-value>true</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>encoding-filter</filter-name>
    <url-pattern>/app/specialRequest.do</url-pattern>
</filter-mapping>

如果这不适合你

  • 找出远程系统编码
  • 启动Wireshark通过ip.src == xxx.xxx.xxx.xxx过滤器分析传入的包
  • 在请求正文中搜索特殊字符(将十六进制值重新计算为二进制并尝试使用几种常用编码来找到与该异常匹配的编码)
  • 通过Jetty的start.ini设置编码即。使用以下参数

    Dorg.eclipse.jetty.util.URI.charset = ISO-8859-15

    Dorg.eclipse.jetty.util.UrlEncoding.charset = ISO-8859-15

如果您有更多问题,请给我留言。

1 个答案:

答案 0 :(得分:4)

看起来客户端发送的文本应该编码为UTF8,但不会对其进行编码。

为了正确诊断此问题,您需要了解UTF8(您可能会这样做,我不知道)

在UTF8中,编码为127(0x7F)或更少的任何字符 - 仅使用最低的7位 - 包含在流(否特殊编码)。但是,任何大于127的东西(即设置比第7个高出至少一位)都是专门编码的。

0xF6大于0x7F因此,如果客户想要发送该字符,则应对其进行编码。

二进制文件中的

0xF611110110,其中UTF8应为11000011 10110110C3 B6

因此,如果客户端想要发送0x88的ISO8859-1字符,那么它应该发送UTC8字节序列0xC3 0xB6。

你真的需要弄清楚客户想要发送的内容,数据所在的字符集/编码,以及它在发送之前没有将其转换为有效的UTF8的原因。

(“状态3”,与Jetty的内部表进行UTF8解码有关,对于诊断这个问题并没有什么帮助。如果找到客户端,它只会派上用场,看起来像客户端正在做正确的事情,你怀疑Jetty的UTF8解码是错误的)