Spring/Tomcat Rest开发 配置UTF-8编码
2017-04-17 14:36
429 查看
环境/框架:windows7+Intellij Idea+jdk8+tomcat+Spring
起因:写微信支付接口时遇到过很多编码错误问题,比如:
1. 收到了微信返回、console里打印出来错误描述是“???mchid???appid???”
2. 返回给设备端的出错描述,postman里看到是“JSON???????”
3. 另外这里提到的签名checksum计算错误
目的:使代码开发、程序运行和读写http消息时都使用UTF-8编码
Disclaimer:只是整理自己遇到且试过的(没有数据库、html页面相关)。解决思路和大部分代码来源都是StackOverflow(感谢SO答主)。一些能原帖链接已经附上、其他用英文google应该都能找到。
Checklist:
IDEA settings -> file encodings 都设成UTF-8,目的:将项目源文件都以UTF-8保存。
[optional] 修改IDEA bin/目录下的idea.exe.vmoptions/idea64.exe.vmoptions文件 或通过Help菜单的Edit Custom VM Options、增加
(仔细想了想其实说不出这个有什么具体作用…但因为遇到过console打印乱码问题,为了限制/缩小排查范围就加上了。)
以上参考intellij-idea-incorrect-encoding-in-console-output
设置maven或gradle编译选项,具体参考:
Maven文档
how-to-configure-encoding-in-maven
show-utf-8-text-properly-in-gradle
目的:保证生成的class文件(特别是其中的static String)都使用utf8编码。
配置tomcat。用到的是
(1)jvm_opts增加
(2)server.xml里
两个非常详细的参考:
Tomcat FAQ CharactorEncoding (里面的How to use UTF-8 everywhere节)
how-to-get-utf-8-working-in-java-webapps
4000
配置web.xml里servlet
如果接口开发里使用的是javax的
参考:
CharacterEncodingFilter
encoding-and-servlet-api-setcontenttype-or-setcharacterencoding
然而如果使用Spring web MVC、具体是用到
参考 RequestMapping Java doc
其中提到比如:
@ResponseBody annotated methods (Servlet-only) for access to the Servlet response HTTP contents. The return value will be converted to the response stream using message converters.
还有这个09年的帖子
CharacterEncodingFilter can’t help here, because String returned by @RequestBody-annotated method is encoded by StringHttpMessageConverter
(没有在Spring代码里找到到底是哪边决定使用
此时如果Controller方法里注入或返回的参数是
参考
StringHttpMessageConverter Java doc
who-sets-response-content-type-in-spring-mvc-responsebody (具体几种配置方法可参考这个链接)
我希望统统都用utf8,所以直接
然而09年那个帖子的回答里写的直接是
实际测下来是可以用的(注入了UTF-8 Charset对象),不是很确定Spring到底是怎么解析的…
4主要处理GET Request、5主要处理POST Request、6主要处理Response,这样server端应该就没问题了。而Spring的
好奇了下Jackson,结果说Jackson因为Json关系只支持的UTF-8、UTF-16和UTF-32、且可以自动检测,参考
jackson-objectmapper-with-utf-8-encoding
JsonEncoding.java
jackson-core/issues/222
特地查了Json的encoding要求,还确实是这样。
xml的话,开头就是
话说回来,编码encoding、字符集charset到底是什么?UTF-8、UTF-16、UTF-32又有什么区别?
又翻回到以前看的…
whats-the-difference-between-encoding-and-charset
what-is-unicode-utf-8-utf-16
评论提到的入门必读absolute-minimum-must-know
甚至这个贴吧帖子: 我早就想问了,极影下载的GB和BIG5,究竟是什么区别?
不过GB是编码,GB2312和GBK是字符集;而Unicode是字符集,UTF-8、UTF-16、UTF-32都是编码;开始确实有点绕…
昨天提交完文档就遇到同组里其他人开发的接口里fastJson的JSONObject注入出错、后来参考了这个17年4月7号的教程、加了
起因:写微信支付接口时遇到过很多编码错误问题,比如:
1. 收到了微信返回、console里打印出来错误描述是“???mchid???appid???”
2. 返回给设备端的出错描述,postman里看到是“JSON???????”
3. 另外这里提到的签名checksum计算错误
目的:使代码开发、程序运行和读写http消息时都使用UTF-8编码
Disclaimer:只是整理自己遇到且试过的(没有数据库、html页面相关)。解决思路和大部分代码来源都是StackOverflow(感谢SO答主)。一些能原帖链接已经附上、其他用英文google应该都能找到。
Checklist:
IDEA settings -> file encodings 都设成UTF-8,目的:将项目源文件都以UTF-8保存。
[optional] 修改IDEA bin/目录下的idea.exe.vmoptions/idea64.exe.vmoptions文件 或通过Help菜单的Edit Custom VM Options、增加
-Dfile.encoding=UTF8参数,目的:使IDE在UTF-8下运行。
(仔细想了想其实说不出这个有什么具体作用…但因为遇到过console打印乱码问题,为了限制/缩小排查范围就加上了。)
以上参考intellij-idea-incorrect-encoding-in-console-output
设置maven或gradle编译选项,具体参考:
Maven文档
how-to-configure-encoding-in-maven
show-utf-8-text-properly-in-gradle
目的:保证生成的class文件(特别是其中的static String)都使用utf8编码。
配置tomcat。用到的是
(1)jvm_opts增加
-Dfile.encoding=UTF8(可以修改catalina.bat或Intellij的run configuration),目的:保证在运行各webapp时用UTF8而不是系统默认编码(开头提到的checksum问题)。
(2)server.xml里
<Connector>增加属性
URIEncoding="UTF-8",目的:保证GET方法的url(及query string)使用utf8解析。
两个非常详细的参考:
Tomcat FAQ CharactorEncoding (里面的How to use UTF-8 everywhere节)
how-to-get-utf-8-working-in-java-webapps
4000
配置web.xml里servlet
<filter>,我看到的用Spring的一般都是
<filter> <filter-name>SpringEncodingFilter</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>
CharacterEncodingFilter的作用Java doc里写的很清楚,代码里是这样:
String encoding = getEncoding(); // 这个是xml里设置的UTF-8 if (encoding != null) { if (isForceRequestEncoding() || request.getCharacterEncoding() == null) { request.setCharacterEncoding(encoding); } if (isForceResponseEncoding()) { // isForceRequestEncoding和isForceResponseEncoding都等于forceEncoding response.setCharacterEncoding(encoding); } }
如果接口开发里使用的是javax的
HttpServletRequest和
HttpServletResponse,配置完这步后、
Content-Type里的charset应该都是UTF-8了。当然这个只是加个名称、具体body的stream读写还是要自己处理的…
参考:
CharacterEncodingFilter
encoding-and-servlet-api-setcontenttype-or-setcharacterencoding
然而如果使用Spring web MVC、具体是用到
@RequestBody、
@ResponseBody等annotation时,将stream和目标Object互转的class是
HttpMessageConverter而非
CharacterEncodingFilter,
参考 RequestMapping Java doc
其中提到比如:
@ResponseBody annotated methods (Servlet-only) for access to the Servlet response HTTP contents. The return value will be converted to the response stream using message converters.
还有这个09年的帖子
CharacterEncodingFilter can’t help here, because String returned by @RequestBody-annotated method is encoded by StringHttpMessageConverter
(没有在Spring代码里找到到底是哪边决定使用
CharacterEncodingFilter或者
HttpMessageConverter,但既然官方doc里这么说了、应用开发知道就好了吧…)
此时如果Controller方法里注入或返回的参数是
String类型1、且没有指定编码(
@RequestMapping里没有produces),仍然是有默认
charset=ISO-8859-1会被框架自动添加上去。这个默认charset来自的是
StringHttpMessageConverter:
public static final Charset DEFAULT_CHARSET = Charset.forName("ISO-8859-1");
参考
StringHttpMessageConverter Java doc
who-sets-response-content-type-in-spring-mvc-responsebody (具体几种配置方法可参考这个链接)
我希望统统都用utf8,所以直接
register-defaults="false"并改了defaultCharset,写出来的xml是这样:
<mvc:annotation-driven> <mvc:message-converters register-defaults="false"> <bean class="org.springframework.http.converter.StringHttpMessageConverter"> <constructor-arg> <util:constant static-field="java.nio.charset.StandardCharsets.UTF_8"/> </constructor-arg> </bean> </mvc:message-converters> </mvc:annotation-driven>
然而09年那个帖子的回答里写的直接是
<constructor-arg value="UTF-8">
实际测下来是可以用的(注入了UTF-8 Charset对象),不是很确定Spring到底是怎么解析的…
4主要处理GET Request、5主要处理POST Request、6主要处理Response,这样server端应该就没问题了。而Spring的
RestTemplateclient,参考how-can-i-tell-resttemplate-to-post-with-utf-8-encoding,也是一样加了utf-8的message converter。
好奇了下Jackson,结果说Jackson因为Json关系只支持的UTF-8、UTF-16和UTF-32、且可以自动检测,参考
jackson-objectmapper-with-utf-8-encoding
JsonEncoding.java
jackson-core/issues/222
特地查了Json的encoding要求,还确实是这样。
xml的话,开头就是
<?xml version="1.0" encoding="UTF-8"?>。
话说回来,编码encoding、字符集charset到底是什么?UTF-8、UTF-16、UTF-32又有什么区别?
又翻回到以前看的…
whats-the-difference-between-encoding-and-charset
what-is-unicode-utf-8-utf-16
评论提到的入门必读absolute-minimum-must-know
甚至这个贴吧帖子: 我早就想问了,极影下载的GB和BIG5,究竟是什么区别?
不过GB是编码,GB2312和GBK是字符集;而Unicode是字符集,UTF-8、UTF-16、UTF-32都是编码;开始确实有点绕…
昨天提交完文档就遇到同组里其他人开发的接口里fastJson的JSONObject注入出错、后来参考了这个17年4月7号的教程、加了
FastJsonHttpMessageConverter就好。总之Spring预设就挂载这多个MessageConverter(前文链接里2.2. The Default Message Converters列表)、有多个converter可以对
supportedMediaTypesproperty进行细化配置,暂时没有更深入了解了就不写了 ↩
相关文章推荐
- spring3mvc框架开发中resin和tomcat默认servelt配置处理静态资源
- jdk+tomcat+myeclipse+spring开发环境配置小记
- 配置Tomcat支持UTF-8编码
- Tomcat之——接收UTF-8编码GET参数请求配置
- Tomcat7.0/8.0 详细安装配置图解,以及UTF-8编码配置
- Tomcat7.0/8.0 详细安装配置图解,以及UTF-8编码配置
- Eclipse+MyEclipse+tomcat开发中,全局编码设置为UTF-8
- 项目启动时,提示spring配置文件未知的utf-8编码
- Spring构建Web应用部署至Tomcat开发过程中的数据编码问题
- Tomcat7.0/8.0 详细安装配置图解,以及UTF-8编码配置
- Spring 3.X 基于Tomcat的Web应用开发配置文件详解
- Tomcat 配置 UTF-8 编码
- 配置Apache和Tomcat使用UTF-8编码
- Spring 安装、配置、REST开发
- tomcat6.0+struts2.2.1+spring2.5.6+ibatis2.3.4+mysql5.1最简开发环境配置及样例开发
- Tomcat 7.0 、Tomcat8.0 详细安装配置图解,以及UTF-8编码配置
- Eclipse + Lomboz + Tomcat JSP 开发配置
- jsp开发所需要的eclipse插件(lomboz、tomcatplugin)及其安装、配置方法
- 再论J2EE开发中的编码问题,统一使用UTF-8以适应多语种J2EE开发
- Web程序开发配置(Eclipse + Tomcat + Webwork + Hibernate)