ZKUI中文编码

问题

上周有同事反馈,通过ZKUI这个工具去上传带有中文的节点值时会出现中文无法显示的问题。最终发现编码是NCR编码,全称是:Numeric Character Reference。

什么是NCR?

这里引入一段维基百科的描述。
A numeric character reference (NCR) is a common markup construct used in SGML and SGML-derived markup languages such as HTML and XML. It consists of a short sequence of characters that, in turn, represents a single character. Since WebSgml, XML and HTML 4, the code points of the Universal Character Set (UCS) of Unicode are used. NCRs are typically used in order to represent characters that are not directly encodable in a particular document (for example, because they are international characters that don't fit in the 8-bit character set being used, or because they have special syntactic meaning in the language). When the document is interpreted by a markup-aware reader, each NCR is treated as if it were the character it represents.

确认是否是ZKUI的问题

由于zookeeper本身是可以存储中文的(引用一段zookeeper网站上的介绍),所以基本确认是ZKUI工具本身的问题。
The ZooKeeper Data Model
ZooKeeper has a hierarchal name space, much like a distributed file system. The only difference is that each node in the namespace can have data associated with it as well as children. It is like having a file system that allows a file to also be a directory. Paths to nodes are always expressed as canonical, absolute, slash-separated paths; there are no relative reference. Any unicode character can be used in a path subject to the following constraints:

  • The null character (\u0000) cannot be part of a path name. (This causes problems with the C binding.)
  • The following characters can't be used because they don't display well, or render in confusing ways: \u0001 - \u0019 and \u007F - \u009F.
  • The following characters are not allowed: \ud800 -uF8FFF, \uFFF0-uFFFF, \uXFFFE - \uXFFFF (where X is a digit 1 - E), \uF0000 - \uFFFFF.
  • The "." character can be used as part of another name, but "." and ".." cannot alone be used to indicate a node along a path, because ZooKeeper doesn't use relative paths. The following would be invalid: "/a/b/./c" or "/a/b/../c".
  • The token "zookeeper" is reserved.

ZKUI是基于什么实现的?

ZKUI个JAVA开源工具,可以下载源码。发现网页功能是基于HttpServlet实现的,没有使用其它一些高级的产品,比如Spring MVC等。知道是使用HttpServlet后,就会去对比Spring MVC对于中文的处理,然后就很容易去解决中文被NCR编码的问题。

这个项目结构是不是很像Spring MVC?

解决HttpServlet请求的中文编码

这里可以增加一个filter为请求对象以及响应对象增加UTF-8的处理。通过这步,ZKUI上提供的单节点的CRUD就可以正常处理中文节点值了。

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

解决上传文件的中文编码

上面只是解决了页面GET,POST解决单节点的CRUD过程中的编码问题,对于文件上传还需要特殊处理。看这段源码,细节我删除了,只留下主体结构以及编码部分的代码:

public class Import extends HttpServlet {private final static Logger logger = LoggerFactory.getLogger(Import.class);@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {logger.debug("Importing Action!");try {Iterator iter = items.iterator();while (iter.hasNext()) {FileItem item = (FileItem) iter.next();if (item.isFormField()) {if (item.getFieldName().equals("scmOverwrite")) {scmOverwrite = item.getString();}if (item.getFieldName().equals("scmServer")) {scmServer = item.getString();}if (item.getFieldName().equals("scmFilePath")) {scmFilePath = item.getString();}if (item.getFieldName().equals("scmFileRevision")) {scmFileRevision = item.getString();}} else {uploadFileName = item.getName();//原来的逻辑是item.getString(),我增加了指定编码sbFile.append(item.getString(StandardCharsets.UTF_8.toString()));}}List<String> importFile = new ArrayList<>();//获取节点的值......ZooKeeperUtil.INSTANCE.importData(importFile, Boolean.valueOf(scmOverwrite), ServletUtil.INSTANCE.getZookeeper(request, //处理其它一些内容request.getSession().setAttribute("flashMsg", "Import Completed!");response.sendRedirect("/home");} catch (FileUploadException | IOException | InterruptedException | KeeperException ex) {logger.error(Arrays.toString(ex.getStackTrace()));ServletUtil.INSTANCE.renderError(request, response, ex.getMessage());}}
}

上传的文件格式也有一定的要求:

  • 要求为无BOM的UTF-8,如果是有BOM,在处理时需要将前面的魔术数手工删除,或者是修改这个正则表达式:
  else if (!inputLine.matches("/.+=.+=.*")) {throw new IOException("Invalid format at line " + lineCnt + ": " + inputLine);}

  • 如果文件格式不是UTF-8的,那么会出现乱码内容。

ZKUI发布为docker

将编译好的java包,config.cfg以及项目中的Dockfile文件上传到linux服务器中。

这里简单介绍下Dockerfile

FROM java:8MAINTAINER jim <jiangmin168168@hotmail.com>WORKDIR /var/appADD zkui-*.jar /var/app/zkui.jar
ADD config.cfg /var/app/config.cfgENTRYPOINT [ "java", "-jar", "/var/app/zkui.jar" ]EXPOSE 9090

  • FROM,这是依赖的一些环境,比如java8,ubuntu,redis等
  • MAINTAINER,这是维护人员的信息
  • WORKDIR,这里指定工作目录,进入docker后,会直接进入这个目录,root@zkui-host:/var/app#
  • ADD,复制文件到容器
  • ENTRYPOINT,容器启动后自动执行的命令,这里直接运行我们的java包
  • EXPOSE,这是主机连接容器的容器端口,实际启动容器时,可以指定-p来配置主机与容器端口的映射

制作image

docker build -t jiangmin168168/zkui .

上面的jiangmin168168是在docker网站上的ID,可以将image上传到网站上去,如果只是本地用可以不用加这个ID。当然即使加了ID,只通过build也不能实现上传功能,还需要登录docker,通过push命令去实现。

docker build非常慢

由于官方的docker网站在国内非常慢,我基本没有成功过,期待良久最后无情的显示超时。最后经过同事的介绍使用了国内的DaoCloud提供的docker加速器,就是docker的一个镜像,这样大部分原本需要从docker.io下载的内容转到国内的镜像了,速度火箭上升。

查看制作的image

docker images

发现这个image还很大,估计是自动引入java8的原因,后面可以研究下自带jdk来看看能否减少空间。

启动容器

docker run -dit --name zkui  --hostname  zkui-host  -v /data:/data -p 9090:9090 zkui:latest

简单说明下这些参数

  • -dit,以后台模式运行,后面的it详细作用可以去查文档
  • --name,是容器的名称
  • --hostname,是登录进容器后显示的名称
  • -v,指定主机与容器的目录映射,方便于容器访问主机的目录
  • -p,是指定主机与容器的端口映射,容器中的端口是固定的,主机的端口是动态配置,这样就可以部署多个容器节点
  • zkui:latest,前面是image名称,后面是tag,如果只输入image默认的tag就是latest

遗留问题

ZKUI中的NCR是在什么地方引入的?回头还需要再查找下

ZKUI中文编码以及以docker方式运行的问题相关推荐

  1. Docker 以 docker 方式运行 jenkins

    https://testerhome.com/topics/5798 Docker 以 docker 方式运行 jenkins jmcn · 2016年08月26日 · 最后由 blueshark 回 ...

  2. 解决: Incorrect username or password, or no permission ( Docker 方式运行 Nexus3 登陆密码不为 admin123 、重置登陆密码)

    前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家.点击跳转到教程. 1. 登陆 输入 admin  admin123 直接报错: 查日志 发现的确登陆不成功: 2. 后 ...

  3. docker方式运行SRS

    步骤: (1)docker镜像用docker-hub官方的: docker pull ossrs/srs:3 (2)然后用命令启动容器: docker run -d -p 1935:1935 -p 1 ...

  4. Docker 方式安装、运行 Nexus3 、重置默认密码、推送 jar 包到私服

    前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家.点击跳转到教程. 1. 找镜像: docker search nexus 2. 拉取镜像:(我已经拉取过,不选择版本时 ...

  5. dingding(钉钉)+sonar(代码质量管理工具)通知并打包成docker容器运行

    项目地址:https://gitee.com/vians/dingding-sonar dingding-sonar-docker 基于dingding-sonar的作者,钉钉的sonar集成通知,钉 ...

  6. linux运行dock打包的镜像,Linux部署之Docker方式部署项目

    Linux部署之Docker方式部署项目 1. 使用Docker对前端vue项目进行部署 1.1 环境准备 服务器或者虚拟机上先安装好Nginx和相关配置 docker pull nginx 拉去最新 ...

  7. docker使用dockerfile方式运行java程序

    docker使用dockerfile方式运行java程序 1,下载基础java环境镜像java:8 2,创建文件夹并进入: mkdir dockerfile cd dockerfile 3,打包好的j ...

  8. [转帖]Docker里运行Docker docker in docker(dind)

    Docker里运行Docker docker in docker(dind) http://www.wantchalk.com/c/devops/docker/2017/05/24/docker-in ...

  9. 基于Docker本地运行k8s(单节点)

    基于Docker本地运行Kubernetes 概览 下面的指引将高速你如何通过Docker创建一个单机.单节点的Kubernetes集群. 下图是最终的结果: 先决条件 你必须拥有一台安装有Docke ...

最新文章

  1. 微服务化的数据库设计与读写分离
  2. Tensorflow警告:our CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2
  3. 三相滤波器怎么接线_您知道家用电表如何接线吗?小编来告诉你!
  4. siesta在Linux运行,请教,为什么siesta编译中没报错,然而运行的时候跑不起来呢...
  5. 安装了mysql5.7后,如何进行配置(密码等)初始化
  6. 成功解决 threading Exception unhandled RuntimeError
  7. SystemC在Ubuntu16.04上安装测试
  8. 1-1. 虚拟机控制
  9. Nagios 监控twemproxy
  10. arm 嵌入式系统复习大纲
  11. BZOJ 1260涂色 paint
  12. 怎么更改网络中的计算机名字,修改网络 “本地连接”的中网络名称“网络2”为其他名称...
  13. 一、线性表的顺序存储和基本运算
  14. 回溯法求解N皇后问题及其时间复杂度分析
  15. 5 Hibernate:Java Persistence API (JPA) 入门
  16. 前端毕业设计项目:基于Vue+Nodejs实现宿舍管理系统
  17. Android13 设备硬件不带振动马达去掉振动服务
  18. 1024 程序员节首日,全球开源掌门人领衔云上云下嘉年华
  19. 暴雪在洛杉矶建了自己的电竞馆,守望先锋锦标赛下个月就会在这里举行
  20. stm32简单小实例_煽动MCU/MPU市场,STM32的生态图

热门文章

  1. 看博客学学Android(二十一)
  2. UITapGestureRecognizer 的用法
  3. Alter index coalesce VS shrink space
  4. 全球软件巨头 Software AG 遭勒索攻击
  5. OpenSSL 修复可导致 DoS攻击的高危漏洞
  6. WebView断网提示
  7. 111 《深入理解Java虚拟机》读书笔记
  8. CVPR(IEEE Conference on Computer Vision and Pattern Recognition)
  9. linux help
  10. 不要在变量名的旁边加echo和.br;