如何获得UTF-8在Java webapps中的工作?

我需要在我的Java webapp(servlets + JSP,不使用框架)中使用UTF-8来支持常规芬兰语文本和西里尔文字母,如特殊情况下的ЦжФ

我的设置如下:

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

使用的数据库:MySQL 5.x

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

如何做到这一点?

回答自己作为本网站的常见问题鼓励自己。 这适用于我:

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

要获得在Java + Tomcat + Linux / Windows + Mysql下工作的UTF-8,需要以下内容:

configurationTomcat的server.xml

有必要configuration连接器使用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请求不受此影响。

CharsetFilter

接下来是强制java webapp处理所有请求和响应,如UTF-8编码。 这就要求我们定义一个像下面这样的字符集filter:

 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() { } } 

这个filter确保如果浏览器没有设置请求中使用的编码,它被设置为UTF-8。

这个filter完成的另一件事是设置默认的响应编码即。 在返回的HTML /无论是编码。 另一种方法是在应用程序的每个控制器中设置响应编码等。

必须将此filter添加到webapp的web.xml或部署描述符中:

  <!--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> 

这个filter的说明可以在tomcat维基上find( 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页面中的字符。 然后是时候告诉vrowser哪个编码html页面了:

这是由web应用程序生成的每个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连接

在使用数据库时,必须定义连接使用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编码。 这是通过创build具有以下内容的数据库来实现的:

  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服务器configuration

MySQL serveri也必须configuration。 通常这是通过修改my.ini文件在Windows中完成的,并且通过configurationmy.cnf文件在Linux中完成。 在这些文件中,应该定义连接到服务器的所有客户端都使用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编码方式相同,string“Petteri”处理正确。

西里尔文字符在latin1中完全不被理解。 因为Tomcat被指示以UTF-8处理请求参数,所以它正确地将该字符编码为%D0%B6

如果指示浏览器以UTF-8编码(带请求标题和html元标记)读取页面,至lessFirefox 2/3和其他浏览器都会将该字符本身编码为%D0%B6

最终的结果是find名为“Petteri”的所有用户,并find所有名称为“ж”的用户。

但是äåö呢?

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

这样做的结果是,Web应用程序不可能相互处理来自GET请求的请求参数,因为有些字符是用latin1编码的,而UTF-8是其他编码的。 注意:如果页面被定义为UTF-8,那么POST请求会起作用,因为浏览器完全以UTF-8编码来自表单的所有请求参数

东西阅读

非常感谢以下作者为我的问题提供答案:

重要的提示

mysql支持使用3字节的UTF-8字符的基本多语言平面 。 如果你需要超出这个范围(某些字母需要超过3个字节的UTF-8),那么你需要使用VARBINARY列types的味道或使用utf8mb4字符集 (这需要MySQL 5.5.3或更高版本)。 请注意,在MySQL中使用utf8字符集将无法100%的工作。

与Apache的Tomcat

还有一件事如果你使用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并在httpd.conf file添加AddDefaultCharset utf-8注意:首先检查它是否存在。 如果存在,你可以用这行更新它。 你也可以在底部添加这一行。

我想你自己的回答总结得很好。

在UTF-8-ing(?)的过程中,你可能也想确保java本身使用UTF-8。 使用-Dfile.encoding = utf-8作为JVM的参数(可以在catalina.bat中configuration)。

要添加到kosoant的答案 ,如果您使用的是Spring,而不是编写自己的Servletfilter,那么可以使用它们提供的org.springframework.web.filter.CharacterEncodingFilter类,在web.xml中对其进行如下configuration:

  <filter> <filter-name>encoding-filter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>FALSE</param-value> </init-param> </filter> <filter-mapping> <filter-name>encoding-filter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> 

当我们想要使用Java访问它们时,这是希腊编码在MySql表中:

在你的JBoss连接池(mysql-ds.xml)中使用下面的连接设置:

 <connection-url>jdbc:mysql://192.168.10.123:3308/mydatabase</connection-url> <driver-class>com.mysql.jdbc.Driver</driver-class> <user-name>nts</user-name> <password>xaxaxa!</password> <connection-property name="useUnicode">true</connection-property> <connection-property name="characterEncoding">greek</connection-property> 

如果你不想把它放在一个JNDI连接池中,你可以把它configuration成一个JDBC-url,如下一行所示:

 jdbc:mysql://192.168.10.123:3308/mydatabase?characterEncoding=greek 

对我和尼克来说,我们永远不会忘记它,浪费时间了…..

尼斯详细的答案。 只是想添加一个更多的东西,肯定会帮助其他人看到URL上的UTF-8编码。

请按照以下步骤在Firefox中的URL上启用UTF-8编码。

  1. 在地址栏中input“about:config”。

  2. 使用filterinputtypes来search“network.standard-url.encode-query-utf8”属性。

  3. 上述属性默认为false,将其设为TRUE。
  4. 重新启动浏览器。

IE6 / 7/8和chrome默认使用URL上的UTF-8编码。

我也想从这里添加这部分解决了我的utf问题:

 runtime.encoding=<encoding> 

我有一个类似的问题,但是,在一个文件的文件名我压缩与Apache公共。 所以,我用这个命令解决了它:

 convmv --notest -f cp1252 -t utf8 * -r 

它对我来说效果很好。 希望它帮助任何人;)

对于我从消息包中显示Unicode字符的情况,我不需要应用“JSP页面编码”部分在我的jsp页面上显示Unicode。 我需要的只是“CharsetFilter”部分。

另一个没有提到的问题涉及到使用Ajax的Java Servlets。 我有这样的情况:网页从用户发送utf-8文本到发送到一个JavaScript文件,这个文件包含在发送给Servlet的URI中。 Servlet查询数据库,捕获结果并将其作为XML返回给格式化JavaScript的文件,并将格式化的响应插入到原始网页中。

在一个Web应用程序中,我遵循一个早期的Ajax书籍的说明,在构buildURI时包装JavaScript。 书中的例子使用了escape()方法,我发现(困难的方法)是错误的。 对于utf-8,你必须使用encodeURIComponent()。

现在很less有人似乎推出了自己的Ajax,但是我认为不妨补充一下。

关于CharsetFilter kosoant答案中提到的CharsetFilter

在tomcat web.xml (位于conf/web.xml )中有一个构buildFilter 。 该filter名为setCharacterEncodingFilter ,默认情况下会进行注释。 您可以取消注释(请记住取消注释其filter-mapping

也没有必要在你的web.xml设置jsp-config (我已经testing了Tomcat 7+)

有时候你可以通过MySQL Administrator向导来解决问题。 在

启动variables>高级>

并设置Def。 char设置:utf8

也许这个configuration需要重新启动MySQL。

如果你已经在连接池(mysql-ds.xml)中指定了,在你的Java代码中,你可以打开连接,如下所示:

 DriverManager.registerDriver(new com.mysql.jdbc.Driver()); Connection conn = DriverManager.getConnection( "jdbc:mysql://192.168.1.12:3308/mydb?characterEncoding=greek", "Myuser", "mypass");