Panduan untuk Encoding / Decoding URL Java

1. Perkenalan

Sederhananya, pengkodean URL menerjemahkan karakter khusus dari URL ke representasi yang sesuai dengan spesifikasi dan dapat dipahami dan ditafsirkan dengan benar.

Dalam artikel ini, kami akan fokus pada cara menyandikan / mendekode URL atau membentuk data sehingga sesuai dengan spesifikasi dan mengirimkan melalui jaringan dengan benar.

2. Analisis URL

Sintaks URI dasar dapat digeneralisasikan sebagai:

scheme:[//[user:[email protected]]host[:port]][/]path[?query][#fragment]

Langkah pertama dalam mengenkode URI adalah memeriksa bagian-bagiannya dan kemudian hanya mengenkode bagian yang relevan.

Mari kita lihat contoh URI:

String testUrl = "//www.baeldung.com?key1=value+1&key2=value%40%21%242&key3=value%253";

Salah satu cara menganalisis URI adalah memuat 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")); }

Kelas URI mem-parsing URL representasi string dan mengekspos bagian-bagiannya melalui API sederhana - misalnya, getXXX.

3. Menyandikan URL

Saat mengenkode URI, salah satu kesalahan umum adalah mengenkode URI lengkap. Biasanya, kita hanya perlu mengenkode bagian kueri URI.

Mari menyandikan data menggunakan metode encode (data, encodingScheme) dari kelas URLEncoder :

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 encode metode menerima dua parameter:

  1. data - string yang akan diterjemahkan
  2. encodingScheme - nama pengkodean karakter

Metode penyandian ini mengubah string menjadi format application / x-www-form-urlencoded .

Skema pengkodean akan mengubah karakter khusus menjadi dua digit representasi heksadesimal dari 8 bit yang akan direpresentasikan dalam bentuk “ % xy “. Ketika kita berurusan dengan parameter jalur atau menambahkan parameter yang bersifat dinamis, maka kita akan menyandikan datanya dan kemudian mengirim ke server.

Catatan: The World Wide Web Consortium Rekomendasi menyatakan bahwa UTF-8 harus digunakan. Tidak melakukannya dapat menyebabkan ketidakcocokan. (Referensi: //docs.oracle.com/javase/7/docs/api/java/net/URLEncoder.html )

4. Dekode URL

Sekarang mari kita mendekode URL sebelumnya menggunakan metode decode dari 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 decoding
  • gunakan skema encoding yang sama untuk encoding dan decoding

Jika kita mendekode daripada menganalisis, bagian URL mungkin tidak diuraikan dengan benar. Jika kita menggunakan skema encoding lain untuk mendekode data, itu akan menghasilkan data sampah.

5. Menyandikan Segmen Jalur

URLEncoder tidak dapat digunakan untuk pengkodean segmen jalur URL . Komponen jalur mengacu pada struktur hierarki yang mewakili jalur direktori, atau berfungsi untuk menemukan sumber daya yang dipisahkan oleh "/" .

Karakter yang dipesan di segmen jalur berbeda dengan di nilai parameter kueri. Misalnya, tanda “+” adalah karakter yang valid di segmen jalur dan oleh karena itu tidak boleh dienkode.

Untuk menyandikan segmen jalur, kami menggunakan kelas UriUtils oleh Spring Framework sebagai gantinya. UriUtils kelas menyediakan encodePath dan encodePathSegment metode untuk encoding jalan dan segmen jalan masing-masing.

Mari kita lihat contohnya:

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 potongan kode di atas kita dapat melihat bahwa ketika kita menggunakan metode encodePathSegment , itu mengembalikan nilai yang dikodekan dan + tidak sedang dikodekan karena itu adalah karakter nilai dalam komponen jalur.

Mari kita tambahkan variabel jalur ke URL uji kita:

String testUrl = "/path+1?key1=value+1&key2=value%40%21%242&key3=value%253";

dan untuk merakit dan menegaskan URL yang dikodekan dengan benar, mari kita ubah pengujian dari bagian 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. Kesimpulan

Dalam tutorial ini, kami telah melihat cara menyandikan dan mendekode data sehingga dapat ditransfer dan diinterpretasikan dengan benar. Meskipun artikel ini berfokus pada encoding / decoding nilai parameter kueri URI, pendekatan tersebut juga berlaku untuk parameter bentuk HTML.

Anda dapat menemukan kode sumbernya di GitHub.