我有Spring应用程序正在遇到一些编码问题。当客户提交“圣保罗”时,我会在请求标头中看到它:
=============>>>网址是:/ users / 1825220 / activity = update_fields& hometown = S%C3%A3o%20Paulo & usrId = 1234 (PUT)
这是通过将请求转储到日志中而生成的。
logger.info("\n=============>>> url is: " + request.getRequestURI() + "/" + request.getQueryString() + " (" + request.getMethod() + ")");
然后将请求传递给方法:
@RequestMapping(value = "/users/{id}", method = RequestMethod.PUT)
public @ResponseBody
OperationResponse updateUser(HttpServletRequest request,
@PathVariable("id") Integer id,
@RequestParam(value = "hometown", required = false) String homeTown)
throws NoSuchAlgorithmException, UnsupportedEncodingException {
当我转储价值时:
logger.debug("HOMETOWN=" + homeTown);
我得到: HOMETOWN =圣保罗
我对编码的基础知识有些熟悉,而且一切看起来都是UTF-8,但显然我不知道如何解决这个问题。我已经看到了几个关于这个问题的主题,即使使用相同的数据,但我还没有发现任何可以解决它的问题。
我看到价值是正确的。例如:ã(在São中)具有这些十六进制值。 http://www.utf8-chartable.de/
U+00A3 £ c2 a3 POUND SIGN
U+00C3 Ã c3 83 LATIN CAPITAL LETTER A WITH TILDE
U+00E3 ã c3 a3 LATIN SMALL LETTER A WITH TILDE
传入的值与本机iOS应用和网站以及curl相同。 由于某种原因,ã(U + 00E3)被分成4个字节(%C3%A3)而不是2个(%E3)。 我无法弄清楚断开连接的位置。
我需要做的是优先找出在配置中要更改的内容,而不是在数据进入的任何地方添加代码更改。
答案 0 :(得分:0)
您遇到的问题是标准的UTF-8编码问题,如果没有按正确的顺序解码,这些问题通常会出现在URL参数中。
对于UTF-8,任何大于127的字符值都将转换为多字节序列,该序列仅由大于127的字节值组成。因此,您的ã正确编码为两个字节值。然后将字节值转换为URL编码使用的%xx表示法。
要对此进行解码,您需要执行相反的操作:将%表示法转换为字节流,然后使用UTF-8编码将字节转换为字符串。问题是某些环境以错误的顺序执行此操作:它们将字节流转换为字符串(解码UTF-8),然后它们处理URL编码。这是错误的顺序。
有一个强力解决方案可以恢复yur值,那就是获取损坏的值,将其转换回字节,然后转换为这样的字符串:
String val = new String(oldval.getBytes("iso-8859-1"), "UTF-8");
这是相当难看的代码,但它会将字符转换回来。
将HTTPRequest对象设置为UTF-8模式可以解决此问题。这样做:
request.setCharacterEncoding("UTF-8");
这可能适用于Spring ...我不确定何时解析标头。对于TomCat,如果您正在使用JSP文件,但是调用JSP文件的时间,则进行此设置为时已晚。标题已经被解析。解决此问题的官方最佳方法是在解析标头并调用JSP之前插入一个过滤器,在请求对象中进行此设置。如果您发现设置字符编码不起作用...请尝试过滤。
我在别处读到你可以在你的web.xml中使用这个设置在Spring中启用这样的过滤器(但我没有这方面的经验):
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
答案 1 :(得分:0)
0xE3
(顺便说一下,这只是1个字节)是大多数8位编码的值 - 特别是iso8859和cp1252 - 用于ã。
但是,url编码通常以UTF-8完成,以获得更好的兼容性。因此,2个字节0xC3 0xA3
。
在您的情况下,您的服务器正在读取它,就好像它不是1个utf-8字符,而是2个iso(或cp)字符。因此结果。
AgilePro建议的解决方案在大多数情况下都可以使用,但通过将服务配置为接受UTF-8或确保客户端指示他们使用的编码来解决实际问题会更清晰。
此问题可能与此问题有关:Spring MVC UTF-8 Encoding