ZKUI 是一款基於 HttpServlet 的開源 ZooKeeper 可視化管理工具。近期同事反饋:通過 ZKUI 上傳包含中文的節點值時顯示異常,經排查發現中文被編碼為 NCR(Numeric Character Reference,數字字符引用)格式。本文記錄問題根因分析、修復方案及 Docker 部署避坑指南。
上傳中文節點值後,前端顯示為 中文 這類十六進制實體引用。NCR 是 SGML/HTML/XML 中表示不可直接編碼字符的標準構造,由 &#xHHHH; 或 &#DDDD; 組成。瀏覽器渲染時會自動轉為對應字符,但在 ZKUI 列表頁、編輯框中卻顯示原始碼,嚴重影響可讀性。
查閱 ZooKeeper 官方文檔:「Any unicode character can be used in a path subject to constraints...」,且禁止字符僅限控制字符、代理區等特殊範圍。中文完全合法。故鎖定為 ZKUI 工具層面問題。
ZKUI 基於原生 HttpServlet 開發,未集成 Spring MVC 的 CharacterEncodingFilter。Tomcat 默認使用 ISO-8859-1 解碼請求參數,導致中文參數被錯誤解碼並進一步轉為 NCR 存儲。
@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 請求中文參數正常處理,列表頁、編輯框均正確顯示中文。
文件上傳使用 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("/.+=.+=.*")。
FROM java:8 MAINTAINER jimWORKDIR /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 映射宿主端口。
docker build -t jiangmin168168/zkui .
官方鏡像源國內極慢,推薦使用 DaoCloud 加速器(配置 Docker daemon registry-mirrors),構建速度提升數量級。
docker run -dit --name zkui --hostname zkui-host \ -v /data:/data -p 9090:9090 zkui:latest
-dit:後台運行 + 分配終端-v:掛載宿主數據目錄,便於持久化配置/導出文件-p:宿主 9090 映射容器 9090,支持多實例部署基於 java:8 基礎鏡像較大(~600MB),後續可嘗試:
① 使用 openjdk:8-jre-alpine(~100MB);
② 多階段構建,僅複製 JAR 到精簡運行鏡像;
③ 使用 jlink 定製精簡 JRE。
NCR 編碼具體在哪個環節(前端 JS、後端 Servlet、FileUpload、ZK 客戶端)引入?後續計劃通過斷點調試與源碼審計精確定位,實現徹底杜絕而非僅靠過濾器修正。
通過編碼過濾器統一 UTF-8、文件上傳顯式指定編碼、Docker 多階段構建優化體積,ZKUI 現已穩定運行於生產環境,完美支持中文節點管理與容器化部署。