Apa cara terbaik untuk mendapatkan URL saat ini di Spring MVC?

95

Saya ingin membuat URL berdasarkan URL yang digunakan oleh klien untuk permintaan aktif. Apakah ada yang lebih pintar daripada mengambil HttpServletRequestobjek saat ini dan itugetParameter...() metode untuk membangun kembali URL lengkap termasuk (dan hanya) parameter GET-nya.

Klarifikasi: Jika memungkinkan saya ingin mengundurkan diri dari menggunakan HttpServletRequestobjek.

Koraktor
sumber

Jawaban:

111

Ada dua metode untuk mengakses data ini dengan lebih mudah, tetapi antarmuka tidak menawarkan kemungkinan untuk mendapatkan seluruh URL dengan satu panggilan. Anda harus membuatnya secara manual:

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

Saya tidak tahu tentang cara melakukan ini dengan fasilitas MVC Spring.

Jika Anda ingin mengakses Permintaan saat ini tanpa meneruskannya ke mana pun, Anda harus menambahkan pendengar di web.xml:

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

Dan kemudian gunakan ini untuk mendapatkan permintaan yang terikat ke Thread saat ini:

((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest()
Daff
sumber
Oke, ini adalah pendekatan yang mirip dengan apa yang telah saya lakukan sejauh ini. Tapi saya mencari cara untuk melakukan ini tanpa benar-benar menggunakan HttpServletRequestobjek tersebut. Ini karena saya menggunakan beberapa kelas / metode pembantu dan saya tidak ingin meneruskan objek permintaan setiap saat.
Koraktor
Oke, saya mengerti maksud Anda dan menambahkan info yang Anda perlukan untuk mengakses permintaan saat ini tanpa menyebarkannya.
Daff
Terima kasih atas pengingatnya tentang pendengar. Saya masih baru mengenal Spring (dan pengembangan web Java secara umum). Saya sekarang menggunakan kode Anda yang dikombinasikan dengan Spring Security UrlUtils. Bekerja seperti pesona.
Koraktor
Dalam kasus saya ini memberikan jalur tampilan terkait alih-alih menelusuri url. Ada ide tentang ini?
Md. Shougat Hossain
76

Alih-alih menggunakan RequestContextHoldersecara langsung, Anda juga dapat menggunakan ServletUriComponentsBuilderdan metode statisnya:

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

Mereka menggunakan RequestContextHolderdi balik terpal, tetapi memberikan fleksibilitas tambahan untuk membuat URL baru menggunakan kemampuan UriComponentsBuilder.

Contoh:

ServletUriComponentsBuilder builder = ServletUriComponentsBuilder.fromCurrentRequestUri();
builder.scheme("https");
builder.replaceQueryParam("someBoolean", false);
URI newUri = builder.build().toUri();
Koraktor
sumber
@ m4rtin Saya menjawab pertanyaan saya sendiri dan tidak ingin mengambil pujian untuk orang yang awalnya membantu saya memecahkan masalah saya.
Koraktor
2
Juga bagus untuk Spring 5. Saya telah berhasil mendapatkan URL di dalam ConstraintValidatordengan ServletUriComponentsBuilder.fromCurrentRequestUri().toUriString();.
GuiRitter
16

Kelas URI Java dapat membantu Anda dalam hal ini:

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();
}
Reed Grey
sumber
ini hanya memberikan nama host
vivex
8

dalam file jsp:

request.getAttribute("javax.servlet.forward.request_uri")
andy
sumber
3

Anda juga dapat menambahkan a UriComponentsBuilderke tanda tangan metode metode pengontrol Anda. Spring akan memasukkan instance pembuat yang dibuat dari permintaan saat ini.

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

Dengan menggunakan pembangun, Anda dapat langsung mulai membuat URI berdasarkan permintaan saat ini, misalnya mengubah segmen jalur.

Lihat juga UriComponentsBuilderMethodArgumentResolver

Mathias Dpunkt
sumber
Perhatikan bahwa yang dimasukkan UriComponentsBuildertidak menyertakan jalur dan parameter kueri dari permintaan tersebut. Jika Anda perlu mengaksesnya, gunakan ServletUriComponentsBuilder.fromCurrentRequest()atau HttpServletRequestServletUriComponentsBuilder.fromRequest(request)
masukkan
-1

Jika Anda memerlukan URL hingga nama host dan bukan jalur, gunakan Lib Umum Apache StringUtil, dan dari URL ekstrak substring hingga indexOf ketiga /.

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

Contoh: Jika fullurl adalah https://example.com/path/after/url/maka output akan https://example.com

Sahil Chhabra
sumber