จะรับ URI คำขอโดยไม่มีเส้นทางบริบทได้อย่างไร


128

วิธีการrequest.getRequestURI ()ส่งคืน URI พร้อมพา ธ บริบท

ตัวอย่างเช่นถ้า URL พื้นฐานของการประยุกต์ใช้เป็นhttp://localhost:8080/myapp/(เช่นเส้นทางบริบทคือmyapp ) และที่ผมเรียกrequest.getRequestURI()สำหรับก็จะกลับhttp://localhost:8080/myapp/secure/users/myapp/secure/users

มีวิธีใดบ้างที่เราจะได้รับเฉพาะส่วนนี้/secure/usersเช่น URI ที่ไม่มีเส้นทางบริบท


คำตอบ:


159

หากคุณอยู่ใน servlet ตัวควบคุมด้านหน้าซึ่งแมปกับรูปแบบคำนำหน้าคุณก็สามารถHttpServletRequest#getPathInfo()ใช้ได้

String pathInfo = request.getPathInfo();
// ...

สมมติว่ามีการแมป servlet ในตัวอย่างของคุณ/secureแล้วสิ่งนี้จะส่งกลับ/usersซึ่งจะเป็นข้อมูลที่น่าสนใจ แต่เพียงผู้เดียวภายใน servlet ตัวควบคุมด้านหน้าทั่วไป

หากมีการแมป servlet บนรูปแบบคำต่อท้าย (อย่างไรก็ตามตัวอย่าง URL ของคุณไม่ได้ระบุว่าเป็นกรณีนี้) หรือเมื่อคุณอยู่ในตัวกรอง (เมื่อยังไม่จำเป็นต้องกำหนด servlet ที่จะเรียกใช้ดังนั้นgetPathInfo()สามารถส่งคืนได้null) ทางออกที่ดีที่สุดของคุณคือการซับ URI คำขอด้วยตัวคุณเองตามความยาวของเส้นทางบริบทโดยใช้Stringวิธีการปกติ:

HttpServletRequest request = (HttpServletRequest) req;
String path = request.getRequestURI().substring(request.getContextPath().length());
// ...

มีเหตุผลที่จะใช้สิ่งนี้แทนgetServletPath()หรือไม่? ฉันกำลังเขียนตัวกรองและสังเกตเห็นว่าgetPathInfo()ส่งคืนnullแต่getServletPath()ส่งคืนเส้นทางลบบริบท (เหมาะสำหรับส่งต่อไปยังผู้มอบหมายงานคำขอ)
Jason C

@JasonC: ตามคำตอบgetPathInfo()จะส่งคืนค่า null หาก servlet ตัวควบคุมด้านหน้าไม่ได้แมปบนรูปแบบคำนำหน้า
BalusC

ใช่. ฉันหมายถึง: มีเหตุผลที่คุณชอบ getPathInfo มากกว่า getServletPath หรือไม่? คำตอบที่ได้คะแนนสูงอื่น ๆ อีกมากมายที่นี่ไม่ได้ใช้ getServletPath เช่นกันซึ่งเป็นสิ่งที่ทำให้ฉันสงสัยและทำไมฉันถึงสงสัย ฉันมีโปรเจ็กต์ servlet ที่กำลังทำอยู่และฉันกำลังพยายามขัดเกลาทักษะของตัวเองเล็กน้อย
Jason C

1
@JasonC: เส้นทาง servlet อาจเปลี่ยนแปลงได้เมื่อคุณติดตั้งเฟรมเวิร์ก MVC ที่ใช้ servlet เช่น JSF หรือ Spring MVC จากนั้นจะแสดงเส้นทางภายในของเฟรมเวิร์ก MVC (เช่น/foo.xhtmlแทนที่จะเป็น/foo.jsf) และไม่ใช่ URI คำขอจริง (อันที่ enduser จะเห็นในแถบที่อยู่ของเบราว์เซอร์) เส้นทางเซิร์ฟเล็ตเดิมในกรณีดังกล่าว แต่ resolveable RequestDispatcher.FORWARD_SERVLET_PATHตามคำขอของแอตทริบิวต์ที่มีคีย์ ไม่ว่าจะด้วยวิธีใดก็ตามคำถามจะถาม URI คำขออย่างชัดเจน (เช่นเดียวกับในแถบที่อยู่ของเบราว์เซอร์) ดังนั้นคำตอบจึงเป็นไปตามนั้น
BalusC

74
request.getRequestURI().substring(request.getContextPath().length())

! น่ากลัว นี่คือสิ่งที่ฉันกำลังมองหา
ช่างฝีมือ

4
+1 ฉันคิดว่านี่เป็นคำตอบที่ดีกว่า getPathInfo เนื่องจาก getPathInfo อาจเป็นโมฆะและสิ่งแปลกประหลาดอื่น ๆ โค้ด Spring ต่างๆทำ getContextPath และลบออกจาก URI เช่นเดียวกับที่คุณทำแทน getPathInfo
Adam Gent

32

ด้วย Spring คุณสามารถทำได้:

String path = new UrlPathHelper().getPathWithinApplication(request);

1
แน่นอนว่าควรเก็บตัวอย่าง UrlPathHelper ไว้เป็นตัวแปรสมาชิกชั้นเรียน ...
James

เราจะรับ url การแมปคำขอจริงได้อย่างไร โปรดชี้แนะที่นี่: stackoverflow.com/questions/60446807/…
Pra_A

14

getPathInfo () บางครั้งคืนค่า null ในเอกสารHttpServletRequest

เมธอดนี้จะคืนค่าว่างหากไม่มีข้อมูลเส้นทางเพิ่มเติม

ฉันต้องการรับเส้นทางไปยังไฟล์โดยไม่มีเส้นทางบริบทในตัวกรองและ getPathInfo () ส่งคืนค่าว่างให้ฉัน ดังนั้นฉันจึงใช้วิธีอื่น: httpRequest.getServletPath ()

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
{
    HttpServletRequest httpRequest = (HttpServletRequest) request;
    HttpServletResponse httpResponse = (HttpServletResponse) response;

    String newPath = parsePathToFile(httpRequest.getServletPath());
    ...

}

8

หากคุณใช้ request.getPathInfo () ภายในตัวกรองคุณมักจะได้รับค่าว่าง (อย่างน้อยก็ด้วยท่าเทียบเรือ)

ข้อผิดพลาด + การตอบสนองที่ไม่ถูกต้องนี้กล่าวถึงปัญหาที่ฉันคิดว่า:

https://issues.apache.org/bugzilla/show_bug.cgi?id=28323

ฉันสงสัยว่ามันเกี่ยวข้องกับการที่ตัวกรองทำงานก่อนที่ servlet จะได้รับคำขอ อาจเป็นข้อบกพร่องของคอนเทนเนอร์หรือพฤติกรรมที่คาดหวังซึ่งฉันไม่สามารถระบุได้

บริบทพา ธ พร้อมใช้งานดังนั้นโซลูชัน fforws จึงทำงานได้แม้ในตัวกรอง ฉันไม่ชอบที่ต้องทำด้วยมือ แต่การนำไปใช้งานเสียหรือ


5

วิธีดำเนินการนี้คือการพักพา ธ บริบท servelet จาก URI คำขอ

String p = request.getRequestURI();
String cp = getServletContext().getContextPath();

if (p.startsWith(cp)) {
  String.err.println(p.substring(cp.length());
}

อ่านที่นี่


-1

คุณสามารถใช้วิธีการแยกเพื่อกำจัด '/ myapp' ได้เช่น:

string[] uris=request.getRequestURI().split("/");
string uri="/"+uri[1]+"/"+uris[2];

3
นี้จะทำให้เกิดปัญหาถ้าผมปรับใช้แอพลิเคชันของฉันเป็นรากและ URL ฐานของมันจะกลายเป็นlocalhost: 8080 ในกรณีนี้ request.getRequestURI () จะส่งคืน "/ secure / user" และวิธีการแยกของคุณจะทำให้เกิดปัญหาที่นี่ รหัสไม่ควรขึ้นอยู่กับการปรับใช้
ช่างฝีมือ
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.