การตรวจสอบ URL ใน Java


103

ฉันต้องการทราบว่ามี API มาตรฐานใน Java เพื่อตรวจสอบ URL ที่กำหนดหรือไม่? ฉันต้องการตรวจสอบว่าสตริง URL ถูกต้องหรือไม่เช่นโปรโตคอลที่กำหนดนั้นถูกต้องจากนั้นตรวจสอบว่าสามารถสร้างการเชื่อมต่อได้หรือไม่

ฉันลองใช้ HttpURLConnection โดยให้ URL และเชื่อมต่อกับมัน ส่วนแรกของความต้องการของฉันดูเหมือนจะบรรลุผล แต่เมื่อฉันพยายามดำเนินการ HttpURLConnection.connect () ข้อยกเว้น 'java.net.ConnectException: การเชื่อมต่อปฏิเสธ' จะถูกโยนทิ้ง

อาจเป็นเพราะการตั้งค่าพร็อกซี? ฉันพยายามตั้งค่าคุณสมบัติของระบบสำหรับพร็อกซี แต่ไม่สำเร็จ

แจ้งให้เราทราบว่าฉันทำอะไรผิด


2
ดูเหมือนจะมีคำถาม 2 ข้อที่นี่ การตรวจสอบ URL และการค้นหาสาเหตุของ ConnectException
Ben James

เนื่องจากนี่เป็น Hit แรกของ Google java url validatorจึงมีคำถามมากมายที่นี่วิธีตรวจสอบความถูกต้องของ URL (จากการดูสตริง) และวิธีตรวจสอบว่า URL นั้นเข้าถึงได้หรือไม่ (ผ่านการเชื่อมต่อ http เป็นต้น)
vikingsteve

คำตอบ:


158

เพื่อประโยชน์ของชุมชนเนื่องจากกระทู้นี้ติดอันดับต้น ๆ ใน Google เมื่อค้นหา
" url validator java "


ข้อยกเว้นในการจับมีราคาแพงและควรหลีกเลี่ยงเมื่อเป็นไปได้ หากคุณต้องการตรวจสอบว่า String ของคุณเป็น URL ที่ถูกต้องคุณสามารถใช้คลาสUrlValidatorจากApache Commons Validatorโปรเจ็กต์

ตัวอย่างเช่น:

String[] schemes = {"http","https"}; // DEFAULT schemes = "http", "https", "ftp"
UrlValidator urlValidator = new UrlValidator(schemes);
if (urlValidator.isValid("ftp://foo.bar.com/")) {
   System.out.println("URL is valid");
} else {
   System.out.println("URL is invalid");
}

38
คลาส URLValidator นั้นถูกทำเครื่องหมายว่าเลิกใช้แล้ว URLValidator ที่แนะนำอยู่ในแพ็คเกจรูทีน: commons.apache.org/validator/apidocs/org/apache/commons/…
Spektr

6
@Spektr ฉันได้แก้ไขลิงค์แล้ว ขอบคุณ.
Yonatan

18
ฉันไม่เห็นว่านี่เป็นAPI มาตรฐานอย่างไร
b1nary.atr0phy

2
UrlValidator มีชุดปัญหาที่ทราบของตนเอง มีไลบรารีสำรองที่ได้รับการดูแลอย่างแข็งขันกว่านี้หรือไม่
Alex Averbuch

9
@AlexAverbuch: คุณช่วยสรุปได้ไหมว่า UrlValidator มีปัญหาอะไรบ้าง การบอกว่ามีอยู่จริง แต่ไม่ได้ช่วยอะไร
cdmckay

33

คุณต้องสร้างทั้งURLวัตถุและURLConnectionวัตถุ โค้ดต่อไปนี้จะทดสอบทั้งรูปแบบของ URL และว่าสามารถสร้างการเชื่อมต่อได้หรือไม่:

try {
    URL url = new URL("http://www.yoursite.com/");
    URLConnection conn = url.openConnection();
    conn.connect();
} catch (MalformedURLException e) {
    // the URL is not in a valid form
} catch (IOException e) {
    // the connection couldn't be established
}

โปรดทราบว่ามีหลายวิธีในการตรวจสอบ URL / ปัญหาที่ผิดรูปแบบ ตัวอย่างเช่นหากคุณจะใช้ url ของคุณสำหรับ a new HttpGet(url)คุณสามารถตรวจจับการIllegalArgumentException HttpGet(...)โยนได้หากมี url ที่ผิดรูปแบบ และHttpResponseจะขว้างสิ่งของใส่คุณด้วยหากมีปัญหาในการรับข้อมูล
Peter Ajtai

2
การเชื่อมต่อตรวจสอบความพร้อมใช้งานของโฮสต์เท่านั้น ไม่มีส่วนเกี่ยวข้องกับความถูกต้องของ URL
Andrey Rodionov

2
MalformedURLException ไม่ใช่กลยุทธ์ที่ปลอดภัยในการทดสอบรูปแบบ URL ที่ถูกต้อง คำตอบนี้ทำให้เข้าใจผิด
Martin

1
@Martin: คุณอธิบายได้ไหมว่าทำไมมันถึงไม่ปลอดภัย?
Jeroen Vannevel

28
นี่คือแพงมาก openConnection / connect จะพยายามเชื่อมต่อกับทรัพยากร http นี่ต้องเป็นวิธีที่แพงที่สุดวิธีหนึ่งในการยืนยัน URL
Glenn Bech

33

java.net.URLชั้นในความเป็นจริงไม่ได้เลยวิธีที่ดีของการตรวจสอบ URL ที่ MalformedURLExceptionจะไม่ถูกส่งไปยัง URL ที่ผิดรูปแบบทั้งหมดในระหว่างการสร้าง จับIOExceptionได้ที่java.net.URL#openConnection().connect()ไม่ตรวจสอบ URL อย่างใดอย่างหนึ่งเพียงบอกสภาพอากาศหรือไม่การเชื่อมต่อสามารถจะจัดตั้งขึ้น

พิจารณาโค้ดส่วนนี้:

    try {
        new URL("http://.com");
        new URL("http://com.");
        new URL("http:// ");
        new URL("ftp://::::@example.com");
    } catch (MalformedURLException malformedURLException) {
        malformedURLException.printStackTrace();
    }

.. ซึ่งไม่มีข้อยกเว้นใด ๆ

ฉันขอแนะนำให้ใช้ API การตรวจสอบความถูกต้องบางตัวที่ติดตั้งโดยใช้ไวยากรณ์ที่ไม่มีบริบทหรือในการตรวจสอบความถูกต้องที่ง่ายมากให้ใช้นิพจน์ทั่วไป อย่างไรก็ตามฉันต้องการคนแนะนำ API ที่เหนือกว่าหรือมาตรฐานสำหรับสิ่งนี้ฉันเพิ่งเริ่มค้นหาด้วยตัวเอง

หมายเหตุ มีการแนะนำให้URL#toURI()ใช้ร่วมกับการจัดการข้อยกเว้นjava.net. URISyntaxExceptionสามารถอำนวยความสะดวกในการตรวจสอบความถูกต้องของ URL อย่างไรก็ตามวิธีนี้สามารถจับได้เฉพาะกรณีง่ายๆข้างต้นเท่านั้น

ข้อสรุปคือไม่มีตัวแยกวิเคราะห์ URL java มาตรฐานในการตรวจสอบความถูกต้องของ URL


คุณพบวิธีแก้ปัญหานี้หรือยัง ??
kidd0

@ bi0s.kidd0 มีห้องสมุดหลายแห่งที่สามารถใช้ได้ แต่เราตัดสินใจที่จะเปิดใช้งานของเราเอง ยังไม่สมบูรณ์ แต่สามารถแยกวิเคราะห์สิ่งที่เราสนใจรวมถึง URL ที่มีโดเมนหรือ IP (ทั้ง v4 และ v6) github.com/jajja/arachne
Martin

15

ใช้API มาตรฐานเท่านั้นส่งสตริงไปยังURLวัตถุจากนั้นแปลงเป็นURIวัตถุ สิ่งนี้จะกำหนดความถูกต้องของ URL ตามมาตรฐาน RFC2396 ได้อย่างถูกต้อง

ตัวอย่าง:

public boolean isValidURL(String url) {

    try {
        new URL(url).toURI();
    } catch (MalformedURLException | URISyntaxException e) {
        return false;
    }

    return true;
}

5
โปรดทราบว่ารูปแบบการตรวจสอบความถูกต้องของ string-> url-> uri นี้รายงานว่ากรณีทดสอบเหล่านี้ถูกต้อง: "http: //.com" " com " "ftp: // :::: @ example.com" "http: /test.com" "http: test.com" "http: /:" ดังนั้นแม้ว่านี่จะเป็น API มาตรฐาน แต่กฎการตรวจสอบที่ใช้อาจไม่เป็น สิ่งที่คาดหวัง
DaveK

10

ใช้android.webkit.URLUtilบน Android:

URLUtil.isValidUrl(URL_STRING);

หมายเหตุ: เป็นเพียงการตรวจสอบรูปแบบเริ่มต้นของ URL ไม่ใช่ว่า URL ทั้งหมดถูกต้อง


2
เฉพาะในกรณีที่คุณกำลังทำงานกับแอปพลิเคชัน Android ของหลักสูตรเท่านั้น
miva2

8

มีวิธีการตรวจสอบ URL ตามมาตรฐานที่เข้มงวดใน Java โดยไม่ต้องใช้ไลบรารีของบุคคลที่สาม:

boolean isValidURL(String url) {
  try {
    new URI(url).parseServerAuthority();
    return true;
  } catch (URISyntaxException e) {
    return false;
  }
}

ตัวสร้างการURIตรวจสอบที่urlเป็น URI ที่ถูกต้องและการเรียกเพื่อparseServerAuthorityให้แน่ใจว่าเป็น URL (สัมบูรณ์หรือสัมพัทธ์) ไม่ใช่ URN


ข้อยกเว้นคือ "หากมีการกำหนดองค์ประกอบสิทธิของ URI นี้ แต่ไม่สามารถแยกวิเคราะห์เป็นสิทธิบนเซิร์ฟเวอร์ตาม RFC 2396" แม้ว่าจะดีกว่าข้อเสนออื่น ๆ มาก แต่ก็ไม่สามารถตรวจสอบความถูกต้องของ URL ได้
Martin

@ มาร์ตินคุณลืมเกี่ยวกับการตรวจสอบความถูกต้องในตัวสร้าง ตามที่ฉันเขียนการรวมกันของการURIเรียกตัวสร้างและการparseServerAuthorityโทรจะตรวจสอบ URL ไม่ใช่parseServerAuthorityเพียงอย่างเดียว
ปิด

1
คุณสามารถค้นหาตัวอย่างในหน้านี้ที่ข้อเสนอแนะของคุณตรวจสอบไม่ถูกต้อง โปรดดูเอกสารประกอบและหากไม่ได้ออกแบบมาเพื่อการใช้งานตามวัตถุประสงค์ของคุณโปรดอย่าส่งเสริมให้ใช้ประโยชน์จากเอกสารนี้
Martin

@ มาร์ตินคุณเจาะจงมากขึ้นได้ไหม ตัวอย่างใดในความคิดของคุณที่ตรวจสอบไม่ถูกต้องโดยวิธีนี้
ลง

1
@Asu ใช่ ตัวที่สอง://มาหลังจากโฮสต์:แนะนำหมายเลขพอร์ตซึ่งสามารถว่างได้ตามไวยากรณ์ //เป็นส่วนหนึ่งของเส้นทางที่มีส่วนว่างซึ่งก็ใช้ได้เช่นกัน หากคุณป้อนที่อยู่นี้ในเบราว์เซอร์ของคุณมันจะพยายามเปิด (แต่ส่วนใหญ่อาจไม่พบเซิร์ฟเวอร์ชื่อhttps;))
dened

2

สิ่งสำคัญคือต้องชี้ว่าออบเจ็กต์ URL จัดการทั้งการตรวจสอบความถูกต้องและการเชื่อมต่อ จากนั้นเฉพาะโปรโตคอลที่มีให้ตัวจัดการในsun.net เท่านั้น www.protocolได้รับอนุญาต ( ไฟล์ , ftp , gopher , http , https , jar , mailto , netdoc ) เท่านั้นที่ถูกต้อง ตัวอย่างเช่นลองสร้าง URL ใหม่ด้วยโปรโตคอลldap :

new URL("ldap://myhost:389")

คุณจะได้รับไฟล์java.net.MalformedURLException: unknown protocol: ldap.

URL.setURLStreamHandlerFactory()คุณจำเป็นต้องดำเนินการจัดการของคุณเองและลงทะเบียนผ่าน ค่อนข้างมากเกินไปหากคุณต้องการตรวจสอบความถูกต้องของไวยากรณ์ URL regexp ดูเหมือนจะเป็นวิธีที่ง่ายกว่า


1

คุณแน่ใจหรือไม่ว่าคุณใช้พร็อกซีที่ถูกต้องเป็นคุณสมบัติของระบบ?

นอกจากนี้หากคุณใช้ 1.5 หรือ 1.6 คุณสามารถส่งอินสแตนซ์ java.net.Proxy ไปยังเมธอด openConnection () นี่คือ imo ที่สง่างามมากขึ้น:

//Proxy instance, proxy ip = 10.0.0.1 with port 8080
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("10.0.0.1", 8080));
conn = new URL(urlString).openConnection(proxy);

ทำไมสิ่งนี้ถึงดูสง่างามหรือถูกต้อง? ใช้ทรัพยากรที่มีราคาแพงเมื่อใช้งานได้และไม่สามารถใช้งานได้กับ URL ที่ถูกต้องจะไม่พร้อมใช้งานสำหรับการเชื่อมต่อเมื่อทดสอบ
Martin

0

ฉันคิดว่าคำตอบที่ดีที่สุดมาจากผู้ใช้ @ b1nary.atr0phy อย่างไรก็ตามฉันขอแนะนำให้รวมวิธีการจากการตอบสนอง b1nay.atr0phy กับ regex เพื่อให้ครอบคลุมกรณีที่เป็นไปได้ทั้งหมด

public static final URL validateURL(String url, Logger logger) {

        URL u = null;
        try {  
            Pattern regex = Pattern.compile("(?i)^(?:(?:https?|ftp)://)(?:\\S+(?::\\S*)?@)?(?:(?!(?:10|127)(?:\\.\\d{1,3}){3})(?!(?:169\\.254|192\\.168)(?:\\.\\d{1,3}){2})(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,}))\\.?)(?::\\d{2,5})?(?:[/?#]\\S*)?$");
            Matcher matcher = regex.matcher(url);
            if(!matcher.find()) {
                throw new URISyntaxException(url, "La url no está formada correctamente.");
            }
            u = new URL(url);  
            u.toURI(); 
        } catch (MalformedURLException e) {  
            logger.error("La url no está formada correctamente.");
        } catch (URISyntaxException e) {  
            logger.error("La url no está formada correctamente.");  
        }  

        return u;  

    }

1
มีปัญหาสองสามประการใน regex นี้: 1. URL ที่ไม่มีคำนำหน้าไม่ถูกต้อง (เช่น "stackoverflow.com") ซึ่งรวมถึง URL ที่มีคำต่อท้ายสองคำหากไม่มีคำนำหน้า (เช่น "amazon.co.uk "). 2. IP ไม่ถูกต้องเสมอ (เช่น " 127.0.0.1" ) ไม่ว่าจะใช้คำนำหน้าหรือไม่ก็ตาม ฉันขอแนะนำให้ใช้"((http|https|ftp)://)?((\\w)*|([0-9]*)|([-|_])*)+([\\.|/]((\\w)*|([0-9]*)|([-|_])*))+"( แหล่งที่มา ) ข้อเสียเพียงประการเดียวของ regex นี้คือเช่น "127.0..0.1" และ "127.0" นั้นใช้ได้
Neph

-2

ขอบคุณ. การเปิดการเชื่อมต่อ URL โดยส่งผ่าน Proxy ตามที่ NickDK แนะนำใช้งานได้ดี

//Proxy instance, proxy ip = 10.0.0.1 with port 8080
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("10.0.0.1", 8080));
conn = new URL(urlString).openConnection(proxy);

อย่างไรก็ตามคุณสมบัติของระบบไม่ทำงานตามที่ฉันได้กล่าวไว้ก่อนหน้านี้

ขอบคุณอีกครั้ง.

ขอแสดงความนับถือ Keya

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.