我需要让UTF-8在我的Java webapp(servlets+JSP,不使用框架)中工作,以支持äöå
等常规芬兰语文本和西里尔字母,如ЦжФ
等特殊情况.
我的设置如下:
- 开发环境:Windows XP
- 生产环境:Debian
使用的数据库:MySQL 5.x
用户主要使用Firefox2,但也使用Opera 9.x、 FF3、IE7和谷歌浏览器被用来访问该网站.
如何做到这一点?
我需要让UTF-8在我的Java webapp(servlets+JSP,不使用框架)中工作,以支持äöå
等常规芬兰语文本和西里尔字母,如ЦжФ
等特殊情况.
我的设置如下:
使用的数据库:MySQL 5.x
用户主要使用Firefox2,但也使用Opera 9.x、 FF3、IE7和谷歌浏览器被用来访问该网站.
如何做到这一点?
Answering myself as the FAQ of this site encourages it. This works for me: 个
大多数字符äåö都不是问题,因为浏览器和tomcat/java用于Web应用程序的默认字符集是latin1,即"理解"这些字符的ISO-8859-1.
要让UTF-8在Java+Tomcat+Linux/Windows+Mysql下工作,需要以下条件:
需要配置连接器使用UTF-8来编码url(GET请求)参数:
<Connector port="8080" maxHttpHeaderSize="8192"
maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
enableLookups="false" redirectPort="8443" acceptCount="100"
connectionTimeout="20000" disableUploadTimeout="true"
compression="on"
compressionMinSize="128"
noCompressionUserAgents="gozilla, traviata"
compressableMimeType="text/html,text/xml,text/plain,text/css,text/ javascript,application/x-javascript,application/javascript"
URIEncoding="UTF-8"
/>
在上面的例子中,关键部分是URIEncoding="UTF-8".这保证了Tomcat以UTF-8编码的方式处理所有传入的GET参数.
https://localhost:8443/ID/Users?action=search&name=*ж*
字符ж被处理为UTF-8,并被编码为(通常在到达服务器之前由浏览器编码)为%D0%B6.
POST请求不受此影响我>
然后是时候强制java webapp以UTF-8编码的方式处理所有请求和响应了.这要求我们定义一个字符集过滤器,如下所示:
package fi.foo.filters;
import javax.servlet.*;
import java.io.IOException;
public class CharsetFilter implements Filter {
private String encoding;
public void init(FilterConfig config) throws ServletException {
encoding = config.getInitParameter("requestEncoding");
if (encoding == null) encoding = "UTF-8";
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain next)
throws IOException, ServletException {
// Respect the client-specified character encoding
// (see HTTP specification section 3.4.1)
if (null == request.getCharacterEncoding()) {
request.setCharacterEncoding(encoding);
}
// Set the default response content type and encoding
response.setContentType("text/html; charset=UTF-8");
response.setCharacterEncoding("UTF-8");
next.doFilter(request, response);
}
public void destroy() {
}
}
此筛选器确保如果浏览器未设置请求中使用的编码,则将其设置为UTF-8.
这个过滤做的另一件事是设置默认的响应编码ie.返回的html/任何内容采用的编码.另一种方法是在应用程序的每个控制器中设置响应编码等.
必须将此过滤器添加到网站.xml或webapp的部署描述符:
<!--CharsetFilter start-->
<filter>
<filter-name>CharsetFilter</filter-name>
<filter-class>fi.foo.filters.CharsetFilter</filter-class>
<init-param>
<param-name>requestEncoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharsetFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
The instructions for making this filter are found at the tomcat wiki (http://wiki.apache.org/tomcat/Tomcat/UTF-8)
在web.xml中,添加以下内容:
<jsp-config>
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<page-encoding>UTF-8</page-encoding>
</jsp-property-group>
</jsp-config>
或者,WebApp的所有JSP页面的顶部需要有以下内容:
<%@page pageEncoding="UTF-8" contentType="text/html; charset=UTF-8"%>
如果使用了具有不同JSP片段的某种布局,那么它们中的所有部分都需要这样做.
JSP页面编码告诉JVM以正确的编码处理JSP页面中的字符.
这是通过在webapp生成的每个xhtml页面的顶部执行以下操作来完成的:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fi">
<head>
<meta http-equiv='Content-Type' content='text/html; charset=UTF-8' />
...
使用db时,必须定义连接使用UTF-8编码.这是在上下文中完成的.xml或JDBC连接定义如下的任何地方:
<Resource name="jdbc/AppDB"
auth="Container"
type="javax.sql.DataSource"
maxActive="20" maxIdle="10" maxWait="10000"
username="foo"
password="bar"
driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/ ID_development?useEncoding=true&characterEncoding=UTF-8"
/>
使用的数据库必须使用UTF-8编码.这是通过使用以下内容创建数据库来实现的:
CREATE DATABASE `ID_development`
/*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_swedish_ci */;
然后,所有表格也需要采用UTF-8格式:
CREATE TABLE `Users` (
`id` int(10) unsigned NOT NULL auto_increment,
`name` varchar(30) collate utf8_swedish_ci default NULL
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_swedish_ci ROW_FORMAT=DYNAMIC;
关键部分是字符集=utf8.
还必须配置MySQL serveri.通常,这在Windows中通过修改my.ini-file来完成,在Linux中通过配置my.cnf-file来完成. 在这些文件中,应该定义连接到服务器的所有客户端都使用UTF8作为默认字符集,并且服务器使用的默认字符集也是UTF8.
[client]
port=3306
default-character-set=utf8
[mysql]
default-character-set=utf8
这些还需要定义字符集.例如:
DELIMITER $$
DROP FUNCTION IF EXISTS `pathToNode` $$
CREATE FUNCTION `pathToNode` (ryhma_id INT) RETURNS TEXT CHARACTER SET utf8
READS SQL DATA
BEGIN
DECLARE path VARCHAR(255) CHARACTER SET utf8;
SET path = NULL;
...
RETURN path;
END $$
DELIMITER ;
如果以及何时在tomcat的服务器中定义.GET请求参数的xml以UTF-8编码,以下GET请求得到正确处理:
https://localhost:8443/ID/Users?action=search&name=Petteri
https://localhost:8443/ID/Users?action=search&name=ж
由于ASCII字符的编码方式与latin1和UTF-8相同,因此字符串"Petteri"的处理是正确的.
在latin1中根本不理解西里尔文字符ж.因为Tomcat被指示将请求参数作为UTF-8处理,所以它将该字符正确地编码为%D0%b6.
如果指示浏览器以UTF-8编码(带有请求头和html元标记)读取页面,则至少Firefox2/3和这一时期的其他浏览器都将字符本身编码为%D0%B6.
最终结果是找到了名为"Petteri"的所有用户,也找到了名为"ж"的所有用户.
HTTP规范定义,默认情况下,URL编码为latin1.这导致firefox2、firefox3等编码如下
https://localhost:8443/ID/Users?action=search&name=*Päivi*
输入到编码版本
https://localhost:8443/ID/Users?action=search&name=*P%E4ivi*
在latin1中,字符ä编码为%E4.Even though the page/request/everything is defined to use UTF-8美元.ä的UTF-8编码版本是%C3%A4
这样做的结果是,webapp不可能正确处理GET请求中的请求参数,因为有些字符是用拉丁文1编码的,而有些字符是用UTF-8编码的.
非常感谢下面的作者为我的问题提供了答案:
mysql supports the Basic Multilingual Plane using 3-byte UTF-8 characters. If you need to go outside of that (certain alphabets require more than 3-bytes of UTF-8), then you either need to use a flavor of VARBINARY
column type or use the utf8mb4
character set (which requires MySQL 5.5.3 or later). Just be aware that using the utf8
character set in MySQL won't work 100% of the time.
如果您使用的是Apache+Tomcat+mod_JK连接器,那么还需要做以下更改:
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" URIEncoding="UTF-8"/>
/etc/httpd/conf
,在httpd.conf file
中添加AddDefaultCharset utf-8
.Note:首先判断它是否存在.如果存在,您可以使用此行更新它.你也可以在底部加上这一行.