SpringMVC+HibernateValidator,配置在properties文件中的错误信息回显前端页面出现中文乱码
問題:
后臺在springMVC中使用hibernate-validator做參數校驗的時候(validator具體使用方法見GOOGLE),用properties文件配置了校驗失敗的錯誤信息。發現回顯給前端頁面的時候中文錯誤信息顯示亂碼。
封裝參數的POJO類
public class UserReqBean {@NotNull(message="{user.name.notnull}")private String userName;}- 1
- 2
- 3
- 4
- 5
- 6
ValErrMsg.properties文件中的配置
user.name.notnull=用戶名不能為空- 1
spring-mvc.xml配置文件中validator的校驗錯誤信息配置
<!-- 校驗錯誤信息配置文件 --> <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource"><!-- 資源文件名 --><property name="basenames"><list><value>classpath:ValErrMsg</value></list></property><!-- 資源文件編碼格式 --><property name="fileEncodings" value="UTF-8"/><!-- 對資源文件內容緩存時間,單位秒 --><property name="cacheSeconds" value="120"/> </bean>我根據網絡上一篇講springMVC+hibernateValidator的文章進行上面的配置,出現了中文亂碼。
后來搜到一篇提到過亂碼,處理方式是Controller中獲取錯誤信息從IOS-8895-1轉UTF-8。但【魯迅眉頭一皺,發現事情并不靠譜.jpg】,框架出了這么久,怎么可能還存在這種需要自己手動轉碼的問題。
再后來搜到一篇靠譜的文章,發現用的是這個配置:
- 1
于是加上這個配置,就OK了!!!
原因:
配置messageSource的時候,使用的是這個ReloadableResourceBundleMessageSource類,點進去看源碼就發現問題在哪兒了。
public class ReloadableResourceBundleMessageSource extends AbstractMessageSource implements ResourceLoaderAware {···private String defaultEncoding;private Properties fileEncodings;···}原來fileEncodings并不是個String類型,所以上面那個配置是錯誤的。再來看加載properties文件的方法(為了看得清楚點,我把寫日志的部分刪除了):
protected Properties loadProperties(Resource resource, String filename) throws IOException {InputStream is = resource.getInputStream();Properties props = new Properties();Properties encoding1;try {if(resource.getFilename().endsWith(".xml")) {this.propertiesPersister.loadFromXml(props, is);} else {// 在這里讀取properties文件String encoding = null;// 先從fileEncodings里面取編碼方式(我之前的配置是String類型,這里就取不到編碼)if(this.fileEncodings != null) {encoding = this.fileEncodings.getProperty(filename);}// 沒取到則直接使用defaultEncoding(汗!之前沒配置!所以也沒取到)if(encoding == null) {encoding = this.defaultEncoding;}if(encoding != null) {this.propertiesPersister.load(props, new InputStreamReader(is, encoding));} else {// 取不到編碼,就只能來這里咯// 而InputStream默認的編碼并不是UTF-8,而是ISO-8859-1// 所以不管你怎么折騰都有問題,除非你愿意在所有地方手動轉碼// is說:怪我咯!!this.propertiesPersister.load(props, is);}}encoding1 = props;} finally {is.close();}弄清楚了原因,所以這里還有最正確的一種解決方案,xml配置如下:
<!-- 資源文件編碼格式 --> <property name="fileEncodings" ><props><prop key="classpath:ValErrMsg">UTF-8</prop></props> </property>- 1
- 2
- 3
- 4
- 5
- 6
這樣就能正確設置fileEncodings這個配置項。
再深入一點,fileEncodings是Properties類型,而Properties繼承于HashTable。從前面加載文件的地方可以看到,取value的key用的是文件名filename。
encoding = this.fileEncodings.getProperty(filename);- 1
所以需要將prop標簽的key設置為前面配置的文件名classpath:ValErrMsg(注意包含classpath)。同時也意味著如果有多個配置文件,可以對應資源文件列表為每個文件設置單獨的編碼。如果某個文件沒有設置編碼,就會使用defaultEncoding這個配置,如果沒配置,就任由InputStream放蕩不羈了……
總結一下:
1. 對于ReloadableResourceBundleMessageSource這個類,編碼的正確設置方式是:為每個資源文件設置編碼,并設置默認編碼。當然,如果項目只會出現一種編碼或者只有一個資源文件,可以直接簡單粗暴的只設置一個defaultEncoding就行了。
2. 網上的代碼不一定跑得起來,遇到問題去網上搜索解決方案,不如自己先跟進源碼去看。
PS:小弟才疏學淺,還在努力的學習中,只是想記錄下學習過程中遇到的問題。可能很簡單的地方講得很啰嗦還請多多包涵,另外許多疏漏之處還請斧正。
更新
之前使用的是springmvc版本4.1.1.RELEASE,ReloadableResourceBundleMessageSource類直接繼承于AbstractMessageSource。大概是在4.2以后的版本中,抽象出一個新類:AbstractResourceBasedMessageSource,defaultEncoding屬性放到了抽象類中。
繼承關系從
ReloadableResourceBundleMessageSource –> AbstractMessageSource
變成了ReloadableResourceBundleMessageSource –> AbstractResourceBasedMessageSource –> AbstractMessageSource
不過獲取文件編碼那一段代碼邏輯沒變。
總結
以上是生活随笔為你收集整理的SpringMVC+HibernateValidator,配置在properties文件中的错误信息回显前端页面出现中文乱码的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 原生线程池这么强大,Tomcat 为何还
- 下一篇: spingmvc的一些简单理解和记录