1. Pengenalan
Ringkasnya, pengekodan URL menerjemahkan watak khas dari URL ke representasi yang mematuhi spesifikasi dan dapat difahami dan ditafsirkan dengan betul.
Dalam artikel ini, kami akan memfokuskan pada cara menyandikan / menyahkod URL atau membentuk data sehingga mematuhi spesifikasi dan mengirimkan melalui jaringan dengan betul.
2. Analisis URL
Sintaks URI asas dapat digeneralisasikan sebagai:
scheme:[//[user:[email protected]]host[:port]][/]path[?query][#fragment]
Langkah pertama untuk mengekod URI adalah memeriksa bahagiannya dan kemudian mengekodkan bahagian yang berkaitan sahaja.
Mari kita lihat contoh URI:
String testUrl = "//www.baeldung.com?key1=value+1&key2=value%40%21%242&key3=value%253";
Salah satu kaedah menganalisis URI ialah memuatkan representasi String ke kelas java.net.URI :
@Test public void givenURL_whenAnalyze_thenCorrect() throws Exception { URI uri = new URI(testUrl); assertThat(uri.getScheme(), is("http")); assertThat(uri.getHost(), is("www.baeldung.com")); assertThat(uri.getRawQuery(), .is("key1=value+1&key2=value%40%21%242&key3=value%253")); }
The URI kelas mem-parsing URL rentetan perwakilan dan mendedahkan bahagian-bahagiannya melalui mudah API - contohnya, getXXX.
3. Kod URL
Semasa mengekod URI, salah satu perangkap biasa adalah mengekod URI lengkap. Biasanya, kita hanya perlu mengekod bahagian pertanyaan URI.
Mari mengekod data menggunakan mengekod (data, encodingScheme) kaedah yang URLEncoder kelas:
private String encodeValue(String value) { return URLEncoder.encode(value, StandardCharsets.UTF_8.toString()); } @Test public void givenRequestParam_whenUTF8Scheme_thenEncode() throws Exception { Map requestParams = new HashMap(); requestParams.put("key1", "value 1"); requestParams.put("key2", "[email protected]!$2"); requestParams.put("key3", "value%3"); String encodedURL = requestParams.keySet().stream() .map(key -> key + "=" + encodeValue(requestParams.get(key))) .collect(joining("&", "//www.baeldung.com?", "")); assertThat(testUrl, is(encodedURL));
The mengekod kaedah menerima dua parameter:
- data - rentetan untuk diterjemahkan
- encodingScheme - nama pengekodan watak
Ini mengekod kaedah menukarkan tali ke dalam application / x-www-bentuk-urlencoded format.
Skema pengekodan akan menukar watak khas menjadi dua digit perwakilan heksadesimal 8 bit yang akan diwakili dalam bentuk “ % xy “. Apabila kita berurusan dengan parameter jalan atau menambahkan parameter yang dinamis, maka kita akan menyandikan data dan kemudian mengirim ke pelayan.
Nota: The World Wide Web Consortium Cadangan menyatakan bahawa UTF-8 harus digunakan. Tidak melakukannya boleh menyebabkan ketidaksesuaian. (Rujukan: //docs.oracle.com/javase/7/docs/api/java/net/URLEncoder.html )
4. Nyatakan URL
Mari kita sekarang menyahkod URL sebelumnya menggunakan kaedah penyahkodan URLDecoder :
private String decode(String value) { return URLDecoder.decode(value, StandardCharsets.UTF_8.toString()); } @Test public void givenRequestParam_whenUTF8Scheme_thenDecodeRequestParams() { URI uri = new URI(testUrl); String scheme = uri.getScheme(); String host = uri.getHost(); String query = uri.getRawQuery(); String decodedQuery = Arrays.stream(query.split("&")) .map(param -> param.split("=")[0] + "=" + decode(param.split("=")[1])) .collect(Collectors.joining("&")); assertEquals( "//www.baeldung.com?key1=value 1&[email protected]!$2&key3=value%3", scheme + "://" + host + "?" + decodedQuery); }
Dua bit penting di sini adalah:
- menganalisis URL sebelum penyahkodan
- gunakan skema pengekodan yang sama untuk pengekodan dan penyahkodan
Sekiranya kita menyahkod daripada menganalisis, bahagian URL mungkin tidak diuraikan dengan betul. Sekiranya kita menggunakan skema pengekodan lain untuk menyahkod data, itu akan menghasilkan data sampah.
5. Mengekod Segmen Laluan
URLEncoder tidak boleh digunakan untuk segmen laluan pengekodan URL . Komponen jalur merujuk kepada struktur hierarki yang mewakili jalan direktori, atau berfungsi untuk mencari sumber yang dipisahkan dengan “/” .
Karakter terpelihara dalam segmen jalan berbeza daripada nilai parameter pertanyaan. Sebagai contoh, tanda "+" adalah watak yang sah di segmen jalan dan oleh itu tidak boleh dikodkan.
Untuk mengekod segmen jalan, kami menggunakan kelas UriUtils dengan Spring Framework. UriUtils kelas menyediakan encodePath dan encodePathSegment kaedah untuk masing-masing pengekodan jalan dan segmen jalan.
Mari lihat contoh:
private String encodePath(String path) { try { path = UriUtils.encodePath(path, "UTF-8"); } catch (UnsupportedEncodingException e) { LOGGER.error("Error encoding parameter {}", e.getMessage(), e); } return path; }
@Test public void givenPathSegment_thenEncodeDecode() throws UnsupportedEncodingException { String pathSegment = "/Path 1/Path+2"; String encodedPathSegment = encodePath(pathSegment); String decodedPathSegment = UriUtils.decode(encodedPathSegment, "UTF-8"); assertEquals("/Path%201/Path+2", encodedPathSegment); assertEquals("/Path 1/Path+2", decodedPathSegment); }
Dalam coretan kod di atas, kita dapat melihat bahawa ketika kita menggunakan kaedah encodePathSegment , ia mengembalikan nilai yang dikodkan dan + tidak sedang dikodkan kerana ia adalah watak nilai dalam komponen jalur.
Mari kita tambahkan pemboleh ubah laluan ke URL ujian kami:
String testUrl = "/path+1?key1=value+1&key2=value%40%21%242&key3=value%253";
dan untuk mengumpulkan dan menegaskan URL yang dikodkan dengan betul mari kita mengubah ujian dari bahagian 2:
String path = "path+1"; String encodedURL = requestParams.keySet().stream() .map(k -> k + "=" + encodeValue(requestParams.get(k))) .collect(joining("&", "/" + encodePath(path) + "?", "")); assertThat(testUrl, CoreMatchers.is(encodedURL));
6. Kesimpulannya
Dalam tutorial ini, kita telah melihat cara mengekod dan menyahkod data sehingga dapat dipindahkan dan ditafsirkan dengan betul. Walaupun artikel tersebut memfokuskan pada pengekodan / penyahkodan nilai parameter pertanyaan URI, pendekatan ini berlaku untuk parameter bentuk HTML juga.
Anda boleh mendapatkan kod sumber di GitHub.