Κωδικοποίηση παραμέτρων συμβολοσειράς ερωτήσεων σε URL της Java

Ας πούμε ότι έχω ένα URL

http://example.com/query?q=

και έχω ένα ερώτημα που εισάγει ο χρήστης, όπως:

τυχαία λέξη £500 bank $

Θέλω το αποτέλεσμα να είναι ένα σωστά κωδικοποιημένο URL:

http://example.com/query?q=random%20word%20%A3500%20bank%20%24

Ποιος είναι ο καλύτερος τρόπος για να το πετύχω αυτό; Δοκίμασα το URLEncoder και τη δημιουργία αντικειμένων URI/URL αλλά κανένα από αυτά δεν βγαίνει σωστά.

Λύση

Το URLEncoder θα πρέπει να είναι ο τρόπος που πρέπει να ακολουθήσετε. Το μόνο που πρέπει να έχετε κατά νου είναι να κωδικοποιήσετε μόνο το όνομα ή/και την τιμή της μεμονωμένης παραμέτρου της συμβολοσειράς ερωτήσεων, όχι ολόκληρο το URL, και σίγουρα όχι τον χαρακτήρα διαχωρισμού της παραμέτρου της συμβολοσειράς ερωτήσεων & ούτε τον χαρακτήρα διαχωρισμού ονόματος-τιμής της παραμέτρου =.

String q = "random word £500 bank $";
String url = "http://example.com/query?q=" + URLEncoder.encode(q, "UTF-8");

Σημειώστε ότι τα κενά στις παραμέτρους ερωτήματος αναπαρίστανται με + και όχι με %20, το οποίο είναι νόμιμα έγκυρο. Το %20 χρησιμοποιείται συνήθως για την αναπαράσταση κενών στο ίδιο το URI (το μέρος πριν από τον χαρακτήρα διαχωρισμού URI-σειράς ερωτήματος ?), όχι στη συμβολοσειρά ερωτήματος (το μέρος μετά το ?).

Σημειώστε επίσης ότι υπάρχουν δύο μέθοδοι encode(). Η μία χωρίς το όρισμα charset και η άλλη με. Η μέθοδος χωρίς το όρισμα charset έχει ξεπεραστεί. Ποτέ μην τη χρησιμοποιείτε και να προσδιορίζετε πάντα το όρισμα charset. Το javadoc μάλιστα συνιστά ρητά τη χρήση της κωδικοποίησης UTF-8, όπως επιβάλλεται από το RFC3986 και το W3C.

Όλοι οι άλλοι χαρακτήρες είναι μη ασφαλείς και μετατρέπονται πρώτα σε ένα ή περισσότερα bytes χρησιμοποιώντας κάποιο σχήμα κωδικοποίησης. Στη συνέχεια, κάθε byte αναπαρίσταται από τη συμβολοσειρά 3 χαρακτήρων "%xy", όπου xy είναι η διψήφια δεκαεξαδική αναπαράσταση του byte. Το συνιστώμενο σχήμα κωδικοποίησης που συνιστάται να χρησιμοποιείται είναι το UTF-8. Ωστόσο, για λόγους συμβατότητας, εάν δεν καθοριστεί κωδικοποίηση, τότε χρησιμοποιείται η προεπιλεγμένη κωδικοποίηση της πλατφόρμας.

Βλέπε επίσης:

Σχόλια (11)

Δεν θα χρησιμοποιούσα τον URLEncoder. Εκτός του ότι έχει λανθασμένο όνομα (το URLEncoder δεν έχει καμία σχέση με τις διευθύνσεις URL), είναι αναποτελεσματικό (χρησιμοποιεί ένα StringBuffer αντί για Builder και κάνει μερικά άλλα πράγματα που είναι αργά) είναι επίσης πολύ εύκολο να το καταστρέψετε.

Αντ' αυτού θα χρησιμοποιούσα το URIBuilder ή το Spring's org.springframework.web.util.UriUtils.encodeQuery ή το Commons Apache HttpClient. Ο λόγος είναι ότι πρέπει να αποφύγετε το όνομα των παραμέτρων του ερωτήματος (δηλαδή την απάντηση του BalusC's q) διαφορετικά από την τιμή της παραμέτρου.

Το μόνο μειονέκτημα των παραπάνω (που ανακάλυψα με οδυνηρό τρόπο) είναι ότι τα URL's δεν αποτελούν πραγματικό υποσύνολο των URI's.

Δείγμα κώδικα:

import org.apache.http.client.utils.URIBuilder;

URIBuilder ub = new URIBuilder("http://example.com/query");
ub.addParameter("q", "random word £500 bank \$");
String url = ub.toString();

// Result: http://example.com/query?q=random+word+%C2%A3500+bank+%24

Επειδή απλά συνδέω με άλλες απαντήσεις, σημείωσα αυτό το κείμενο ως wiki της κοινότητας. Μπορείτε ελεύθερα να το επεξεργαστείτε.

Σχόλια (9)