วิธีที่ดีที่สุดในการรับ URL ปัจจุบันใน Spring MVC คืออะไร


98

ฉันต้องการสร้าง URL ตาม URL ที่ลูกค้าใช้สำหรับคำขอที่ใช้งานอยู่ มีอะไรที่ฉลาดไปกว่าการใช้HttpServletRequestออบเจ็กต์ปัจจุบันและgetParameter...()วิธีการสร้าง URL ที่สมบูรณ์ขึ้นมาใหม่รวมถึง (และเท่านั้น) เป็นพารามิเตอร์ GET

ชี้แจง: ถ้าเป็นไปได้ฉันต้องการลาออกจากการใช้HttpServletRequestวัตถุ

คำตอบ:


112

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

public static String makeUrl(HttpServletRequest request)
{
    return request.getRequestURL().toString() + "?" + request.getQueryString();
}

ฉันไม่รู้วิธีดำเนินการกับสิ่งอำนวยความสะดวก Spring MVC

หากคุณต้องการเข้าถึงคำขอปัจจุบันโดยไม่ผ่านทุกที่คุณจะต้องเพิ่ม Listener ใน web.xml:

<listener>
    <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>

จากนั้นใช้สิ่งนี้เพื่อรับคำขอที่ผูกไว้กับเธรดปัจจุบัน:

((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest()

โอเคนี่เป็นแนวทางที่คล้ายกับสิ่งที่ฉันทำจนถึงตอนนี้ แต่ฉันกำลังหาวิธีทำโดยไม่ต้องใช้HttpServletRequestวัตถุจริงๆ นี่เป็นเพราะฉันใช้คลาสตัวช่วย / วิธีการหลายอย่างและฉันไม่ต้องการส่งผ่านวัตถุคำขอทุกครั้ง
Koraktor

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

ขอบคุณสำหรับคำเตือนเกี่ยวกับผู้ฟัง ฉันยังใหม่กับ Spring (และการพัฒนาเว็บ Java โดยทั่วไป) UrlUtilsตอนนี้ผมใช้รหัสของคุณร่วมกับฤดูใบไม้ผลิของการรักษาความปลอดภัย ใช้งานได้เหมือนมีเสน่ห์
Koraktor

ในกรณีของฉันมันให้เส้นทางมุมมองที่เกี่ยวข้องแทนการเรียกดู url มีความคิดเกี่ยวกับเรื่องนี้ไหม
Md. Shougat Hossain

โดยไม่ต้องใช้ HttpServletRequest ... ตัวอย่างในวิธีการควบคุม Spring Boot เราไม่ได้รับสิ่งนี้เป็นพารามิเตอร์ ... จากนั้นคำตอบอื่น ๆ ของการโทรแบบคงที่ดูดี ServletUriComponentsBuilder.fromCurrentRequest () toUriString ()
msanjay

79

แทนที่จะใช้RequestContextHolderโดยตรงคุณยังสามารถใช้ServletUriComponentsBuilderและวิธีการคงที่:

  • ServletUriComponentsBuilder.fromCurrentContextPath()
  • ServletUriComponentsBuilder.fromCurrentServletMapping()
  • ServletUriComponentsBuilder.fromCurrentRequestUri()
  • ServletUriComponentsBuilder.fromCurrentRequest()

พวกเขาใช้ RequestContextHolderภายใต้ประทุน แต่ให้ความยืดหยุ่นเพิ่มเติมในการสร้าง URL ใหม่โดยใช้ความสามารถของUriComponentsBuilder.

ตัวอย่าง:

ServletUriComponentsBuilder builder = ServletUriComponentsBuilder.fromCurrentRequestUri();
builder.scheme("https");
builder.replaceQueryParam("someBoolean", false);
URI newUri = builder.build().toUri();

@ m4rtin ฉันตอบคำถามของตัวเองและไม่ต้องการให้เครดิตกับคนที่ช่วยฉันแก้ปัญหาในตอนแรก
Koraktor

2
ยังดีสำหรับ Spring 5 ฉันจัดการเพื่อรับ URL ภายในConstraintValidatorด้วยServletUriComponentsBuilder.fromCurrentRequestUri().toUriString();.
GuiRitter

17

URI Class ของ Java สามารถช่วยคุณได้:

public static String getCurrentUrl(HttpServletRequest request){
    URL url = new URL(request.getRequestURL().toString());
    String host  = url.getHost();
    String userInfo = url.getUserInfo();
    String scheme = url.getProtocol();
    String port = url.getPort();
    String path = request.getAttribute("javax.servlet.forward.request_uri");
    String query = request.getAttribute("javax.servlet.forward.query_string");

    URI uri = new URI(scheme,userInfo,host,port,path,query,null)
    return uri.toString();
}

ให้ชื่อโฮสต์เท่านั้น
vivex


3

คุณยังสามารถเพิ่ม a UriComponentsBuilderลงในลายเซ็นวิธีการของวิธีควบคุมของคุณ Spring จะฉีดอินสแตนซ์ของตัวสร้างที่สร้างขึ้นจากคำขอปัจจุบัน

@GetMapping
public ResponseEntity<MyResponse> doSomething(UriComponentsBuilder uriComponentsBuilder) {
    URI someNewUriBasedOnCurrentRequest = uriComponentsBuilder
            .replacePath(null)
            .replaceQuery(null)
            .pathSegment("some", "new", "path")
            .build().toUri();
  //...
}

การใช้ตัวสร้างคุณสามารถเริ่มสร้าง URI ได้โดยตรงตามคำขอปัจจุบันเช่นแก้ไขเซ็กเมนต์เส้นทาง

โปรดดูUriComponentsBuilderMethodArgumentResolver ด้วย


โปรดทราบว่าการแทรกUriComponentsBuilderไม่รวมเส้นทางและพารามิเตอร์การสืบค้นของคำขอ หากคุณต้องการเข้าถึงสิ่งเหล่านั้นใช้ServletUriComponentsBuilder.fromCurrentRequest()หรือฉีดอินสแตนซ์HttpServletRequestและใช้งานServletUriComponentsBuilder.fromRequest(request)
Martin Devillers

0

หากคุณต้องการ URL จนถึงชื่อโฮสต์และไม่ใช้เส้นทางของ Apache Lib ทั่วไปStringUtilและจาก URL แยกย่อยจนถึง /indexOf

public static String getURL(HttpServletRequest request){
   String fullURL = request.getRequestURL().toString();
   return fullURL.substring(0,StringUtils.ordinalIndexOf(fullURL, "/", 3)); 
}

ตัวอย่าง:หากfullurlเป็นhttps://example.com/path/after/url/แล้ว เอาท์พุทจะเป็น https://example.com

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