Unicode 支持在 Java Web 程序中应用实践Unicode 是互联网的基石,为了保证我们的 Web 应用程序很好的支持 Unicode 标准。从代码角度需要考虑 Unicode 支持的地方有(不限于这些,下面是基于笔者项目实践):
Java 默认字符集设定:通常情况下如 Windows 系统,我们会通过设置环境变量 JAVA_TOOL_OPTIONS 将默认编码更改为 UTF-8,下面是 Java 程序默认字符集的优先级顺序:
- 程序执行时使用 Properties 指定的字符集,如 System.getProperties().put("file.encoding","UTF-8);
- 参数-Dfile.encoding 指定的字符集,如 Windows 可以通过设置环境变量 JAVA_TOOL_OPTIONS=-Dfile.encoding=UTF-8
- 操作系统默认的字符集;
- JDK 中 JVM 默认的字符集。
JSP:通过 JSP 页面命令<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>设置 JSP 页面的编码方式(pageEncoding)以及提交表单时所使用的编码方式(charset 属性);
HTML:
设置 Content-Type 属性<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">;
Servlet:设置 response.setContentType("text/html;charset=UTF-8"),即服务器端编码方式;
POST请求:
通过 request.setCharacterEncoding ("UTF-8")设置解码方式、response.setCharacterEncoding("UTF-8")设置服务器端响应数据的编码方式,如清单 3 所示;
清单 3. POST 请求字符编码设置 1
2
3
4
5
6
| protected void service(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
// TODO Auto-generated method stub
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
}
|
Get 请求:Get 请求方式中请求参数会被附加到地址栏的 URL 之后,URL 组成:域名:端口/contextPath/servletPath/pathInfo?queryString,不同的服务器对 URL 中 pathInfo 和 queryString 解码方式设定不一样,比如 Tomcat 服务器一般在 server.xml 中设定的,Tomcat8 之前的版本默认使用的是 ISO-8859-1,但是 Tomcat 8 默认使用的是 UTF-8,如清单 4 所示;另外对于双字节字符如中日韩等作为 URL 的参数时,最好先 URI 编码后在放到 URL 中 URLEncoder.encode(String.valueOf(c),"UTF-8");
清单 4. Tomcat server.xml 设置 1
2
3
4
5
6
7
| Tomcat server.xml
<Connector port="8080" protocol="HTTP/1.1"
maxThreads="150"
connectionTimeout="20000"
redirectPort="8443"
URIEncoding="UTF-8"
useBodyEncodingForURI="true">
|
XML 文档:设置 transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
调用 API 时指定字符集:调用字符串操作相关或者其他 I/O 操作 API 时,最好指定字符集,如 String.getBytes("UTF-8"),而不是 String.getBytes();根据情况必要的时候需要写入 BOM 头,例如 Microsoft Office 在读取 csv 文件的时候,它将首先读取 BOM,然后使用 BOM 中的编码打开文件,这种情况下我们在创建或者导出到 CSV 文件的时候,我们需要在代码里面写入 BOM 头。图 10 所示的例子是创建一个 csv 文件的时候没有写入 BOM,用 Office 打开看到的都是乱码,但是用其他编辑器比如 notepad++显示是正常。当加上 BOM 文件头的时候 fos.write(new byte[]{(byte)0xEF,(byte)0xBB, (byte)0xBF}) 用 Office 再次打开就是正确的字符,代码如清单 5 所示。备注一下,UTF-8 虽然部分大端小端序,但是可以加 BOM 头,表示这个文本是 UTF-8 编码。
图 11. 缺少 BOM 标记乱码示例清单 5. BOM 标记例子 1
2
3
4
5
6
7
8
9
10
11
12
13
14
| private static void createCsvFile() {
try {
FileOutputStream fos = new FileOutputStream("c:\\test.csv");
String str ="姓名,性别,年龄,出生年月";
fos.write(new byte[]{(byte)0xEF,(byte)0xBB, (byte)0xBF});
OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8");
BufferedWriter b_writer = new BufferedWriter(osw);
b_writer.write(str);
b_writer.close();
} catch (IOException e) {
System.out.println(e.toString());
}
}
|
Oracle 数据库:Oracle 数据库从 7.2 开始支持 Unicode,为了让应用程序更好的支持多语言,当我们新建一个数据库的时候,最好使用 UTF-8 编码格式,从而可以对如 CHAR、VARCHAR2、CLOB、LONG 等 SQL 数据类型使用 UTF-8 进行编码;如果多语言数据可能只出现在某些字段中,那么也可以直接使用支持 Unicode 编码的 SQL 数据类型,如 NCHAR、NVARCHAR2 和 NCLOB,如表 4 列出的常用 SQL 数据类型介绍。
表 5. SQL 数据类型介绍SQL 数据类型编码方式内存分配
最大
字节数SemanticsCHAR
数据库编码方式 固定长度 2000 字节(Bytes) NCHAR Unicode 固定长度 2000 字符(character) VARCHAR2 数据库编码方式 变长 4000 字节/字符(bytes/character) NVARCHAR2 Unicode 变长 4000 字符(character)
总结本文介绍了 Unicode 规范,详细概述了 Unicode 常用的三种编码方式编码算法、特点以及他们之间的区别和应用场景,介绍了 ICU4J 库,基于项目实践,终结了如何在 Java Web 程序中更好的支持 Unicode,从而实现应用程序的多语言化,希望能对读者深入理解 Unicode 规范、Unicode 编码方式以及如何让我们的 Web 程序更好的支持 Unicode 提供帮助。 |