หากเพื่อนโปรแกรมเมอร์คนใดบอกว่าเขาไม่เคยพบปัญหาของรหัสภาษาจีนที่อ่านไม่ออกฉันไม่อยากเชื่อเลย วันนี้เมื่อฉันตอบกลับอย่างชาญฉลาดไปยังบัญชีการสมัครสมาชิก WeChat ฉันกระโดดเข้าไปในหลุมไฟของรหัสภาษาจีนที่อ่านไม่ออกด้วยวิธีที่สับสน เมื่อฉันแก้ไขปัญหาครั้งแรกฉันให้กำลังใจและลืมความเจ็บปวดที่เธอเคยนำมาให้ฉัน
1. คำอธิบายปัญหา
เมื่อเห็นว่ารหัสที่อ่านไม่ออกในกรอบสีแดงนั้นกระตุ้นให้ฉัน แต่ฉันก็ทำอะไรไม่ถูก มันแย่มาก
2. หาทางออก
เมื่อเผชิญกับปัญหาคุณสามารถบังคับตัวเองให้แก้ด้วยมีดได้เท่านั้น คุณทำอะไรได้บ้าง?
ก่อนอื่นเราต้องเข้าใจกลไกของการตอบอย่างชาญฉลาด WeChat และวาดภาพดังนี้:
ปล. โปรดขออภัยที่ไม่ใช้เครื่องมือได้ดี
ถัดไปให้มุ่งเน้นไปที่ประเด็นสำคัญและดูว่ารหัสที่อ่านไม่ออกมีความสำคัญอย่างไร
1. คอนโทรลเลอร์กลับไปยังผู้ใช้
Response.SetheAder ("เนื้อหาประเภท", "text/html; charset = utf-8"); // การเข้ารหัสเบราว์เซอร์การตอบสนองของเบราว์เซอร์. getOutputStream () เขียน (result.get.getBytes ());เพียงแค่รหัสนี้วิธีการเข้ารหัสของการระบุการตอบสนองคือ UTF-8 มันมีเหตุผลที่ปัญหาที่อ่านไม่ออกควรดีขึ้น แต่ผลลัพธ์ก็ยังไม่
2. Toxml ของ Jaxb
สตริงสาธารณะ ToxML (Object OBJ) {String result = NULL; ลอง {jaxbcontext context = jaxbcontext.newinstance (obj.getClass ()); Marshaller M = context.createMarshaller (); M.SetProperty (Marshaller.jaxb_encoding, "UTF-8"); M.SetProperty (marshaller.jaxb_formatted_output, true); M.SetProperty (marshaller.jaxb_fragment, true); // ลบส่วนหัวข้อความ ByteArrayOutputStream OS = ใหม่ byteArrayOutputStream (); XMLSerializer serializer = getXMLSerializer (OS); M.Marshal (OBJ, serializer.ascontenthandler ()); ผลลัพธ์ = os.toString ("UTF-8"); } catch (exception e) {e.printstacktrace (); } logger.info ("ข้อความตอบกลับ:" + ผลลัพธ์); ผลตอบแทนผลลัพธ์;} ส่วนตัว XMLSerializer getXMLSerializer (OutputStream OS) {outputFormat ของ = new OutputFormat (); formatcDatatag (); ของ. setCdataelements (cdatanode); ของ. setPreservespace (จริง); ของ. setindenting (จริง); ของ. setOmitxmldeclaration (จริง); ของ. setencoding ("UTF-8"); XMLSerializer serializer = ใหม่ XMLSerializer (OF); serializer.setOutputByTestream (OS); คืนอนุกรม;} นี่คือสามประเด็นสำคัญ:
1. M.SetProperty (Marshaller.jaxb_encoding, "UTF-8");
2. getXMLSerializer (OS)
3. OS.ToString ("UTF-8");
คุณจะเห็นว่าสามสถานที่ข้างต้นเกี่ยวข้องกับการแปลงรหัส ในสถานที่แรกตั้งค่าการเข้ารหัส Marshaller; ในสถานที่ที่สองตั้งค่าการเข้ารหัส XMLSerializer ทั้งหมด ในสถานที่ที่สามตั้งค่าการเข้ารหัสสตริงของ ByteArrayOutputStream ที่ส่งคืน ทั้งสามเป็นสิ่งที่ขาดไม่ได้
เวลานี้ควรแก้ไขปัญหา แต่วิธีการแก้ปัญหายังคงเป็นภาษาจีนที่อ่านไม่ออก แล้วฉันควรทำอย่างไร?
3. สภาพแวดล้อมการส่งออกของ Tomcat ผิด
ในการตอบสนองต่อจุดนี้มีคนออนไลน์ให้ทางออกดังกล่าว
ตั้งค่า java_opts =% java_opts%% logging_manager% -dfile.encoding = utf -8
หลังจากตั้งค่าแล้วการรีสตาร์ท Tomcat ปัญหาคือมันสามารถแก้ไขได้ แต่ผลข้างเคียงคือ Tomcat ทั้งหมดรันผลลัพธ์บนเซิร์ฟเวอร์ (หน้าต่าง CMD ของ Tomcat) ถูกอ่านออกมาเสมอและฉันคิดว่าโซลูชันนี้ไม่แนะนำ
เพิ่มรหัสต่อไปนี้ในสงครามที่กำลังดำเนินอยู่
System.getProperty ("file.encoding");คุณจะประหลาดใจที่พบว่าสภาพแวดล้อมการทำงานของ Tomcat (Window Server 2008) กลายเป็น GBK ฉันสงสัยว่าคุณไม่แปลกใจ ฉันกลัวทำไมมันถึงไม่ใช่ UTF-8? หากเป็น GBK ฉันจะเพิ่มหน้า UTF-8 เพิ่มเติมในสองขั้นตอนข้างต้นและฉันไม่เข้าใจ
3. แก้ปัญหา
ด้วยประสบการณ์ข้างต้นเราแก้ไขรหัส WeChat4J ต่อไปนี้ซึ่งส่วนใหญ่เป็นจุดที่สอง
สตริงสาธารณะ ToxML (Object OBJ) {String result = NULL; ลอง {jaxbcontext context = jaxbcontext.newinstance (obj.getClass ()); Marshaller M = context.createMarshaller (); String encoding = config.instance (). getJaxB_encoding (); logger.debug ("การเข้ารหัส ToxML" + การเข้ารหัส + "ไฟล์ระบบการเข้ารหัส" + System.getProperty ("file.encoding")); M.SetProperty (Marshaller.jaxb_encoding, การเข้ารหัส); M.SetProperty (marshaller.jaxb_formatted_output, true); M.SetProperty (marshaller.jaxb_fragment, true); // ลบส่วนหัวข้อความ ByteArrayOutputStream OS = ใหม่ byteArrayOutputStream (); XMLSerializer serializer = getXMLSerializer (OS); M.Marshal (OBJ, serializer.ascontenthandler ()); ผลลัพธ์ = os.toString (การเข้ารหัส); } catch (exception e) {e.printstacktrace (); } logger.info ("ข้อความตอบกลับ:" + ผลลัพธ์); ผลตอบแทนผลลัพธ์;} ส่วนตัว XMLSerializer getXMLSerializer (OutputStream OS) {outputFormat ของ = new OutputFormat (); formatcDatatag (); ของ. setCdataelements (cdatanode); ของ. setPreservespace (จริง); ของ. setindenting (จริง); ของ. setOmitxmldeclaration (จริง); String encoding = config.instance (). getJaxB_encoding (); ของ. setencoding (การเข้ารหัส); XMLSerializer serializer = ใหม่ XMLSerializer (OF); serializer.setOutputByTestream (OS); คืนอนุกรม;}ในบรรดาสองวิธีนี้เราเพิ่มวิธีการเข้ารหัสที่กำหนดค่าได้เพื่อตั้งค่า GBK โดยอัตโนมัติ (GBK ถูกกำหนดค่าบนเซิร์ฟเวอร์ของฉัน), GB2312 และ UTF-8
ด้วยวิธีนี้คุณจะพบว่าการส่งออกพื้นหลังของ WeChat4J ไม่ได้อยู่ในภาษาจีนที่อ่านไม่ออกอีกต่อไป แต่ข้อมูลที่ส่งกลับไปยังผู้ใช้นั้นยุ่งมากขึ้น
จะทำอย่างไร? ฉันเป็นโปรแกรมเมอร์และฉันต้องการสาบานคำสาบานสองสามคำ แต่อย่ากลัว เนื่องจากบันทึกการบันทึกของ WeChat4J ไม่ได้อยู่ในภาษาจีนที่อ่านไม่ออกอีกต่อไปจึงสามารถกล่าวได้ว่ามีปัญหาอื่นในขั้นตอนแรก
ปรับ
Response.SetheAder ("เนื้อหาประเภท", "ข้อความ/html; charset = utf-8"); // การเข้ารหัสเบราว์เซอร์ตอบสนองการตอบสนองของเบราว์เซอร์. getOutputStream () เขียน (result.getBytes ("UTF-8")); โปรดทราบว่าสิ่งนี้ไม่สามารถเป็น GBK ได้ แต่สามารถเป็น UTF-8 เท่านั้น ฉันบอกว่าฉันไม่รู้ว่าทำไมผู้จัดการผลิตภัณฑ์ของ WeChat ให้คำอธิบาย
ประเด็นสำคัญคือ JAXB และการตอบสนองร่วมกันแก้ไขรหัส WECHAT4J ภาษาจีนที่อ่านไม่ออกได้รับการประกาศดังนี้:
wechatcontroller.java เป็น URL ที่คุณจัดสรรให้กับแพลตฟอร์มการพัฒนาสาธารณะ WeChat การตอบสนองจะถูกปรับดังนี้
Response.SetheAder ("เนื้อหาประเภท", "ข้อความ/html; charset = utf-8"); // การเข้ารหัสเบราว์เซอร์ตอบสนองการตอบสนองของเบราว์เซอร์. getOutputStream () เขียน (result.getBytes ("UTF-8"));jaxbparser.java ของ weChat4J ปรับ TOXML (Object OBJ) และ GetXMLSerializer (OutputStream OS) ตามลำดับ:
สตริงสาธารณะ ToxML (Object OBJ) {String result = NULL; ลอง {jaxbcontext context = jaxbcontext.newinstance (obj.getClass ()); Marshaller M = context.createMarshaller (); String encoding = config.instance (). getjaxb_encoding (); // gbk logger.debug ("การเข้ารหัส toxml" + การเข้ารหัส + "system file.encoding" + system.getProperty ("file.encoding")); M.SetProperty (Marshaller.jaxb_encoding, การเข้ารหัส); M.SetProperty (marshaller.jaxb_formatted_output, true); M.SetProperty (marshaller.jaxb_fragment, true); // ลบส่วนหัวข้อความ ByteArrayOutputStream OS = ใหม่ byteArrayOutputStream (); XMLSerializer serializer = getXMLSerializer (OS); M.Marshal (OBJ, serializer.ascontenthandler ()); ผลลัพธ์ = os.toString (การเข้ารหัส); } catch (exception e) {e.printstacktrace (); } logger.info ("ข้อความตอบกลับ:" + ผลลัพธ์); ผลตอบแทนผลลัพธ์;} ส่วนตัว XMLSerializer getXMLSerializer (OutputStream OS) {outputFormat ของ = new OutputFormat (); formatcDatatag (); ของ. setCdataelements (cdatanode); ของ. setPreservespace (จริง); ของ. setindenting (จริง); ของ. setOmitxmldeclaration (จริง); String encoding = config.instance (). getJaxB_encoding (); // gbk ของ. setEncoding (การเข้ารหัส); XMLSerializer serializer = ใหม่ XMLSerializer (OF); serializer.setOutputByTestream (OS); คืนอนุกรม;} โอเคทุกอย่างเป็นไปด้วยดี
ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่ามันจะเป็นประโยชน์ต่อการเรียนรู้ของทุกคนและฉันหวังว่าทุกคนจะสนับสนุน wulin.com มากขึ้น