7.spring boot activiti 審批留言亂碼問題

最近用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.

Paste_Image.png
Paste_Image.png

轉換代碼:

    @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的方法為:測試的配置里更改.


Paste_Image.png

這樣啟動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編碼(根據需要隨時調整)
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容