การเข้ารหัส Java URL: URLEncoder กับ URI

เมื่อดูที่หน้าเว็บการเข้ารหัส URL ของ W3 Schools ระบุว่า @ ควรเข้ารหัสเป็น %40 และ space ควรเป็น เข้ารหัสเป็น %20

ฉันได้ลองทั้ง URLEncoder และ URI แล้ว แต่ทั้งสองอย่างข้างต้นไม่ถูกต้อง:

import java.net.URI;
import java.net.URLEncoder;

public class Test {
    public static void main(String[] args) throws Exception {

        // Prints me%40home.com (CORRECT)
        System.out.println(URLEncoder.encode("[email protected]", "UTF-8"));

        // Prints Email+Address (WRONG: Should be Email%20Address)
        System.out.println(URLEncoder.encode("Email Address", "UTF-8"));

        // http://www.home.com/test?Email%[email protected]
        // (WRONG: it has not encoded the @ in the email address)
        URI uri = new URI("http", "www.home.com", "/test", "Email [email protected]", null);
        System.out.println(uri.toString());
    }
}

ด้วยเหตุผลบางประการ URLEncoder เว้นวรรคที่อยู่อีเมลอย่างถูกต้องแต่ไม่ได้เว้นวรรค และ URI เว้นวรรคสกุลเงินแต่ไม่ได้เว้นวรรคที่อยู่อีเมล

ฉันจะเข้ารหัสพารามิเตอร์ 2 ตัวนี้ให้สอดคล้องกับสิ่งที่ w3schools บอกว่าถูกต้องได้อย่างไร (หรือ w3schools ผิด?)


person John Farrelly    schedule 14.01.2013    source แหล่งที่มา
comment
หากคุณกำลังดูที่ w3schools.com แสดงว่าคุณกำลังทำผิด อ้างถึงสิ่งนี้   -  person Srinivas    schedule 14.01.2013
comment
@Srinivas บริการเว็บที่ฉันใช้ละเว้นคำขออย่างชัดเจนเว้นแต่จะมีการเข้ารหัสพารามิเตอร์ตามที่อธิบายไว้ในหน้าเว็บ w3schools :(   -  person John Farrelly    schedule 14.01.2013
comment
URLEncoder ไม่เข้ารหัสตามข้อกำหนด URL แต่ตามรูปแบบ application/x-www-form-urlencoded MIME (ซึ่งเป็นสิ่งที่เซิร์ฟเวอร์แอปพลิเคชันส่วนใหญ่คาดหวังสำหรับคีย์/ค่าพารามิเตอร์) ประเภท URI เข้ารหัสตามเอกสารประกอบ - นั่นคือมันไม่สมบูรณ์ ตัวสร้าง URL โปรดทราบว่าส่วนต่างๆ ของ URI มีกฎที่แตกต่างกัน ดูโพสต์นี้สำหรับ การวิเคราะห์เพิ่มเติม   -  person McDowell    schedule 14.01.2013
comment
@McDowell ใช่ฉันคิดว่าฉันควรจะถามว่าฉันจะรับ java เพื่อทำสิ่งที่ encodeURIComponent() ของ JavaScript ทำได้อย่างไร ฉันจะตรวจสอบ lib ของคุณ   -  person John Farrelly    schedule 14.01.2013


คำตอบ (2)


แม้ว่าฉันคิดว่าคำตอบจาก @fge นั้นเป็นคำตอบที่ถูกต้อง แต่เนื่องจากฉันใช้เว็บเซอร์ของบุคคลที่สามที่อาศัยการเข้ารหัสที่ระบุไว้ในบทความ W3Schools ฉันจึงติดตามคำตอบจาก Java เทียบเท่ากับ encodeURIComponent ของ JavaScript ที่สร้างเอาต์พุตเหมือนกันหรือไม่

public static String encodeURIComponent(String s) {
    String result;

    try {
        result = URLEncoder.encode(s, "UTF-8")
                .replaceAll("\\+", "%20")
                .replaceAll("\\%21", "!")
                .replaceAll("\\%27", "'")
                .replaceAll("\\%28", "(")
                .replaceAll("\\%29", ")")
                .replaceAll("\\%7E", "~");
    } catch (UnsupportedEncodingException e) {
        result = s;
    }

    return result;
}
person John Farrelly    schedule 20.01.2013
comment
คุณลืมสัญลักษณ์ & ซึ่งมีความสำคัญในการถอดรหัส URL (ทั้งสำหรับวิธี GET หรือ POST) เนื่องจากเป็นสัญลักษณ์ที่แยกคีย์ในคำขอ - person Giorgos Fandomas; 10.08.2015
comment
ฉันจำเป็นต้องชี้ให้เห็นว่า w3schools ไม่ใช่ W3C พวกเขาค่อนข้างแตกต่างกันมาก - person Mike B; 06.11.2018

ไวยากรณ์ URI ถูกกำหนดโดย RFC 3986 (เนื้อหาที่อนุญาตสำหรับสตริงการสืบค้นถูกกำหนดไว้ในส่วน 3.4) URI ของ Java เป็นไปตาม RFC นี้ โดยมีคำเตือนบางประการที่กล่าวถึงใน จาวาด็อก.

คุณจะสังเกตเห็นว่ากฎไวยากรณ์ pchar ถูกกำหนดโดย:

pchar = ไม่ได้สงวนไว้ / เข้ารหัส pct / การลบย่อย / /// / "@"

ซึ่งหมายความว่า @ ถูกกฎหมาย ในสตริงข้อความค้นหา

เชื่อถือ URI มันจะทำสิ่งที่ถูกต้องและ "ถูกกฎหมาย"

สุดท้ายนี้ หากคุณได้ดูที่ Javadoc ของ URLEncoder คุณจะเห็นว่ามันระบุ:

คลาสนี้มีวิธีคงที่สำหรับการแปลงสตริงเป็นรูปแบบ MIME ของ application/x-www-form-urlencoded

ซึ่งไม่ใช่เหมือนกับสตริงการสืบค้นตามที่กำหนดโดยข้อกำหนด URI

person fge    schedule 14.01.2013
comment
ฉันคิดว่าคำถามที่ฉันควรถามคือฉันจะทำให้ java เข้ารหัส URL ในลักษณะเดียวกับ JavaScript encodeURIComponent ได้อย่างไร เนื่องจากนี่คือสิ่งที่เว็บเซอร์รับคาดหวัง: stackoverflow.com/questions/607176/ - person John Farrelly; 14.01.2013
comment
ตั้งแต่นั้นมา ฉันได้พัฒนาไลบรารี่ที่ใช้เทมเพลต URI (RFC 6570) ซึ่งมีประสิทธิภาพมากยิ่งขึ้น ;) - person fge; 05.07.2013
comment
นี่แปลกมาก ... Javadocs สำหรับ URI ระบุว่าเป็นไปตาม RFC 2396 แม้ใน Java 8 โดยที่ RFC 2396 มาจากปี 1998 และ ล้าสมัย โดย RFC 3986 ตั้งแต่ปี 2005 - person arcuri82; 28.03.2017