Pengkodean & decoding
Melalui gambar berikut, kita dapat memahami di mana ada transkode di Javaweb:
Pengguna ingin server mengirim permintaan HTTP. Tempat -tempat di mana pengkodean adalah URL, cookie, dan parameter diperlukan. Setelah pengkodean, server menerima permintaan HTTP, mem -parsing permintaan HTTP, dan kemudian memecahkan kode URL, cookie, dan parameter. Selama pemrosesan logika bisnis server, mungkin perlu membaca database, file lokal, atau file lain dalam jaringan, dll., Dan proses ini memerlukan pengkodean dan decoding. Setelah pemrosesan selesai, server mengkodekan data dan mengirimkannya ke klien, dan browser menampilkannya ke pengguna setelah decoding. Ada banyak pengkodean dan decoding yang terlibat dalam seluruh proses ini, dan tempat yang paling mungkin untuk tampil kacau adalah proses berinteraksi dengan server dan klien.
Seluruh proses di atas dapat diringkas sebagai berikut: Data yang dikodekan halaman diteruskan ke server, dan server memecahkan kode data yang diperoleh, dan setelah beberapa pemrosesan logika bisnis, hasil akhir dikodekan dan diproses, dan klien mendekode dan menampilkannya kepada pengguna. Jadi di bawah ini saya akan meminta penjelasan tentang pengkodean dan decoding Javaweb.
Jika klien ingin server mengirim permintaan, itu akan melewati empat situasi:
1. Akses langsung dengan URL.
2. Tautan halaman.
3. Formulir Dapatkan Pengajuan
4. Formulir Posting Formulir
Metode URL: Untuk URL, jika semua URL dalam bahasa Inggris, tidak ada masalah. Jika ada orang Cina, pengkodean akan terlibat. Bagaimana cara mengkode? Aturan apa yang ingin Anda kodekan? Jadi bagaimana cara memecahkan kode? Jawabannya akan dijawab satu per satu di bawah ini! Pertama -tama lihat komponen URL:
Dalam URL ini, browser akan mengkodekan jalur dan parameter. Untuk lebih menjelaskan proses pengkodean, gunakan URL berikut
http://127.0.0.1:8080/perbank/i am cm? name = i am cm
Masukkan alamat di atas ke dalam kotak input URL browser. Dengan melihat informasi header pesan HTTP, kita dapat melihat bagaimana browser mengkodekannya. Berikut adalah kondisi pengkodean tiga browser:
Anda dapat melihat bahwa penyandian "I Am" oleh browser utama adalah sebagai berikut:
bagian jalur | String kueri | |
Firefox | E6 88 91 E6 98 AF | E6 88 91 E6 98 AF |
Chrome | E6 88 91 E6 98 AF | E6 88 91 E6 98 AF |
YAITU | E6 88 91 E6 98 AF | CE D2 CA C7 |
void converturi yang dilindungi (MessageBytes URI, permintaan permintaan) melempar Exception {bytechunk bc = uri.getByTechunk (); int panjang = bc.getLength (); Charchunk cc = uri.getCharchunk (); cc.alokasi (panjang, -1); String enc = connector.geturiencoding (); // Dapatkan set decoding uri if (enc! = Null) {b2cconverter conv = request.geturiconverter (); coba {if (conv == null) {conv = b2cconverter baru (ENC); request.seturiconverter (conv); }} catch (ioException e) {...} if (conv! = null) {coba {conv.convert (bc, cc, cc.getBuffer (). length - cc.getend ()); uri.setchars (cc.getBuffer (), cc.getStart (), cc.getLength ()); kembali; } catch (ioException e) {...}}} // Pengkodean default: byte konversi cepat [] bbuf = bc.getBuffer (); char [] cbuf = cc.getBuffer (); int start = bc.getStart (); untuk (int i = 0; i <panjang; i ++) {cbuf [i] = (char) (bbuf [i+start] & 0xff); } uri.setchars (cbuf, 0, panjang); } Dari kode di atas, kita dapat melihat bahwa operasi decoding URI adalah untuk terlebih dahulu mendapatkan set decoding konektor, yang dikonfigurasi di server.xml
<Connector uriencoding = "UTF-8" />
Jika tidak ditentukan, pengkodean default ISO-8859-1 akan digunakan untuk parsing.
Untuk bagian string kueri, kami tahu bahwa apakah kami mengirimkannya melalui GET atau POST, semua parameter disimpan dalam parameter, dan kemudian kami menggunakan permintaan.getParameter, pekerjaan decoding dilakukan ketika metode GetParameter disebut pertama kali. Di dalam metode getParameter, ia memanggil metode parseparameters dari org.apache.catalina.connector.request, yang akan memecahkan kode parameter yang diteruskan. Kode berikut hanyalah bagian dari metode parseparameters:
// Dapatkan string encoding enc = getCharacterencoding (); // Dapatkan charset boolean yang didefinisikan dalam contentType useBodyEncodingForuri = connector.getuseBebodyencodingForuri (); if (enc! = null) {// Jika pengkodean tidak kosong, atur encoding ke ENC parameter.setencoding (ENC); if (useBodyEncodingForuri) {// Jika chartset diatur, atur decoding queryString ke chartset parameter.setQueryStringEncoding (ENC); }} else {// atur parameter metode decoding default.setencoding (org.apache.coyote.constants.default_character_encoding); if (useBodyEncodingForuri) {parameter.setQueryStringEncoding (org.apache.coyote.constants.default_character_encoding); }} Dari kode di atas, kita dapat melihat bahwa format decoding string kueri baik menggunakan chartset yang ditetapkan atau menggunakan format decoding default ISO-8859-1. Perhatikan bahwa grafik dalam pengaturan ini adalah contentType yang ditentukan dalam header HTTP. Pada saat yang sama, jika kita perlu mengubah atribut yang ditentukan agar berlaku, kita perlu mengonfigurasi yang berikut:
<Connector uriencoding = "UTF-8" UseBodyencodingForuri = "true"/>
Bagian di atas memperkenalkan proses pengkodean dan decoding dari permintaan URL secara rinci. Bahkan, bagi kami, lebih banyak cara kami adalah untuk menyerahkan dalam bentuk.
Bentuk mendapatkan
Kita tahu bahwa mengirimkan data melalui URL mudah menyebabkan masalah kode kacau, jadi kami cenderung menggunakan formulir formulir. Ketika pengguna mengklik mengirimkan formulir, browser akan mengatur lebih banyak kode untuk meneruskan data ke server. Data yang dikirimkan melalui GET disambung setelah URL (dapatkah itu dianggap sebagai string kueri ??), jadi Uriencoding berperan dalam proses decoding server Tomcat. Server Tomcat akan mendekode sesuai dengan set Uriencoding, dan jika tidak diatur, ia akan menggunakan ISO-8859-1 default untuk memecahkan kode. Jika kami mengatur pengkodean ke UTF-8 pada halaman, dan Uriencoding tidak atau tidak diatur, maka kode kacau akan terjadi ketika server mendekode. Pada saat ini, kita umumnya dapat memperoleh data yang benar melalui bentuk string baru (request.getParameter ("name"). GetBytes ("iso-8859-1"), "UTF-8").
Formulir Formulir
Untuk metode POST, pengkodean yang digunakan juga ditentukan oleh halaman, yaitu, ContentType. Ketika saya mengirimkan formulir dengan mengklik tombol Kirim pada halaman, browser pertama -tama akan menyandikan parameter formulir POST sesuai dengan format pengkodean charset dari OntentType dan mengirimkannya ke server. Di sisi server, ia juga menggunakan set karakter yang diatur dalam ContentType untuk mendekode (berbeda dari metode GET di sini). Ini berarti bahwa parameter yang diajukan melalui formulir pos umumnya tidak memiliki masalah kacau. Tentu saja, kita dapat mengatur set karakter yang mengkode diri: request.setcharacterencoding (charset).
Selesaikan masalah URL yang kacau dalam bahasa Cina
Kami terutama mengirim permintaan ke server melalui dua bentuk pengiriman: URL dan formulir. Bentuk bentuk umumnya tidak memiliki masalah kacau, dan masalah yang kacau terutama pada URL. Melalui pengenalan blog sebelumnya, kami tahu bahwa proses pengiriman pengkodean permintaan ke server oleh URL benar -benar terlalu membingungkan. Sistem operasi yang berbeda, browser yang berbeda, dan set karakter web yang berbeda akan menghasilkan hasil penyandian yang sama sekali berbeda. Bukankah terlalu menakutkan jika pemrogram ingin memperhitungkan setiap hasil? Apakah ada cara untuk memastikan bahwa klien hanya menggunakan satu metode pengkodean untuk mengeluarkan permintaan ke server?
memiliki! Di sini saya terutama memberikan metode berikut
Javascript
Menggunakan encoding JavaScript tidak memberi browser kesempatan untuk campur tangan. Setelah pengkodean, kirim permintaan ke server dan kemudian mendekodenya di server. Saat menguasai metode ini, kita membutuhkan tiga metode pengkodean JavaScript: Escape (), Encodeuri (), dan Encodeuricomponent ().
melarikan diri
String yang ditentukan dikodekan menggunakan set karakter SIO Latin. Semua karakter non-ASCII dikodekan sebagai string dalam format %xx, di mana xx mewakili angka heksadesimal yang sesuai dengan karakter dalam set karakter. Misalnya, pengkodean yang sesuai dengan format adalah %20. Metode decoding yang sesuai adalah Unescape ().
Faktanya, Escape () tidak dapat digunakan secara langsung untuk pengkodean URL, fungsi sebenarnya adalah mengembalikan nilai yang dikodekan unicode karakter. Misalnya, hasil "I Am CM" di atas adalah %U6211 %U662FCM, di mana pengkodean yang sesuai dari "I" adalah 6211, pengkodean "ya" adalah 662F, dan pengkodean "CM" adalah CM.
Perhatikan bahwa Escape () tidak dikodekan oleh "+". Tetapi kita tahu bahwa ketika halaman web mengirimkan formulir, jika ada spasi, itu akan dikonversi menjadi + karakter. Ketika server memproses data, tanda + akan diproses menjadi spasi. Karena itu, berhati -hatilah saat menggunakannya.
encodeuri
Pengkodean seluruh URL, menggunakan format UTF-8 untuk mengeluarkan string yang dikodekan. Namun, Encodeuri tidak akan menyandikan beberapa karakter khusus kecuali pengkodean ASCII, seperti :! @ # $ & * () =: /; ? + '.
Encodeuricomponent
Konversi string URI menjadi string format pelarian dalam format pengkodean UTF-8. Dibandingkan dengan Encodeuri, Encodeuricomponent akan lebih kuat, dan itu akan dikodekan untuk simbol (; / ?: @ & = + $, #) yang tidak dikodekan dalam Encodeuri (). Namun, komponen encodeuric hanya akan menyandikan komponen URL secara individual, dan tidak akan digunakan untuk menyandikan seluruh URL. Metode Decodeuricomponen Metode Decode yang sesuai.
Tentu saja, kami biasanya menggunakan Pihak Encodeuri untuk melakukan operasi pengkodean. Apa yang disebut pengkodean dan decoding JavaScript dua kali di latar belakang adalah menggunakan metode ini. Ada dua solusi untuk menyelesaikan masalah ini dalam JavaScript: satu transkode dan dua metode transkode.
Transcoding sekali
Transcoding JavaScript:
var url = '<s: nilai properti = "webpath" />/showmoBlieqrcode.servlet?name=i am cm'; window.location.href = encodeuri (url);
URL transcoded: http://127.0.0.1:8080/perbank/showmoBlieqrcode.servlet?name=%E6%88%91%E6%98%AFCM
Pemrosesan Backend:
Name string = request.getParameter ("name"); System.out.println ("Parameter masuk latar depan:" + Nama); name = string baru (name.getBytes ("iso-8859-1"), "UTF-8"); System.out.println ("Parameter Decoded:" + Name); Hasil output:
Parameter Masuk di Meja Depan: ?????? CM
Setelah parameter decoding: saya cm
Transkode sekunder
Javascript
var url = '<s: nilai properti = "webpath" />/showmoBlieqrcode.servlet?name=i am cm'; window.location.href = encodeuri (encodeuri (url));
URL transcoded: http://127.0.0.1:8080/perbank/showmoblieqrcode.servlet?name=%25e6%2588%2591%25E6%2598%25AFCM
Pemrosesan Backend:
Name string = request.getParameter ("name"); System.out.println ("Parameter masuk latar depan:" + Nama); name = urldecoder.decode (name, "UTF-8"); System.out.println ("Parameter Decoded:" + Name); Hasil output:
Parameter masuk front-end: E68891E698AFCM
Setelah parameter decoding: saya cm
menyaring
Menggunakan filter, filter menyediakan dua jenis, yang pertama adalah mengatur pengkodean, dan yang kedua adalah melakukan operasi decoding secara langsung di filter.
Filter 1
Filter ini secara langsung menetapkan format pengkodean permintaan.
Kelas Publik KarakterEncoding mengimplementasikan filter {private filterconfig config; String encoding = null; public void dashar () {config = null; } public void dofilter (permintaan servletRequest, respons servletResponse, rantai filterchain) melempar ioException, servletException {request.setcharacterencoding (encoding); rantai.dofilter (permintaan, respons); } public void init (filterconfig config) melempar servletException {this.config = config; // Dapatkan Parameter Konfigurasi String str = config.getInitparameter ("encoding"); if (str! = null) {encoding = str; }}} Konfigurasi:
<!-Konfigurasi Filter China-> <nilter> <filter-name> ChinaCoding </tiler-name> <nilter-class> com.test.filter.characterencoding </filter-class> <Ilin-param> <param-name> encoding </param-name> <param-value> UTF-8 </param-value> </init-param> <param-value> UTF-8 </param-value> </init-param> <param-value> UTF-8 <filter-name> ChinaCoding </tiler-name> <rucs-pola>/*</rucpats-pola> </filter-mapping>
Filter 2
Dalam metode pemrosesan, filter secara langsung mendekode parameter, dan kemudian mengatur ulang parameter yang diterjemahkan ke atribut permintaan.
Public Class Characterencoding mengimplementasikan filter {filterconfig filterconfig yang dilindungi; String encoding = null; public void hancurkan () {this.filterconfig = null; } / *** inisialisasi* / public void init (filterconfig filterconfig) {this.filterconfig = filterconfig; } / *** Konversi Instr menjadi Formulir Pengkodean UTF -8** @param Instr enter String* @return UTF - Formulir Pengkodean 8 String* @Throws UnsupportedEncodingException* / Private String toutf (String Instr) melempar Uns UnsportedEncodingException {String outstr = ""; if (instr! = null) {outstr = new string (instr.getbytes ("iso-8859-1"), "utf-8"); } return outstr; } / *** Pemrosesan penyaringan China kacau* / public void dofilter (servletRequest servletRequest, servletResponse servletResponse, rantai filterchain) melempar ioException, servletException {httpservletrequest = (httpservletreest) servletrequest); HttpservletResponse respons = (httpservletResponse) ServletResponse; // Metode untuk mendapatkan permintaan (1.post atau 2.get), dan pemrosesan yang berbeda dilakukan sesuai dengan metode permintaan yang berbeda Metode string = request.getMethod (); // 1. Untuk permintaan yang dikirimkan di pos, langsung atur pengkodean ke UTF-8 if (method.equalsignorecase ("post")) {coba {request.setcharacterencoding ("UTF-8"); } catch (UnsupportedEncodingException e) {e.printstacktrace (); }} // 2. Permintaan yang dikirimkan di Get Else {// Keluar dari set parameter yang dikirimkan oleh Enumeration Client <string> paramNames = request.getParameternames (); // lintasi parameter yang diatur untuk mengeluarkan nama dan nilai dari setiap parameter while (paramnames.hasmoreElements ()) {string name = paramNames.NextElement (); // Keluar dari Nilai Parameter Nilai String [] = Request.GetParameterValues (Name); // Keluarkan nilainya sesuai dengan nama parameter // Jika set nilai parameter tidak kosong jika (nilai! = Null) {// melintasi nilai parameter yang ditetapkan untuk (int i = 0; i <values.length; i ++) {coba {// Lingkaran kembali dan panggil setiap nilai toutf (values [i]) metode untuk mengonversi karakter {// Paramet Nilai Paramer. nilai [i] = vlustr; } catch (UnsupportedEncodingException e) {e.printstacktrace (); }} // Sembunyikan nilai dalam bentuk atribut dalam permintaan permintaan permintaan.setAttribute (name, values); }}} // Atur metode respons dan mendukung set response karakter Cina.setContentType ("Teks/html; charset = UTF-8"); // Lanjutkan untuk menjalankan filter berikutnya. Jika tidak ada filter, permintaan akan menjadi rantai.dofilter (permintaan, respons); }} Konfigurasi:
<!-Konfigurasi Filter China-> <nilter> <filter-name> ChinaCoding </tilter-name> <nilter-class> com.test.filter.characterencoding </filter-class> </filter> <nilter-papping> <nilter-name> </filter-name> <rilter-pattern>/</url-pola> </filter-name> <ruRl-pattern>/</url-pola> </filter-name> <rill-pola>/</url-pola> </filter-name>
lainnya
1. Setel PageEncoding dan ContentType
<%@ halaman bahasa = "java" contentType = "Text/html; charset = utf-8" pageEncoding = "UTF-8"%>
2. Atur Uriencoding Tomcat
Secara default, server Tomcat menggunakan format pengkodean ISO-8859-1 untuk menyandikan URL yang diminta oleh parameter Uriencoding, jadi kita hanya perlu menambahkan uriencoding = "UTF-8" ke tag <nonnector> dari file server.xml dari tomcat.