我需要让 UTF-8 在我的 Java webapp(servlets + JSP,未使用框架)中工作,以支持盲枚氓常规芬兰文本和西里尔字母等笑卸肖特殊情况。
盲枚氓
笑卸肖
我的设置如下:
使用的数据库:MySQL 5.x
用户主要使用 Firefox2,但也使用 Opera 9.x、FF3、IE7 和 Google Chrome 访问该站点。
如何做到这一点?
回答我自己作为本网站的常见问题解答鼓励它。 这对我有用:
由于浏览器和 webapps 的 tomcat/java 使用的默认字符集是 latin1 即 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。
此过滤器完成的另一件事是设置默认响应编码,即。返回的 html/whatever 的编码。另一种方法是在应用程序的每个控制器中设置响应编码等。
必须将此过滤器添加到 web.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>
制作此过滤器的说明可在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 页面中的字符。然后是时候告诉浏览器html页面的编码是什么了:
这是通过 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 编码。这是在 context.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;
关键部分是 CHARSET=utf8 。
MySQL serveri 也必须配置。这通常在 Windows 中通过修改 my.ini 文件来完成,在 Linux 中通过配置 my.cnf 文件来完成。在这些文件中,应该定义连接到服务器的所有客户端都使用 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 的 server.xml 中定义 GET 请求参数以 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 元标记)读取页面时,至少 Firefox 2/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 。 即使页面/请求/一切都被定义为使用 UTF-8 。盲的 UTF-8 编码版本是 %C3%A4
这样做的结果是 webapp 完全不可能正确处理来自 GET 请求的请求参数,因为某些字符以 latin1 编码,而另一些字符以 UTF-8 编码。 注意:如果页面被定义为 UTF-8,则 POST 请求确实可以工作,因为浏览器将表单中的所有请求参数完全编码为 UTF-8
非常感谢以下作者为我的问题提供答案:
mysql支持使用 3 字节 UTF-8 字符的基本多语言平面。如果您需要超出此范围(某些字母需要超过 3 字节的 UTF-8),那么您需要使用VARBINARY列类型或使用utf8mb4字符集(需要 MySQL 5.5.3 或更高版本)。请注意,utf8在 MySQL 中使用字符集不会 100% 有效。
VARBINARY
utf8mb4
utf8
还有一件事如果您使用的是 Apache + Tomcat + mod_JK 连接器,那么您还需要进行以下更改:
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" URIEncoding="UTF-8"/>
/etc/httpd/conf
AddDefaultCharset utf-8
httpd.conf file