C2A0造成FastJSON序列化时,出现异常java.lang.ArrayIndexOutOfBoundsException

今天莫名其妙的出现问题,表现为部分数据造成服务端500错误,出现java.lang.ArrayIndexOutOfBoundsException异常。
第一反应是特殊字符,仔细检查果然如此。
00

UTF-8编码:C2A0
Unicode序号:00A0
Unicode字符:NO-BREAK SPACE
HTML实体编码: 
NO-BREAK SPACE

低版本(<=1.1.39)的FastJSON在序列化时,会出现数组越界异常,升级为高版本(>=1.1.41)即可(为什么不是1.1.40版本?)。看来又被集团类库坑了(为什么要说“又”呢?)。

参考资料:
Unicode®字符百科
The Unicode Standard, Version 8.0
FastJSON序列化特殊字符BUG

Windows下Git和TortoiseGit的安装与基本操作

图文版下载:http://blog.codemonkey.cn/static/Windows-Git-TortoiseGit-Tutorial.pdf
纯文本内容如下:


1安装Git
1.1下载地址:https://git-scm.com/download/win
1.1.1下载相应版本。

1.1.2检查数字签名。

1.2安装过程:
1.2.1开始安装。

1.2.2同意用户协议。

1.2.3指定安装路径。

1.2.4资源管理器集成和文件格式关联。

1.2.5启用开始菜单。

1.2.6建议只在Git Bash中使用Git,尽可能避免环境污染。

1.2.7建议不要修改换行风格,避免提交无意义变更。

1.2.8建议使用自带命令行,避免莫名其妙的错误。

1.2.9感觉没必要启用缓存。

1.2.10等待安装完成。

1.2.11安装完成。

1.3检查安装结果
1.3.1在文件夹空白处右键,进入Git Bash。

1.3.2输入git –version,检查Git版本。

2安装TortoiseGit
2.1下载地址:https://tortoisegit.org/download/
2.1.1下载相应版本(及其语言包)。

2.1.2检查数字签名。

2.2安装过程
2.2.1开始安装。

2.2.2同意用户协议。

2.2.3本文档使用PuTTY作为SSH客户端。如需选用OpenSSH,请自行查找Git SSH配置。

2.2.4指定安装路径,资源管理器集成和文件格式关联。

2.2.5确认安装。

2.2.6等待安装完成。

2.2.7安装完成。

2.2.8安装语言包。

3生成并配置密钥
3.1生成公钥和私钥
3.1.1找到并启动PuTTY程序。

3.1.2开始创建公私密钥对。

3.1.3鼠标在空白区域狂划。

3.1.4创建成功,暂时放着,一会再用。

3.1.5进入个人文件夹根目录(如C:\Users\UserName),使用CMD命令“md .ssh”创建“.ssh”文件夹。

3.1.6进入“.ssh”文件夹,使用“cd . > config”创建“config”文件。

3.1.7回到PuTTY程序。修改Key comment为有意义文本(如gitlab-rsa-key-20151028),便于识别。建议添加Key passphrase,为当前私钥加密,可避免未授权使用。注意,此密码一经设置不可修改。

3.1.8保存PuTTY格式私钥文件。

3.1.9建议保存在前面创建的“.ssh”文件夹中,建议使用“.ppk”后缀(如gitlab-rsa-key-20151028.ppk)。

3.1.10保存公钥文件。

3.1.11建议保存在前面创建的“.ssh”文件夹中,建议使用“.pub”后缀(如gitlab-rsa-key-20151028.pub)。

3.1.12转换当前PuTTY格式私钥为OpenSSH格式。

3.1.13建议保存在前面创建的“.ssh”文件夹中,建议无后缀(如gitlab-rsa-key-20151028)。

3.2配置Git多账户
3.2.1打开前面创建的“config”文件。

3.2.2每一个账户,须配置一套如下参数
Host gitlab.alibaba-inc.com # 远程仓储域名
User UserName # 仓储用户名
IdentityFile ~/.ssh/gitlab-rsa-key-20151028 # OpenSSH私钥路径,“~”符号表示个人文件夹根目录。

3.3配置远程仓储
3.3.1打开阿里内部的Git平台gitlab.alibaba-inc.com,进入配置界面。

3.3.2进入SSH Key菜单,点击Add SSH Key按钮。

3.3.3回到PuTTY程序。复制公钥字符串。

3.3.4将公钥字符串粘贴至Key文本框(Title文本框会自动填充),点击Add Key按钮完成添加。

4尝试Git基本操作
4.1克隆远程仓储至本地仓储
4.1.1找到远程仓储地址

4.1.2在合适位置(如MyGit文件夹)右键,点击Git Clone(Git克隆)。

4.1.3在URL中输入远程仓储地址。在Load Putty Key(加载Putty密钥)中选择前面生成的PuTTY格式私钥文件。

4.1.4如果前面为私钥设置了密码,第一次使用时需要输入私钥密码。

4.1.5第一次连接远程仓储时会有安全确认。

4.1.6克隆远程仓储成功,根据远程仓储配置默认会创建master分支。

4.2切换远程分支
4.2.1在项目目录,右键点击TortoiseGit,选中Switch/Checkout(切换/检出)。

4.2.2在Branch(分支)中选中期望远程分支(如remotes/origin/daily/1.1.0),默认会创建对应的本地分支(如daily/1.1.0)。

4.2.3切换预期远程分支成功。

4.3拉取远程分支
4.3.1在项目目录,右键点击TortoiseGit,选中Pull(拉取)。注意,Pull(拉取)操作,实际上经历了Fetch(获取)远程分支,和Merge(合并)本地分支。

4.3.2确认拉取操作。

4.3.3拉取远程分支成功。

4.4提交修改至本地仓储
4.4.1修改本地文件(如Readme.md),进行一些操作(如在最后敲个换行)。

4.4.2在项目目录,右键点击Git Commit -> “daily/1.1.0”(Git提交 -> “daily/1.1.0”)。

4.4.3在第一次提交时,需要输入名称和邮件。

4.4.4修改配置前必读。

4.4.5配置项在Git中分为三级,分别是Local(此版本库)、Global(全局)、System(系统)。Local级配置只对当前版本库起效,Global级配置只对当前用户起效,System级配置对当前PC所有用户起效。优先级为Local高于Global高于System。建议针对每个项目,都使用Local级配置。去除User Info(用户信息)中name(名称)和Email(邮箱)后的inherit(继承)复选框,在文本框中填写相应信息。

4.4.6继续提交,必须输入Message(日志信息)。

4.4.7提交成功。

4.5推送本地分支至远程分支
4.5.1在项目目录,右键点击TortoiseGit,选中Push(推送)。

4.5.2使用默认配置即可。

4.5.3推送成功。

4.5.4检查远程仓储推送记录。

5在gitlab.aibaba-inc.com中正式发布(请谨慎操作)。
5.1在本地分支中打标签
5.1.1在项目目录,右键点击TortoiseGit,选中Create Tag(创建标签)。

5.1.2输入标签名称。在gitlab.alibaba-inc.com中约定,开发时需要创建一个名为daily/x.y.z的分支,开发结束后,在该分支上打一个名为publish/x.y.z的标签,其中x.y.z要相同。

5.2推送本地分支中标签至远程分支
5.2.1在项目目录,右键点击TortoiseGit,选中Push(推送)。

5.2.2选中Include Tags(包含标签)复选框。

5.2.3推送成功后,当前标签(publish/1.1.0)会自动触发线上发布脚本,将代码部署至正式环境。发布完成后,会自动将远程仓储中当前分支(如daily/1.1.0)与master分支合并,然后删除当前分支。

JSON并不完全是JavaScript的子集,它们对部分字符处理不同。

业务方提出的BUG,某位用户总是无法正常使用系统,初步诊断为接口JSON解析失败。

进一步检查发现,该接口返回数据:
正常情况下,“Response Headers”中“Content-Type”为“application/json; charset=utf-8
”,Chrome开发工具中“Response Body Preview”为JSON对象。
异常情况下,“Response Headers”中“Content-Type”为“application/json; charset=utf-8
”,Chrome开发工具中“Response Body Preview”为JSON字符串。

而“Response Body”初看起来,一切正常。仔细一看才发现,原来其中混入了一个控制字符“ESC”(Unicode编码为\u001b),现代浏览器(IE9-11、Chrome、Firefox)不可正常识别数据格式(IE8反而可以识别),造成JSON解析失败,进而触发Ajax的error回调。如图所示:
JSON特殊字符

查询相关资料,发现之前对于JSON的理解有些狭隘,原来JSON并不完全是JavaScript的子集。
mozilla说明:
JavaScript 与 JSON 的区别

现代浏览器测试:

由此可知,需要对用户输入进行过滤。对于部分字符进行预处理,避免浏览器无法解析接口返回数据。
写了一个处理函数:

参考资料:
介绍 JSON
http://www.json.org/json-zh.html
JSON
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/JSON
JSON: The JavaScript subset that isn’t
http://www.timelessrepo.com/json-isnt-a-javascript-subset

IE8与近代(IE9至IE11)及现代(Chrome和Firefox)浏览器,对于\r和\n的处理方式不同。

需求:对于textarea中输入的换行,要在页面中表现出来。
方案:输入内容在展示时,通过将\r和\n替换为标签,代码如下:

以上代码,在IE9-11、Chrome、Firefox中运行良好,但在IE8下无效。
调试后发现,原来IE8中通过innerHTML拿出的字符串,被移除了\r和\n。

IE8
IE9
chrome
firefox

参考资料:
Document.createElement()
https://developer.mozilla.org/zh-CN/docs/Web/API/Document/createElement
element.innerHTML
https://developer.mozilla.org/zh-CN/docs/Web/API/Element/innerHTML
Node.nodeValue
https://developer.mozilla.org/zh-CN/docs/Web/API/Node/nodeValue
Node.textContent
https://developer.mozilla.org/zh-CN/docs/Web/API/Node/textContent

使用Java对图片进行裁剪,裁减后出现偏色现象。

关键词:
Java 图片 照片 裁剪 剪切 缩放 偏色 失真 变形

先上结论:
对原始图片进行裁剪操作,一切正常。对上传后的文件进行裁剪,出现偏色现象。调节各种裁剪参数,更换多种裁剪方式,均不奏效。
最后发现,原始图片和上传后的图片,虽然直接打开后视觉效果表现一致,但文件大小变小了。进一步检查发现,图片中的大部分EXIF信息丢失,只剩下最基本的信息。
在上传图片的过程中,使用了集团封装的类库,对文件内容进行安全过滤。我们并不清楚过滤的具体细节,结果由于过度信任而浪费了大量时间。
猜测java的图形处理类库,需要依赖较多的EXIF信息,对此种文件兼容性较差。由于时间原因,未深入探寻。如以后找到更多信息,再回来进行补充。

再来吐槽:
百度和google了很久,相关信息很少,stackoverflow中也没找到相关问题。只找到很久之前两个没有答案的问题,也不知道这两位题主最后有没有找到解决方案。
http://www.oschina.net/question/190011_85557
http://zhidao.baidu.com/link?url=-1-_iQBsBuLzeuadYWGNXjVuQUIXqc4P07veaTKoJHDytJmmbhqE5a6pb108Bn2HBY6F7IjOjJ-5JLQgsiaHsshA4oNNKJZbq4M5w1hRH-i

最后看图:
原始图片
原图
原始图片EXIF信息
原图_EXIF
安全过滤后图片
新图
安全过滤后图片的EXIF信息
新图_EXIF
裁剪后偏色图片
小图
裁剪后偏色图片的EXIF信息
小图_EXIF