Mysql
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Mysql

Làm cách nào để UTF-8 hoạt động trong các ứng dụng web Java?

Tự trả lời là Câu hỏi thường gặp của trang web này khuyến khích điều đó. Điều này phù hợp với tôi:

Hầu hết các ký tự äåö không phải là một vấn đề vì bộ ký tự mặc định được sử dụng bởi các trình duyệt và tomcat / java cho các ứng dụng web là latin1 tức là. ISO-8859-1 "hiểu" các ký tự đó.

Để UTF-8 hoạt động trong Java + Tomcat + Linux / Windows + Mysql yêu cầu những điều sau:

Định cấu hình server.xml của Tomcat

Cần phải định cấu hình trình kết nối sử dụng UTF-8 để mã hóa các tham số url (yêu cầu 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"
/>

Phần quan trọng là URIEncoding ="UTF-8" trong ví dụ trên. Điều này chứng minh rằng Tomcat xử lý tất cả các tham số GET đến dưới dạng được mã hóa UTF-8. Kết quả là khi người dùng viết nội dung sau vào thanh địa chỉ của trình duyệt:

 https://localhost:8443/ID/Users?action=search&name=*ж*

ký tự ж được xử lý dưới dạng UTF-8 và được mã hóa (thường là bởi trình duyệt trước khi đến máy chủ) là % D0% B6 .

Yêu cầu POST không bị ảnh hưởng bởi điều này.

CharsetFilter

Sau đó, đã đến lúc buộc ứng dụng web java xử lý tất cả các yêu cầu và phản hồi dưới dạng mã hóa UTF-8. Điều này yêu cầu chúng tôi xác định một bộ lọc bộ ký tự như sau:

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

Bộ lọc này đảm bảo rằng nếu trình duyệt chưa đặt mã hóa được sử dụng trong yêu cầu, thì mã đó được đặt thành UTF-8.

Điều khác được thực hiện bởi bộ lọc này là đặt mã hóa phản hồi mặc định tức là. mã hóa trong đó html được trả về / bất kỳ là gì. Giải pháp thay thế là đặt mã hóa phản hồi, v.v. trong mỗi bộ điều khiển của ứng dụng.

Bộ lọc này phải được thêm vào web.xml hoặc trình mô tả triển khai của ứng dụng web:

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

Hướng dẫn tạo bộ lọc này có tại wiki tomcat ( http://wiki.apache.org/tomcat/Tomcat/UTF-8 )

Mã hóa trang JSP

Trong web.xml của bạn , thêm phần sau:

<jsp-config>
    <jsp-property-group>
        <url-pattern>*.jsp</url-pattern>
        <page-encoding>UTF-8</page-encoding>
    </jsp-property-group>
</jsp-config>

Ngoài ra, tất cả các trang JSP của ứng dụng web sẽ cần có phần sau ở đầu chúng:

 <%@page pageEncoding="UTF-8" contentType="text/html; charset=UTF-8"%>

Nếu một số loại bố cục với các đoạn JSP khác nhau được sử dụng, thì điều này là cần thiết trong tất cả trong số họ.

Thẻ meta HTML

Mã hóa trang JSP yêu cầu JVM xử lý các ký tự trong trang JSP theo cách mã hóa chính xác.

Điều này được thực hiện với phần sau ở đầu mỗi trang xhtml được tạo bởi ứng dụng web:

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

Kết nối JDBC

Khi sử dụng db, nó phải được xác định rằng kết nối sử dụng mã hóa UTF-8. Điều này được thực hiện trong context.xml hoặc bất cứ nơi nào kết nối JDBC được ngắt như sau:

      <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"
    />

Cơ sở dữ liệu MySQL và bảng

Cơ sở dữ liệu được sử dụng phải sử dụng mã hóa UTF-8. Điều này đạt được bằng cách tạo cơ sở dữ liệu như sau:

   CREATE DATABASE `ID_development` 
   /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_swedish_ci */;

Sau đó, tất cả các bảng cũng cần phải ở dạng 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;

Phần quan trọng là CHARSET =utf8 .

Cấu hình máy chủ MySQL

MySQL serveri cũng phải được định cấu hình. Thông thường, điều này được thực hiện trong Windows bằng cách sửa đổi my.ini -tệp và trong Linux bằng cách định cấu hình my.cnf -file.Trong các tệp đó, cần xác định rằng tất cả các máy khách được kết nối với máy chủ sử dụng utf8 làm bộ ký tự mặc định và bộ ký tự mặc định được máy chủ sử dụng cũng là utf8.

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

   [mysql]
   default-character-set=utf8

Các thủ tục và hàm Mysql

Chúng cũng cần phải xác định bộ ký tự. Ví dụ:

   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 ;

Yêu cầu GET:latin1 và UTF-8

Nếu và khi nó được xác định trong server.xml của tomcat mà các tham số yêu cầu GET được mã hóa trong UTF-8, thì các yêu cầu GET sau sẽ được xử lý đúng cách:

   https://localhost:8443/ID/Users?action=search&name=Petteri
   https://localhost:8443/ID/Users?action=search&name=ж

Vì các ký tự ASCII được mã hóa theo cùng một cách cả với latin1 và UTF-8, chuỗi "Petteri" được xử lý chính xác.

Ký tự Cyrillic ж hoàn toàn không được hiểu trong tiếng latin1. Vì Tomcat được hướng dẫn xử lý các tham số yêu cầu dưới dạng UTF-8 nên nó mã hóa ký tự đó một cách chính xác thành % D0% B6 .

Nếu và khi các trình duyệt được hướng dẫn đọc các trang bằng mã hóa UTF-8 (với tiêu đề yêu cầu và thẻ meta html), thì ít nhất Firefox 2/3 và các trình duyệt khác từ giai đoạn này đều mã hóa ký tự dưới dạng % D0% B6 .

Kết quả cuối cùng là tất cả người dùng có tên "Petteri" được tìm thấy và tất cả người dùng có tên "ж" đều được tìm thấy.

Nhưng còn äåö thì sao?

Đặc tả HTTP xác định rằng các URL mặc định được mã hóa dưới dạng latin1. Điều này dẫn đến firefox2, firefox3, v.v. mã hóa như sau

    https://localhost:8443/ID/Users?action=search&name=*Päivi*

sang phiên bản được mã hóa

    https://localhost:8443/ID/Users?action=search&name=*P%E4ivi*

Trong tiếng latin1, ký tự ä được mã hóa thành % E4 . Mặc dù trang / yêu cầu / mọi thứ được xác định để sử dụng UTF-8 . Phiên bản được mã hóa UTF-8 của ä là % C3% A4

Kết quả của việc này là ứng dụng web hoàn toàn không thể xử lý chính xác các tham số yêu cầu từ các yêu cầu GET vì một số ký tự được mã hóa bằng latin1 và các ký tự khác trong UTF-8. Lưu ý:Yêu cầu POST hoạt động khi trình duyệt mã hóa tất cả các tham số yêu cầu từ các biểu mẫu hoàn toàn bằng UTF-8 nếu trang được xác định là UTF-8

Nội dung cần đọc

Rất cảm ơn những người viết sau đây đã đưa ra câu trả lời cho vấn đề của tôi:

  • 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.uto Toronto.ca/webdocs/HTMLdocs/NewHTML/iso_table.html
  • http://www.utf8-chartable.de/

Lưu ý quan trọng

hỗ trợ Mặt phẳng đa ngôn ngữ cơ bản sử dụng ký tự UTF-8 3 byte. Nếu bạn cần phải vượt ra ngoài điều đó (các bảng chữ cái nhất định yêu cầu nhiều hơn 3 byte UTF-8), thì bạn cần phải sử dụng phiên bản VARBINARY loại cột hoặc sử dụng utf8mb4 bộ ký tự (yêu cầu MySQL 5.5.3 trở lên). Chỉ cần lưu ý rằng sử dụng utf8 bộ ký tự trong MySQL sẽ không hoạt động 100% thời gian.

Tomcat với Apache

Một điều nữa Nếu bạn đang sử dụng trình kết nối Apache + Tomcat + mod_JK thì bạn cũng cần thực hiện các thay đổi sau:

  1. Thêm URIEncoding ="UTF-8" vào tệp tomcat server.xml cho trình kết nối 8009, nó được trình kết nối mod_JK sử dụng.
  2. Chuyển thư mục apache của bạn, tức là / etc / httpd / conf và thêm AddDefaultCharset utf-8 trong tệp httpd.conf . Lưu ý: Đầu tiên hãy kiểm tra xem nó có tồn tại hay không. Nếu tồn tại, bạn có thể cập nhật nó bằng dòng này. Bạn cũng có thể thêm dòng này ở dưới cùng.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Làm cách nào để làm trễ các cột trong MySQL?

  2. Làm cách nào để thay đổi thời gian chờ kết nối Mysql mặc định khi kết nối qua python?

  3. COUNT (*) từ nhiều bảng trong MySQL

  4. Cách sao chép bảng trong MySQL

  5. Chuyển đổi dấu thời gian thành ngày tháng trong truy vấn MySQL