最近用spring boot整合activiti后,發(fā)現(xiàn)審批留言有亂碼,很是困惑.經(jīng)過研究發(fā)現(xiàn),是編碼的問題.
先看Comment源碼:
public byte[] getFullMessageBytes() {
return (fullMessage!=null ? fullMessage.getBytes() : null);
}
public void setFullMessageBytes(byte[] fullMessageBytes) {
fullMessage = (fullMessageBytes!=null ? new String(fullMessageBytes) : null );
}
數(shù)據(jù)庫中這個(gè)字段是個(gè)blob字段.set get時(shí)用的是默認(rèn)編碼.這個(gè)默認(rèn)編碼是什么,用下面一段代碼,隨便加在一個(gè)controller中就可以得出.
String name1 = Charset.defaultCharset().name();
System.out.println(name1);
String name2 =Charset.defaultCharset().name();
System.out.println(name2);
啟動(dòng)單獨(dú)的tomcat,經(jīng)過測(cè)試,發(fā)現(xiàn)是GBK.
然后用idea啟動(dòng)tomcat,發(fā)現(xiàn)是UTF-8.為什么,因?yàn)槲倚薷腏etBrains\IntelliJ IDEA 2017.1\bin\idea64.exe.vmoptions文件,增加一行,修改了jvm啟動(dòng)參數(shù)
-Dfile.encoding=UTF-8
tomcat的jvm啟動(dòng)參數(shù)設(shè)置為utf-8
D:\devinstall\apache-tomcat-8.5.9\bin\catalina.bat
增加一行
set JAVA_OPTS=-Dfile.encoding=UTF-8
或者環(huán)境變量里設(shè)置
JAVA_TOOL_OPTIONS
-Dfile.encoding=UTF-8
這樣tomcat啟動(dòng)后,編碼就變成里utf-8.
我是有一次修改了這個(gè)tomcat編碼utf-8后,用戶發(fā)起了審批留言.然后我又換回了gbk.用戶發(fā)起審批留言的時(shí)候存入數(shù)據(jù)庫是utf-8編碼,切回gbk環(huán)境,讀取utf-8編碼的數(shù)據(jù)就有問題了.
我決定tomcat用utf-8編碼,blob字段也轉(zhuǎn)為utf-8編碼.先進(jìn)數(shù)據(jù)庫把數(shù)據(jù)導(dǎo)出到excel,就2列,id和blob字段.放到d盤,另存為-工具-web選項(xiàng),選擇編碼:utf-8,默認(rèn)是gbk.
轉(zhuǎn)換代碼:
@Test
public void test11() throws Exception {
//1.通過excel獲取sheet.
Sheet sheet = getSheetByFile();
//2.通過sheet獲取MyComment
List<MyComment> list = getList(sheet);
System.out.println(list);
//3.通過循環(huán)list,更新值
for (MyComment c:list){
String message = c.getMessage();
String id=c.getId();
byte[] bytes = message.getBytes("UTF-8");
todoTaskDao.updateComment(bytes, id);
}
}
public static Sheet getSheetByFile() throws Exception {
InputStream stream= new FileInputStream(new File("d:\\5.xls"));
Workbook wb = new HSSFWorkbook(stream);
return wb.getSheetAt(0);
}
public List<MyComment> getList(Sheet sheet1) throws Exception {
List<MyComment> myComments = new ArrayList<>();
for (int i = 1; i <= sheet1.getLastRowNum(); i++) {
try {
HSSFRow row = (HSSFRow) sheet1.getRow(i);
HSSFCell cell;
if (row == null || MyUtils.isBlankRow(row)) {
continue;
}
MyComment myComment = new MyComment();
for (int j = 0; j <= row.getLastCellNum(); j++) {
cell = row.getCell(j);
if (cell == null)
continue;
switch (j) {
case 0:
cell.setCellType(CellType.STRING);
myComment.setId(cell.getStringCellValue());
break;
case 1:
cell.setCellType(CellType.STRING);
myComment.setMessage(cell.getStringCellValue());
break;
default:
break;
}
}
myComments.add(myComment);
} catch (Exception e) {
String message = "第" + (i + 1) + "行有錯(cuò)誤:" + e.getMessage();
throw new Exception(message);
}
}
return myComments;
}
package com.yunchuang.console.workflow.domain;
import java.util.Arrays;
/**
* @author 尹冬飛
* @create 2017-04-20 13:40
*/
public class MyComment {
protected String id;
protected String message;
protected Object fullMessage;
protected byte[] fullMessageBytes;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Object getFullMessage() {
return fullMessage;
}
public void setFullMessage(Object fullMessage) {
this.fullMessage = fullMessage;
}
public byte[] getFullMessageBytes() {
return fullMessageBytes;
}
public void setFullMessageBytes(byte[] fullMessageBytes) {
this.fullMessageBytes = fullMessageBytes;
}
@Override
public String toString() {
return "MyComment{" +
"id='" + id + '\'' +
", message='" + message + '\'' +
", fullMessage=" + fullMessage +
", fullMessageBytes=" + Arrays.toString(fullMessageBytes) +
'}';
}
}
<resultMap id="commentResultMap" type="com.yunchuang.console.workflow.domain.MyComment">
<id property="id" column="ID_" jdbcType="VARCHAR" />
<result property="fullMessage" column="FULL_MSG_" jdbcType="BLOB" />
</resultMap>
<!-- COMMENT SELECT -->
<select id="selectComment" resultMap="commentResultMap">
select id_,FULL_MSG_
from ACT_HI_COMMENT
where ID_ = #{id,jdbcType=VARCHAR}
</select>
<!--2.更改-->
<update id="updateComment">
update ACT_HI_COMMENT set FULL_MSG_=#{fullMessage,jdbcType=BLOB} where ID_ = #{id,jdbcType=VARCHAR}
</update>
這樣就改過來了.這里提一句,測(cè)試?yán)锞幋a環(huán)境是utf-8,更改為gbk的方法為:測(cè)試的配置里更改.
這樣啟動(dòng)tomcat,測(cè)試,發(fā)現(xiàn)都正常.
但是問題又來了,tomcat的日志顯示不正常了,都亂碼了,包括tomcat本身和logback的都亂碼.logback亂碼解決方案:
在logback-spring.xml配置文件里有這么一段
<!--寫入日志到控制臺(tái)的appender,用默認(rèn)的,但是要去掉charset,否則windows下tomcat下亂碼-->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
</encoder>
</appender>
這里沒有設(shè)置編碼,是為了解決日志亂碼
tomcat本身亂碼,經(jīng)過查找,是因?yàn)閠omcat的編碼是utf-8,但是tomcat的默認(rèn)代碼頁是gbk,在tomcat左上角右鍵屬性里可以看到.修改tomcat控制當(dāng)前活動(dòng)頁為UTF-8 .
運(yùn)行regedit打開注冊(cè)表
HKEY_CURRENT_USER\Console\Tomcat
新增DWORD(32位)值
名稱:
CodePage
數(shù)據(jù):
0000fde9
運(yùn)行tomcat,發(fā)現(xiàn)還是亂碼,因?yàn)樽煮w不支持,所以設(shè)置tomcat屬性里字體,改為非點(diǎn)陣字體.發(fā)現(xiàn)tomcat本身日志不亂碼了.
但是logback的日志在原有不亂碼的下面幾行出現(xiàn)了亂碼.我懷疑是字體問題,按照網(wǎng)上的方法試了幾次,注冊(cè)表里增加控制臺(tái)字體,都沒有效果,最后只能改為gbk編碼了.
綜上,最后處理結(jié)果是,幾碼合一,才能不亂碼:
- tomcat控制臺(tái)代碼頁有編碼(GBK)
- tomcat控制臺(tái)字體也支持這個(gè)編碼
- tomcat的jvm啟動(dòng)參數(shù)有編碼(GBK,去掉UTF-8的設(shè)置)
- logback輸入到控制臺(tái)有編碼(GBK,不設(shè)置,就是調(diào)用系統(tǒng)默認(rèn)編碼)
- activiti設(shè)置和獲取Comment時(shí)用的系統(tǒng)默認(rèn)編碼(GBK)
- idea啟動(dòng)時(shí)可以設(shè)置jvm啟動(dòng)編碼(可設(shè)置UTF-8)
- 單元測(cè)試時(shí),可設(shè)置jvm編碼(根據(jù)需要隨時(shí)調(diào)整)