كثيرًا ما أرى أشخاصًا يسألونني في منتديات المناقشة عما يجب فعله إذا كانت الأحرف الصينية المعروضة في JSP مشوهة، ولماذا يكون الإدخال الصيني من قبل المستخدم الذي أحصل عليه من خلال الطلب مشوهًا، ولماذا تكون الأحرف الصينية التي أكتبها إلى قاعدة البيانات مشوهة، وغير ذلك أسئلة حول الأحرف الصينية مشوهة.
في الواقع، هذه المشكلة بسيطة جدًا، بغض النظر عما إذا كانت أحرفًا صينية أو يابانية أو لغة أخرى مزدوجة البايت، فسوف نتعامل معها على أنها UTF-8.
(1) النص مزدوج البايت في الطلب جيد الآن، سنستخدم ترميز UTF-8 في التطبيق بأكمله. إن سبب اختيار UTF-8 ليس فقط للأسباب المذكورة أعلاه UTF-8 أو أعلى، لذلك يجب أن نكون على حق في اختيار UTF-8^_^
نقوم أولاً بحفظ ملفات .java و.jsp بترميز UTF-8. لا يهم إذا لم يتم حفظ الملفات السابقة بترميز UTF-8، ولكن يوصى بحفظ جميع الملفات المستقبلية بترميز UTF-8.
واكتب بصيغة .jsp: < %@page contentType="text/html; charset=UTF-8"%> بدلاً من < %@page contentType="text/html; charset=UTF-8"%>
ثم قم بإضافة الفقرة التالية إلى web.xml:
<تطبيق الويب>
...
<فلتر>
<filter-name>تعيين ترميز الأحرف</filter-name>
<filter-class>com.redv.projects.eduadmin.util.filters.SetCharacterEncodingFilter</filter-class>
<init-param>
<param-name>التشفير</param-name>
<param-value>UTF-8</param-value>
</init-param>
</فلتر>
<تعيين عامل التصفية>
<filter-name>تعيين ترميز الأحرف</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
...
</web-app>
رمز com.redv.projects.eduadmin.util.filters.SetCharacterEncodingFilter هو كما يلي:
package com.redv.projects.eduadmin.util.filters;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.UnavailableException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
الفئة العامة SetCharacterEncodingFilter
ينفذ عامل التصفية {
ترميز السلسلة المحمي = فارغ؛
protected FilterConfig filterConfig = null;
protected
void Destroy() {
this.encoding = null;
this.filterConfig = null
}
public void doFilter(ServletRequest request, ServletResponse Response,
سلسلة FilterChain) تطرح IOException، ServletException {
// تحديد مشروط وتعيين ترميز الأحرف المراد استخدامه
إذا (تجاهل || (request.getCharacterEncoding() == null)) {
ترميز السلسلة = SelectEncoding(request);
إذا (الترميز! = فارغ) {
request.setCharacterEncoding(encoding); // هذا هو ما يعمل، هاها: يتجاوز اسم ترميز الأحرف المستخدم في نص هذا الطلب، ويجب استدعاء هذه الطريقة قبل قراءة معلمات الطلب أو قراءة الإدخال باستخدام getReader(. ).
}
}
// تمرير التحكم إلى الفلتر التالي
chain.doFilter(request, Response);
}
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
this.encoding = filterConfig.getInitParameter("encoding");
قيمة السلسلة = filterConfig.getInitParameter("ignore");
إذا (القيمة == فارغة) {
this.ignore = true;
}
وإلا إذا (value.equalsIgnoreCase("true")) {
this.ignore = true;
}
وإلا إذا (value.equalsIgnoreCase("yes")) {
this.ignore = true;
}
آخر {
this.ignore = false;
}
}
protected String SelectEncoding(ServletRequest request) {
return (this.encoding);
}
}
بهذه الطريقة، يتم تشفير طلبنا في UTT-8، ويمكننا استخدامه في برنامج JSP: request.getParameter("myKey" ) يمكنك الحصول مباشرة على السلسلة المشفرة UTF-8، بدلاً من ذلك: new String(request.getParameter("myKey").getBytes("ISO-8859-1"), "GBK") لحل تلك الأحرف المشوهة. http://www.devdao.com/
(2) تتم معالجة النص مزدوج البايت بواسطة قاعدة البيانات http://www.upas.org/java/DatabaseEncodingProblemSolution/
مشكلة أخرى هي مشكلة الكتابة إلى قاعدة البيانات. نحن نعلم أنه عند استخدام mysql، يمكننا استخدام عنوان URL هذا للتعامل مع مشكلة ترميز الأحرف الصينية: jdbc:mysql://localhost:3306/upas?useUnicode=true&characterEncoding=gb2312,
فماذا يجب أن نفعل بشأن تلك الأشياء التي لا يمكننا حلها مثل الخلية؟ هل يجب أن نكتب هكذا في كل مرة:
import java.sql.*;
Class.forName("org.gjt.mm.mysql.Driver");
اتصال يخدع = فارغ؛
PreparedStatement pstmt = null;
ResultSet rs = null;
يحاول {
con = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "");
pstmt = con.prepareStatement("SELECT f3, f4 FROM tbl1 WHERE f1 = ? AND f2 = ؟");
pstmt.setString(1, new String(f1.getBytes("GBK"), "ISO-8859-1");
pstmt.setString(2, new String(f2.getBytes("GBK"), "ISO-8859-1");
rs = pstmt.executeQuery();
سلسلة f3، f4؛
بينما (rs.next()) {
f3 = new String(rs.getString(1).getBytes("ISO-8859-1"), "GBK");
f4 = new String(rs.getString(2).getBytes("ISO-8859-1"), "GBK");
}
}
أخيراً {
// إغلاق الموارد
...
}
في الحقيقة، يمكننا كتابتها هكذا:
استيراد java.sql.*;
import com.redv.sql.encoding.*;
Class.forName("org.gjt.mm.mysql.Driver");
اتصال يخدع = فارغ؛
PreparedStatement pstmt = null;
ResultSet rs = null;
يحاول {
con = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "");
// تولي مثيل اتصال قاعدة البيانات
الترميز المنطقي = صحيح؛
EncodingConnection codingConnection = new EncodingConnection(con, coding, "ISO-8859-1", "GBK");
// احصل على مثيل اتصال قاعدة البيانات بعد الاستيلاء عليه، استخدم con مباشرة في المستقبل، وهو بالفعل مثيل تم إعادة تجميعه بواسطة EncodingConnection.
con = codingConnection.getConnection();
pstmt = con.prepareStatement("SELECT f3, f4 FROM tbl1 WHERE f1 = ? AND f2 = ؟");
pstmt.setString(1, f1);
pstmt.setString(2, f2);
rs = pstmt.executeQuery();
سلسلة f3، f4؛
بينما (rs.next()) {
f3 = rs.getString(1);
f4 = rs.getString(2);
}
}
أخيراً {
// إغلاق الموارد
...
}
دعونا نرى، ماذا عن الأمر، نحتاج فقط إلى تعديله قليلاً حيث نحصل على اتصال قاعدة البيانات، يمكننا حتى حفظه كمعلمة في الخصائص وتغيير القيمة المنطقية للتشفير لتعيين ما إذا كان سيتم استخدام تحويل الترميز التلقائي. غالبًا ما يمكننا استخدام فئة Database لتغليف getConnection الذي يحصل على اتصال قاعدة البيانات، حتى نتمكن من الحصول على اتصال قاعدة البيانات من javax.sql.DataSource. في هذا الوقت، نحتاج فقط إلى تعديل فئة قاعدة البيانات الخاصة بنا، بدلاً من البحث عن جميع الأماكن التي يتم فيها استخدام rs.setString() و rs.getString() لإضافة كود تحويل التشفير الخاص بنا. حتى عندما نستخدم عبارة con.createStatment()، فلا توجد مشكلة حتى لو كانت عبارة SQL الخاصة بنا تحتوي على أحرف صينية أو أحرف أخرى مزدوجة البايت:
حدد الاسم والجنس من جدول الطلاب حيث الفصل مثل '%computer%'