ตอบคำถามตัวเองว่าเป็นคำถามที่พบบ่อยของเว็บไซต์นี้ สิ่งนี้ใช้ได้กับฉัน:
อักขระส่วนใหญ่äåöไม่ใช่ปัญหาเนื่องจากชุดอักขระเริ่มต้นที่ใช้โดยเบราว์เซอร์และ tomcat / java สำหรับ webapps คือ latin1 เช่น ISO-8859-1 ซึ่ง "เข้าใจ" อักขระเหล่านั้น
ในการทำให้ UTF-8 ทำงานภายใต้ Java + Tomcat + Linux / Windows + Mysql จำเป็นต้องมีสิ่งต่อไปนี้:
กำหนดค่า server.xml ของ Tomcat
จำเป็นต้องกำหนดค่าว่าตัวเชื่อมต่อใช้พารามิเตอร์ 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 จัดการกับพารามิเตอร์ GET ขาเข้าทั้งหมดตามการเข้ารหัส UTF-8 ดังนั้นเมื่อผู้ใช้เขียนสิ่งต่อไปนี้ในแถบที่อยู่ของเบราว์เซอร์:
https://localhost:8443/ID/Users?action=search&name=*ж*
жตัวอักษรที่มีการจัดการเป็น UTF-8 และมีการเข้ารหัส (โดยปกติเบราว์เซอร์ก่อนที่จะได้เดินทางไปยังเซิร์ฟเวอร์) ตาม% D0% B6
คำขอ POST จะไม่ได้รับผลกระทบจากสิ่งนี้
CharsetFilter
จากนั้นถึงเวลาที่จะบังคับให้ 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 / อะไรก็ตาม ทางเลือกคือการตั้งค่าการเข้ารหัสการตอบสนอง ฯลฯ ในแต่ละคอนโทรลเลอร์ของแอปพลิเคชัน
ต้องเพิ่มตัวกรองนี้ใน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>
หรือมิฉะนั้นหน้า JSP ทั้งหมดของ webapp จะต้องมีสิ่งต่อไปนี้ที่ด้านบนของพวกเขา:
<%@page pageEncoding="UTF-8" contentType="text/html; charset=UTF-8"%>
หากมีการใช้เลย์เอาต์ที่มี JSP-fragments ต่างกันดังนั้นจึงจำเป็นต้องใช้สิ่งเหล่านี้ทั้งหมด
แท็ก HTML-meta
การเข้ารหัสเพจ JSP แจ้งให้ JVM จัดการอักขระในหน้า JSP ในการเข้ารหัสที่ถูกต้อง จากนั้นก็ถึงเวลาที่จะบอกเบราว์เซอร์ที่เข้ารหัสหน้า html:
สิ่งนี้ทำกับสิ่งต่อไปนี้ที่ด้านบนของแต่ละหน้า xhtml ที่ผลิตโดย webapp:
<?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 เป็น defiend ดังนี้:
<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"
/>
ฐานข้อมูลและตาราง 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 -file และใน Linux โดยกำหนดค่าmy.cnf -file ในไฟล์เหล่านั้นควรกำหนดให้ไคลเอ็นต์ทั้งหมดที่เชื่อมต่อกับเซิร์ฟเวอร์ใช้ 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 ;
รับคำขอ: latin1 และ UTF-8
ถ้าและเมื่อมันถูกกำหนดใน server.xml ของ tomcat ที่ 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" อย่างถูกต้อง
อักขระซีริลลิกไม่เข้าใจในละติน 1 ทั้งหมด เพราะ Tomcat ได้รับคำสั่งให้ค่าคำขอจับเป็น UTF-8 มันเข้ารหัสตัวอักษรที่ถูกต้องตาม% D0% B6
ถ้าและเมื่อเบราว์เซอร์จะได้รับคำแนะนำในการอ่านหน้าในการเข้ารหัส UTF-8 (ที่มีการร้องขอส่วนหัวและ HTML เมตาแท็ก) อย่างน้อย 2/3 Firefox และเบราว์เซอร์อื่น ๆ จากช่วงเวลานี้เข้ารหัสทุกตัวละครตัวเองเป็น% 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
ผลที่ได้คือสิ่งนี้เป็นไปไม่ได้ที่เว็บแอปจะจัดการพารามิเตอร์คำขอจากคำขอ GET โดยทั่วไปเนื่องจากอักขระบางตัวถูกเข้ารหัสใน latin1 และอื่น ๆ ใน UTF-8
แจ้งให้ทราบล่วงหน้า: คำขอ POST ทำงานเป็นเบราว์เซอร์เข้ารหัสพารามิเตอร์คำขอทั้งหมดจากแบบฟอร์มอย่างสมบูรณ์ใน UTF-8 หากหน้าถูกกำหนดให้เป็น UTF-8
เรื่องน่าอ่าน
ขอบคุณมากสำหรับผู้เขียนต่อไปนี้ที่ให้คำตอบสำหรับปัญหาของฉัน:
- http://tagunov.tripod.com/i18n/i18n.html
- http://wiki.apache.org/tomcat/Tomcat/UTF-8
- http://java.sun.com/developer/technicalArticles/Intl/HTTPCharset/
- http://dev.mysql.com/doc/refman/5.0/en/charset-syntax.html
- http://cagan327.blogspot.com/2006/05/utf-8-encoding-fix-tomcat-jsp-etc.html
- http://cagan327.blogspot.com/2006/05/utf-8-encoding-fix-for-mysql-tomcat.html
- http://jeppesn.dk/utf-8.html
- http://www.nabble.com/request-parameters-mishandle-utf-8-encoding-td18720039.html
- http://www.utoronto.ca/webdocs/HTMLdocs/NewHTML/iso_table.html
- http://www.utf8-chartable.de/
โน๊ตสำคัญ
MySQLรองรับเครื่องบินแบบหลายภาษาขั้นพื้นฐานโดยใช้อักขระ UTF-8 ขนาด 3 ไบต์ หากคุณต้องการออกไปข้างนอกนั้น (ตัวอักษรบางตัวต้องมากกว่า 3-bytes ของ UTF-8) จากนั้นคุณต้องใช้รสชาติของVARBINARY
ประเภทคอลัมน์หรือใช้utf8mb4
ชุดอักขระ (ซึ่งต้องใช้ MySQL 5.5.3 หรือใหม่กว่า) เพิ่งทราบว่าการใช้utf8
ชุดอักขระใน MySQL จะไม่ทำงาน 100% ของเวลา
Tomcat กับ Apache
อีกอย่างหนึ่งถ้าคุณใช้ตัวเชื่อมต่อ Apache + Tomcat + mod_JK คุณก็ต้องทำการเปลี่ยนแปลงดังต่อไปนี้:
- เพิ่ม URIEncoding = "UTF-8" ลงในไฟล์ tomcat server.xml สำหรับตัวเชื่อมต่อ 8009 ซึ่งถูกใช้โดยตัวเชื่อมต่อ mod_JK
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" URIEncoding="UTF-8"/>
- ไปที่คุณ Apache โฟลเดอร์เช่น
/etc/httpd/conf
และเพิ่มในAddDefaultCharset utf-8
หมายเหตุ:ตรวจสอบก่อนว่ามันมีอยู่หรือไม่ หากมีอยู่คุณสามารถอัปเดตด้วยสายนี้ คุณสามารถเพิ่มบรรทัดนี้ที่ด้านล่างได้httpd.conf file