Debug và khắc phục lỗi hiển thị ký tự Unicode của ứng dụng Web

Công Nghệ
Debug và khắc phục lỗi hiển thị ký tự Unicode của ứng dụng Web
Bài viết được sự cho phép của BBT Tạp chí Lập trình Tác giả: Nguyễn Bình Sơn Bài viết này ngầm định rằng bạn biết “bảng mã” nghĩa là gì, và bạn quen thuộc với các thành phần của mô hình ứng dụng web cũng như mô hình trình diễn...

Bài viết được sự cho phép của BBT Tạp chí Lập trình

Tác giả: Nguyễn Bình Sơn

Bài viết này ngầm định rằng bạn biết “bảng mã” nghĩa là gì, và bạn quen thuộc với các thành phần của mô hình ứng dụng web cũng như mô hình trình diễn MVC. Mặc dù mã ở đây được trình bày dưới dạng thức của ngôn ngữ Java, framework Spring MVC và database MySQL, các vấn đề được nhắc đến là chung, các khái niệm được nhắc đến là phổ biến, và các cách giải quyết là tổng quát. Hãy cùng tìm hiểu về Debug và khắc phục lỗi hiển thị ký tự Unicode của ứng dụng Web nhé!

”]

Model mang dữ liệu Unicode nhưng View thì không

Bạn có model như thế này.

Nhưng bạn nhận được kết quả như thế này:

Là vì View của bạn có nội dung như thế này:

CREATE DATABASE IF NOT EXISTS cms CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

Bạn cần làm cho view engine render cho bạn một view mà trong đó các ký tự unicode của template và model được bảo toàn. Ví dụ sau đây là cấu hình cho view engine Thymeleaf.

@Bean
public ViewResolver viewResolver() {
    // ...
    viewResolver.setCharacterEncoding("UTF-8");
    return viewResolver;
}

Template mang ký tự Unicode nhưng View thì không

Bạn có view template như thế này:

<tr>
  <td>Tên</td>
  <td>
    <input type="text" name="name" th:value="${customer.name}">
  </td>
</tr>
<tr>
  <td>Email</td>
  <td>
    <input type="text" name="email" th:value="${customer.email}">
  </td>
</tr>
<tr>
  <td>Địa chỉ</td>
  <td>
    <input type="text" name="address" th:value="${customer.address}">
  </td>
</tr>

Nhưng bạn nhận được view như thế này:

Nếu bạn đã xử lý vấn đề encoding trong lúc render như ở trên rồi, thì có thể vấn đề là do template resorver đã dùng một encoding khác để đọc tài liệu template. Hãy cấu hình lại cho cả template resolver nữa.

@Bean
public ITemplateResolver templateResolver() {
    // ...
    templateResolver.setCharacterEncoding("UTF-8");
    return templateResolver;
}

Không thể chuyển tải ký tự Unicode qua tầng giao vận

Giả sử cần submit form sau:

Tầng giao vận TCP/IP không quan tâm với bảng mã, nó đơn giản và vận chuyển gói tin, từng byte một. Phần lớn web server, trừ khi là web server do bạn tự viết, decode các bytes này để có các parametter theo lối như thể rằng các bytes đó trước kia là ký tự của bảng mã ISO-8859–1. Nếu bạn nhìn các ký tự đã được decode ra dưới con mắt của bảng mã UTF-8 (trớ trêu rằng, phần lớn các ngôn ngữ lập trình làm như thế), bạn sẽ nhận được kết quả không mong muốn.

Cách xử lý luôn luôn là encode chuỗi ký tự ngược lại thành dòng bytes (theo bảng mã ISO-8859–1, tất nhiên), và sau đó decode lại theo bảng mã UTF-8. Cho dù là thủ công như sau:

public String createCustomer(Customer customer) {
    try {
        byte[] bytes = customer.getName().getBytes("ISO-8859-1");
        String decodedName = new String(bytes, "UTF-8");
        customer.setName(decodedName);
        customerService.save(customer);
        return "redirect:/customers";
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
        return "500";
    }
}

… hay tự động, bằng cách sử dụng filter, như sau chẳng hạn:

public class AppInit extends AbstractAnnotationConfigDispatcherServletInitializer {
    // ...    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        FilterRegistration.Dynamic filterRegistration =
            servletContext.addFilter("endcoding-filter", new CharacterEncodingFilter());
        filterRegistration.setInitParameter("encoding", "UTF-8");
        filterRegistration.setInitParameter("forceEncoding", "true");
        
        //make sure encodingFilter is matched most first, by "false" arg
        filterRegistration.addMappingForUrlPatterns(null, false, "/*");
        
        super.onStartup(servletContext);
    }
}

Entity mang thông tin Unicode, vào đến Database thì mất dấu

Bạn có form như thế này:

Entity ngon nghẻ như thế này:

Vào tới database thì loạn cào cào hết cả:

Hầu hết các client của các dbms, khi kết nối tới dbms server, đều chọn mặc định một bảng mã để làm việc với nhau. “Mặc định” này đôi khi là một giá trị cố định, đôi khi là lấy dynamic. Dù là trường hợp nào đi chăng nữa, đôi khi charset đó hoàn toàn khác với charset được dùng cho Schema/Table/Column. Nghĩa là “anh nói tiếng của anh, nhưng tôi hiểu theo tiếng của tôi”.

Cách xử lý luôn là cố định lại bảng mã dùng trong cuộc nói chuyện giữa client và dbms server:

CREATE DATABASE IF NOT EXISTS cms CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

Và đồng thời (điều này rất quan trọng), sử dụng cùng một bảng mã đó cho Schema/Table/Column:

CREATE DATABASE IF NOT EXISTS cms CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

Nếu database cùng với dữ liệu đã tồn tại, theo một bảng mã khác, cách xử lý luôn là sử dụng một kỹ thuật nào đó được dbms hỗ trợ để convert dữ liệu từ bảng mã cũ sang bảng mã mong muốn.

Bài viết gốc được đăng tải tại Tạp Chí Lập Trình

Có thể bạn quan tâm:

Xem thêm các  IT Jobs for Developer hấp dẫn tại Station D

Bài viết liên quan

Ngành IT: Làm việc “trên mây” kiếm nhiều tiền nhất hiện nay

Ngành IT: Làm việc “trên mây” kiếm nhiều tiền nhất hiện nay

Kết quả từ cuộc khảo sát đầu năm của Station D về lương bổng của lập trình viên cho thấy nhiều thay đổi đã và đang diễn ra trong ngành IT – cuộc khảo sát tập trung vào các câu hỏi về khối lượng công việc, triển vọng cũng như...

By stationd
Đâu chỉ mỗi Bitcoin, công nghệ Blockchain còn nhiều ứng dụng hơn thế!

Đâu chỉ mỗi Bitcoin, công nghệ Blockchain còn nhiều ứng dụng hơn thế!

Khi nhắc đến blockchain , lập tức mọi người thường nghĩ ngay đến các loại tiền mã hóa, chẳng hạn như bitcoin. Tuy nhiên, blockchain lại là công nghệ tạo ra tiền mã hóa nhưng bản thân công nghệ này không phải là tiền mã hóa như cách mà chúng...

By stationd
Mock phương thức static trong Unit Test sử dụng PowerMock

Mock phương thức static trong Unit Test sử dụng PowerMock

Bài viết được sự cho phép của tác giả Nguyễn Hữu Khanh Trong bài viết này, mình sẽ hướng dẫn các bạn Mock các phương thức static trong Unit Test các bạn nhé! Nếu bạn nào chưa biết về Mock trong Unit Test thì mình có thể nói sơ qua...

By stationd
Cảnh Báo Malware Giả Mạo Hợp Đồng Việc Làm: Tập Tin .EXE Nguy Hiểm Đội Lốt PDF/Word

Cảnh Báo Malware Giả Mạo Hợp Đồng Việc Làm: Tập Tin .EXE Nguy Hiểm Đội Lốt PDF/Word

Kẻ xấu đang lợi dụng nhu cầu tìm việc để phát tán phần mềm độc hại (malware) dưới dạng tệp 'hợp đồng' giả mạo. Hãy cảnh giác với những file có icon Word/PDF nhưng thực chất là .exe. Nếu mở, máy tính của bạn có thể bị đánh cắp toàn bộ thông tin cá nhân, cookie và mật khẩu.

By admin