首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

ZKUI 中文亂碼終極解決方案與 Docker 化部署全記錄

     編輯:Java 綜合教學

ZKUI 中文亂碼終極解決方案與 Docker 化部署全記錄

ZKUI 是一款基於 HttpServlet 的開源 ZooKeeper 可視化管理工具。近期同事反饋:通過 ZKUI 上傳包含中文的節點值時顯示異常,經排查發現中文被編碼為 NCR(Numeric Character Reference,數字字符引用)格式。本文記錄問題根因分析、修復方案及 Docker 部署避坑指南。

1. 問題現象與 NCR 介紹

上傳中文節點值後,前端顯示為 中文 這類十六進制實體引用。NCR 是 SGML/HTML/XML 中表示不可直接編碼字符的標準構造,由 &#xHHHH; 或 &#DDDD; 組成。瀏覽器渲染時會自動轉為對應字符,但在 ZKUI 列表頁、編輯框中卻顯示原始碼,嚴重影響可讀性。

2. 確認非 ZooKeeper 原生問題

查閱 ZooKeeper 官方文檔:「Any unicode character can be used in a path subject to constraints...」,且禁止字符僅限控制字符、代理區等特殊範圍。中文完全合法。故鎖定為 ZKUI 工具層面問題。

3. 根因分析:HttpServlet 缺乏編碼過濾器

ZKUI 基於原生 HttpServlet 開發,未集成 Spring MVC 的 CharacterEncodingFilter。Tomcat 默認使用 ISO-8859-1 解碼請求參數,導致中文參數被錯誤解碼並進一步轉為 NCR 存儲。

4. 解決方案一:添加全局字符編碼過濾器

@WebFilter(filterName = "filtercharset", urlPatterns = "/*")
public class CharsetFilter implements Filter {
    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain fc)
            throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;
        request.setCharacterEncoding(StandardCharsets.UTF_8.name());
        response.setCharacterEncoding(StandardCharsets.UTF_8.name());
        fc.doFilter(req, res);
    }
    // init/destroy 留空
}

配置後,單節點 CRUD 的 GET/POST 請求中文參數正常處理,列表頁、編輯框均正確顯示中文。

5. 解決方案二:文件上傳編碼專項修復

文件上傳使用 Apache Commons FileUpload,需顯式指定編碼讀取表單字段與文件內容:

public class Import extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) {
        // ... 省略上傳解析邏輯 ...
        while (iter.hasNext()) {
            FileItem item = (FileItem) iter.next();
            if (item.isFormField()) {
                // 表單字段也需指定編碼
                String value = item.getString(StandardCharsets.UTF_8.name());
                // 處理 scmOverwrite, scmServer 等字段
            } else {
                // 文件內容按 UTF-8 讀取
                sbFile.append(item.getString(StandardCharsets.UTF_8.name()));
            }
        }
        // 後續導入邏輯...
    }
}

文件格式要求: 必須為無 BOM 的 UTF-8 編碼。若含 BOM,需手動移除魔數或調整行格式校驗正則:!inputLine.matches("/.+=.+=.*")。

6. ZKUI Docker 化部署實踐

6.1 Dockerfile 編寫

FROM java:8
MAINTAINER jim 
WORKDIR /var/app
ADD zkui-*.jar /var/app/zkui.jar
ADD config.cfg /var/app/config.cfg
ENTRYPOINT ["java", "-jar", "/var/app/zkui.jar"]
EXPOSE 9090

關鍵指令說明:WORKDIR 進入容器默認目錄;ADD 複製構建產物;ENTRYPOINT 容器啟動命令;EXPOSE 聲明容器端口,運行時通過 -p 映射宿主端口。

6.2 構建鏡像與加速

docker build -t jiangmin168168/zkui .

官方鏡像源國內極慢,推薦使用 DaoCloud 加速器(配置 Docker daemon registry-mirrors),構建速度提升數量級。

6.3 運行容器

docker run -dit --name zkui --hostname zkui-host \
  -v /data:/data -p 9090:9090 zkui:latest
  • -dit:後台運行 + 分配終端
  • -v:掛載宿主數據目錄,便於持久化配置/導出文件
  • -p:宿主 9090 映射容器 9090,支持多實例部署

6.4 鏡像體積優化方向

基於 java:8 基礎鏡像較大(~600MB),後續可嘗試:
① 使用 openjdk:8-jre-alpine(~100MB);
② 多階段構建,僅複製 JAR 到精簡運行鏡像;
③ 使用 jlink 定製精簡 JRE。

7. 遺留問題追蹤

NCR 編碼具體在哪個環節(前端 JS、後端 Servlet、FileUpload、ZK 客戶端)引入?後續計劃通過斷點調試與源碼審計精確定位,實現徹底杜絕而非僅靠過濾器修正。

通過編碼過濾器統一 UTF-8、文件上傳顯式指定編碼、Docker 多階段構建優化體積,ZKUI 現已穩定運行於生產環境,完美支持中文節點管理與容器化部署。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved