小编典典

如何让 UTF-8 在 Java webapps 中工作?

all

我需要让 UTF-8 在我的 Java webapp(servlets +
JSP,未使用框架)中工作,以支持盲枚氓常规芬兰文本和西里尔字母等笑卸肖特殊情况。

我的设置如下:

  • 开发环境:Windows XP
  • 生产环境:Debian

使用的数据库:MySQL 5.x

用户主要使用 Firefox2,但也使用 Opera 9.x、FF3、IE7 和 Google Chrome 访问该站点。

如何做到这一点?


阅读 62

收藏
2022-03-28

共1个答案

小编典典

回答我自己作为本网站的常见问题解答鼓励它。 这对我有用:

由于浏览器和 webapps 的 tomcat/java 使用的默认字符集是 latin1 即 latin1
,因此大多数字符盲坏枚都不是问题。ISO-8859-1 “理解”这些字符。

要让 UTF-8 在 Java+Tomcat+Linux/Windows+Mysql 下工作,需要以下条件:

配置 Tomcat 的 server.xml

需要配置连接器使用 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
)中找到

JSP 页面编码

在您的 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 片段的某种布局,那么 所有 这些都需要这样做。

HTML 元标记

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' />
   ...

JDBC 连接

使用 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&amp;characterEncoding=UTF-8"
    />

MySQL 数据库和表

使用的数据库必须使用 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服务器配置

MySQL serveri 也必须配置。这通常在 Windows 中通过修改 my.ini 文件来完成,在 Linux 中通过配置
my.cnf 文件来完成。在这些文件中,应该定义连接到服务器的所有客户端都使用 utf8 作为默认字符集,并且服务器使用的默认字符集也是 utf8。

   [client]
   port=3306
   default-character-set=utf8

   [mysql]
   default-character-set=utf8

Mysql程序和函数

这些也需要定义字符集。例如:

   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 ;

GET 请求:latin1 和 UTF-8

如果并且当它在 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%
有效。

Tomcat 与 Apache

还有一件事如果您使用的是 Apache + Tomcat + mod_JK 连接器,那么您还需要进行以下更改:

  1. 将 URIEncoding=”UTF-8” 添加到 8009 连接器的 tomcat server.xml 文件中,供 mod_JK 连接器使用。<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" URIEncoding="UTF-8"/>
  2. 转到您的 apache 文件夹,即并/etc/httpd/conf添加AddDefaultCharset utf-8. 注意:* 首先检查它是否存在。如果存在,您可以使用此行更新它。您也可以在底部添加此行。httpd.conf file *
2022-03-28