ความแตกต่างระหว่างเมธอด getRequestURI และ getPathInfo ใน HttpServletRequest คืออะไร


143

ฉันกำลังสร้างส่วนควบคุมด้านหน้าที่เรียบง่ายและมีน้ำหนักเบามาก ฉันต้องจับคู่พา ธ คำขอกับตัวจัดการที่แตกต่างกัน (การกระทำ) เพื่อเลือกอันที่ถูกต้อง

ในเครื่องท้องถิ่นของฉันHttpServletRequest.getPathInfo()และHttpServletRequest.getRequestURI()ส่งคืนผลลัพธ์เดียวกัน แต่ฉันไม่แน่ใจว่าสิ่งที่พวกเขาจะกลับมาในสภาพแวดล้อมการผลิต

ดังนั้นความแตกต่างระหว่างวิธีการเหล่านี้กับสิ่งที่ฉันควรเลือกคืออะไร


1
คุณอาจพบว่าคำตอบนี้มีประโยชน์เช่นกัน
BalusC

@BalusC: ขอบคุณฉันใช้เคล็ดลับจากคำตอบนั้นไปแล้ว
โรมัน

สิ่งนี้อธิบายความแตกต่างด้วยแผนภาพที่ดี: agiletribe.wordpress.com/2016/02/23/…
AgilePro

คำตอบ:


77

getPathInfo()ให้ข้อมูลเส้นทางพิเศษหลังจาก URI ที่ใช้ในการเข้าถึง Servlet ของคุณโดยที่getRequestURI()ให้ URI ที่สมบูรณ์

ฉันคิดว่าพวกเขาจะแตกต่างกันเนื่องจาก Servlet ต้องถูกกำหนดค่าด้วยรูปแบบ URI ของตัวเองตั้งแต่แรก ฉันไม่คิดว่าฉันจะให้บริการ Servlet จาก root (/)

ตัวอย่างเช่นถ้า Servlet 'Foo' ถูกจับคู่กับ URI '/ foo' ฉันจะคิด URI:

/foo/path/to/resource

จะส่งผลให้:

RequestURI = /foo/path/to/resource

และ

PathInfo = /path/to/resource

20
มูลค่าการกล่าวขวัญเกี่ยวกับพฤติกรรมการถอดรหัส getRequestURI () ไม่ถอดรหัสสตริง โดยที่ getPathInfo () จะถอดรหัส
Kavindu Dodanduwa

1
ในบางกรณีgetRequestURI()ทำให้ผมสตริง"/foo/path/to/resource"ตามคาด แต่getPathInfo()สำหรับเดียวกันวัตถุให้ฉันHttpServletRequest nullเกิดอะไรขึ้นในโลกนี้? แก้ไข: มันมีคำตอบด้านล่างโดยผู้ใช้ "30thh"
anddero

460

ฉันจะวางตารางเปรียบเทียบขนาดเล็กที่นี่ (เพื่อให้มันอยู่ที่ไหนสักแห่ง):

Servlet ถูกแมปเป็นและการประยุกต์ใช้จะใช้งานภายใต้/test%3F/*/app

http://30thh.loc:8480/app/test%3F/a%3F+b;jsessionid=S%3F+ID?p+1=c+d&p+2=e+f#a

Method              URL-Decoded Result           
----------------------------------------------------
getContextPath()        no      /app
getLocalAddr()                  127.0.0.1
getLocalName()                  30thh.loc
getLocalPort()                  8480
getMethod()                     GET
getPathInfo()           yes     /a?+b
getProtocol()                   HTTP/1.1
getQueryString()        no      p+1=c+d&p+2=e+f
getRequestedSessionId() no      S%3F+ID
getRequestURI()         no      /app/test%3F/a%3F+b;jsessionid=S+ID
getRequestURL()         no      http://30thh.loc:8480/app/test%3F/a%3F+b;jsessionid=S+ID
getScheme()                     http
getServerName()                 30thh.loc
getServerPort()                 8480
getServletPath()        yes     /test?
getParameterNames()     yes     [p 2, p 1]
getParameter("p 1")     yes     c d

ในตัวอย่างด้านบนเซิร์ฟเวอร์กำลังทำงานบนlocalhost:8480และชื่อ30thh.locถูกวางลงในhostsไฟล์OS

ความคิดเห็น

  • "+" ถูกจัดการเป็นพื้นที่ในสตริงข้อความค้นหาเท่านั้น

  • Anchor "#a" ไม่ถูกถ่ายโอนไปยังเซิร์ฟเวอร์ มีเพียงเบราว์เซอร์เท่านั้นที่สามารถใช้งานได้

  • หากurl-patternในการทำแผนที่เซิร์ฟเล็ตไม่ได้จบด้วย*(ตัวอย่าง/testหรือ*.jsp) ผลตอบแทนgetPathInfo()null

หากใช้ Spring MVC

  • วิธีการรับผลตอบแทนgetPathInfo()null

  • เมธอดgetServletPath()ส่งคืนส่วนระหว่างพา ธ บริบทและ ID เซสชัน ในตัวอย่างด้านบนค่าจะเป็น/test?/a?+b

  • ระวังด้วยส่วนที่เข้ารหัส URL ของ@RequestMappingและ@RequestParamในฤดูใบไม้ผลิ มันเป็นรถ (รุ่นปัจจุบัน 3.2.4) และมักจะไม่ทำงานตามที่คาดไว้


20
ฉันกำลังพิมพ์คำตอบของคุณและวางเป็นโปสเตอร์ในสำนักงานของเรา มันมีประโยชน์มากขนาดไหน!
Ibrahim Arief

2
If the url-pattern in the servlet mapping does not end with * (for example /test or *.jsp), getPathInfo() returns null.สุกใส
Boris Treukhov

1
ฉันเชื่อว่าทั้งสองgetRequestURI()และgetRequestURL()ควรส่งคืน jsessionid ที่ไม่ได้ถอดรหัสในกรณีS%3F+IDนี้ อย่างน้อยก็ทำบน Tomcat / 8.5.6
Gediminas Rimsa

30

มาแบ่ง URL ทั้งหมดที่ลูกค้าจะพิมพ์ลงในแถบที่อยู่เพื่อเข้าถึง servlet ของคุณ:

http://www.example.com:80/awesome-application/path/to/servlet/path/info?a=1&b=2#boo

ชิ้นส่วนคือ:

  1. โครงการ: http
  2. ชื่อโฮสต์: www.example.com
  3. ท่าเรือ: 80
  4. เส้นทางบริบท: awesome-application
  5. เส้นทาง servlet: path/to/servlet
  6. ข้อมูลเส้นทาง: path/info
  7. แบบสอบถาม: a=1&b=2
  8. ชิ้นส่วน: boo

URI คำขอ (ส่งคืนโดยgetRequestURI ) สอดคล้องกับส่วนที่ 4, 5 และ 6

(บังเอิญแม้ว่าคุณจะไม่ได้ขอสิ่งนี้ แต่วิธีที่getRequestURLจะให้ส่วนที่ 1, 2, 3, 4, 5 และ 6)

ขณะนี้:

  • ส่วนที่ 4 (เส้นทางบริบท) ใช้เพื่อเลือกแอปพลิเคชันเฉพาะของคุณจากแอปพลิเคชั่นอื่น ๆ อีกมากมายที่อาจทำงานอยู่ในเซิร์ฟเวอร์
  • ส่วนที่ 5 (เส้นทาง servlet) ใช้เพื่อเลือก servlet เฉพาะจาก servlet อื่น ๆ ที่อาจรวมอยู่ใน WAR ของแอปพลิเคชันของคุณ
  • ส่วนที่ 6 (ข้อมูลเส้นทาง) ถูกตีความโดยตรรกะของ servlet ของคุณ (เช่นอาจชี้ไปที่ทรัพยากรที่ควบคุมโดยเซิร์ฟเล็ตของคุณ)
  • ตอนที่ 7 (เคียวรี) ทำให้ servlet ของคุณพร้อมใช้งานโดยใช้getQueryString
  • ตอนที่ 8 (แฟรกเมนต์) ไม่ได้ถูกส่งไปยังเซิร์ฟเวอร์และมีความเกี่ยวข้องและรู้จักกับลูกค้าเท่านั้น

ต่อไปนี้จะเก็บไว้เสมอ (ยกเว้นความแตกต่างในการเข้ารหัส URL):

requestURI = contextPath + servletPath + pathInfo

ตัวอย่างต่อไปนี้จากข้อมูลจำเพาะของServlet 3.0มีประโยชน์มาก:


หมายเหตุ:ภาพดังต่อไปนี้ฉันไม่มีเวลาที่จะสร้างใน HTML:

ป้อนคำอธิบายรูปภาพที่นี่


16

พิจารณาความสับสนของ servlet ต่อไปนี้:

   <servlet>
        <servlet-name>NewServlet</servlet-name>
        <servlet-class>NewServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>NewServlet</servlet-name>
        <url-pattern>/NewServlet/*</url-pattern>
    </servlet-mapping>

ตอนนี้เมื่อฉันกด URL http://localhost:8084/JSPTemp1/NewServlet/jhiมันจะเรียกใช้NewServletเนื่องจากมีการจับคู่กับรูปแบบที่อธิบายไว้ข้างต้น

ที่นี่:

getRequestURI() =  /JSPTemp1/NewServlet/jhi
getPathInfo() = /jhi

เรามีสิ่งเหล่านี้:

  • getPathInfo()

    ส่งคืน
    สตริงซึ่งถอดรหัสโดยเว็บคอนเทนเนอร์โดยระบุข้อมูลพา ธ พิเศษที่มาหลังพา ธ servlet แต่ก่อนสตริงการสืบค้นใน URL คำขอ หรือ null หาก URL ไม่มีข้อมูลเส้นทางพิเศษใด ๆ

  • getRequestURI()

    ส่งคืน
    สตริงที่มีส่วนของ URL จากชื่อโปรโตคอลจนถึงสตริงการสืบค้น

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