最近用spring boot整合activiti后,发现审批留言有乱码,很是困惑.经过研究发现,是编码的问题.
先看Comment源码:
public byte[] getFullMessageBytes() {
return (fullMessage!=null ? fullMessage.getBytes() : null);
}
public void setFullMessageBytes(byte[] fullMessageBytes) {
fullMessage = (fullMessageBytes!=null ? new String(fullMessageBytes) : null );
}
数据库中这个字段是个blob字段.set get时用的是默认编码.这个默认编码是什么,用下面一段代码,随便加在一个controller中就可以得出.
String name1 = Charset.defaultCharset().name();
System.out.println(name1);
String name2 =Charset.defaultCharset().name();
System.out.println(name2);
启动单独的tomcat,经过测试,发现是GBK.
然后用idea启动tomcat,发现是UTF-8.为什么,因为我修改JetBrains\IntelliJ IDEA 2017.1\bin\idea64.exe.vmoptions文件,增加一行,修改了jvm启动参数
-Dfile.encoding=UTF-8
tomcat的jvm启动参数设置为utf-8
D:\devinstall\apache-tomcat-8.5.9\bin\catalina.bat
增加一行
set JAVA_OPTS=-Dfile.encoding=UTF-8
或者环境变量里设置
JAVA_TOOL_OPTIONS
-Dfile.encoding=UTF-8
这样tomcat启动后,编码就变成里utf-8.
我是有一次修改了这个tomcat编码utf-8后,用户发起了审批留言.然后我又换回了gbk.用户发起审批留言的时候存入数据库是utf-8编码,切回gbk环境,读取utf-8编码的数据就有问题了.
我决定tomcat用utf-8编码,blob字段也转为utf-8编码.先进数据库把数据导出到excel,就2列,id和blob字段.放到d盘,另存为-工具-web选项,选择编码:utf-8,默认是gbk.
转换代码:
@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.通过循环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) + "行有错误:" + 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>
这样就改过来了.这里提一句,测试里编码环境是utf-8,更改为gbk的方法为:测试的配置里更改.
这样启动tomcat,测试,发现都正常.
但是问题又来了,tomcat的日志显示不正常了,都乱码了,包括tomcat本身和logback的都乱码.logback乱码解决方案:
在logback-spring.xml配置文件里有这么一段
<!--写入日志到控制台的appender,用默认的,但是要去掉charset,否则windows下tomcat下乱码-->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
</encoder>
</appender>
这里没有设置编码,是为了解决日志乱码
tomcat本身乱码,经过查找,是因为tomcat的编码是utf-8,但是tomcat的默认代码页是gbk,在tomcat左上角右键属性里可以看到.修改tomcat控制当前活动页为UTF-8 .
运行regedit打开注册表
HKEY_CURRENT_USER\Console\Tomcat
新增DWORD(32位)值
名称:
CodePage
数据:
0000fde9
运行tomcat,发现还是乱码,因为字体不支持,所以设置tomcat属性里字体,改为非点阵字体.发现tomcat本身日志不乱码了.
但是logback的日志在原有不乱码的下面几行出现了乱码.我怀疑是字体问题,按照网上的方法试了几次,注册表里增加控制台字体,都没有效果,最后只能改为gbk编码了.
综上,最后处理结果是,几码合一,才能不乱码:
- tomcat控制台代码页有编码(GBK)
- tomcat控制台字体也支持这个编码
- tomcat的jvm启动参数有编码(GBK,去掉UTF-8的设置)
- logback输入到控制台有编码(GBK,不设置,就是调用系统默认编码)
- activiti设置和获取Comment时用的系统默认编码(GBK)
- idea启动时可以设置jvm启动编码(可设置UTF-8)
- 单元测试时,可设置jvm编码(根据需要随时调整)