Bagaimana cara mendapatkan URI permintaan tanpa jalur konteks?

127

Metode request.getRequestURI () mengembalikan URI dengan jalur konteks.

Misalnya, jika URL dasar dari sebuah aplikasi adalah http://localhost:8080/myapp/(yaitu jalur konteks adalah myapp ), dan saya sebut request.getRequestURI()untuk http://localhost:8080/myapp/secure/users, itu akan kembali /myapp/secure/users.

Adakah cara agar kita hanya bisa mendapatkan bagian ini /secure/users, yaitu URI tanpa jalur konteks?

tukang
sumber

Jawaban:

158

Jika Anda berada di dalam servlet contoller depan yang dipetakan pada pola awalan, maka Anda dapat menggunakan HttpServletRequest#getPathInfo().

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

Dengan asumsi bahwa servlet dalam contoh Anda dipetakan /secure, maka ini akan mengembalikan /usersyang akan menjadi informasi yang menjadi kepentingan tunggal di dalam servlet pengontrol depan yang khas.

Namun, jika servlet dipetakan pada pola sufiks (contoh URL Anda tidak menunjukkan bahwa ini masalahnya), atau ketika Anda benar-benar berada di dalam filter (ketika servlet yang akan dipanggil belum ditentukan, jadi getPathInfo()dapat kembali null), maka taruhan terbaik Anda adalah membuat substring URI permintaan sendiri berdasarkan panjang jalur konteks menggunakan Stringmetode biasa :

HttpServletRequest request = (HttpServletRequest) req;
String path = request.getRequestURI().substring(request.getContextPath().length());
// ...
BalusC
sumber
Apakah ada alasan untuk menggunakan ini daripada getServletPath()? Saya sedang menulis filter dan saya perhatikan bahwa getPathInfo()mengembalikan null, tetapi getServletPath()mengembalikan jalur tanpa konteks (cocok untuk meneruskan ke dispatcher permintaan).
Jason C
@JasonC: Seperti yang dijawab, getPathInfo()mengembalikan null jika servlet pengontrol depan tidak dipetakan pada pola awalan.
BalusC
Ya. Maksud saya: apakah ada alasan Anda lebih memilih getPathInfo daripada getServletPath? Banyak jawaban skor tinggi lainnya di sini juga tidak menggunakan getServletPath, itulah yang membuat saya curiga dan mengapa saya bertanya-tanya. Saya punya proyek servlet yang sedang saya kerjakan dan saya mencoba mengasah sedikit keterampilan saya.
Jason C
1
@JasonC: jalur servlet dapat berubah ketika Anda memiliki kerangka kerja MVC berbasis servlet yang diinstal seperti JSF atau Spring MVC. Ini kemudian akan mewakili jalur internal kerangka kerja MVC (misalnya, /foo.xhtmlbukan /foo.jsf) dan bukan URI permintaan sebenarnya (yang akan dilihat pengguna akhir di bilah alamat browser). Jalur servlet asli dalam kasus seperti itu namun dapat diselesaikan sebagai atribut permintaan dengan kunci RequestDispatcher.FORWARD_SERVLET_PATH. Dengan cara apa pun, pertanyaan tersebut secara eksplisit meminta URI permintaan (seperti di bilah alamat browser), jadi jawabannya didasarkan pada itu.
BalusC
74
request.getRequestURI().substring(request.getContextPath().length())
fforw
sumber
Hebat! Inilah yang saya cari.
pengrajin
4
+1 Saya pikir ini adalah jawaban yang lebih baik daripada getPathInfo karena fakta bahwa getPathInfo bisa null dan keanehan lainnya. Berbagai kode Spring melakukan getContextPath dan menghapusnya dari URI seperti yang telah Anda lakukan alih-alih getPathInfo.
Adam Gent
32

Dengan Spring, Anda dapat melakukan:

String path = new UrlPathHelper().getPathWithinApplication(request);
James
sumber
1
Tentu saja akan masuk akal untuk menyimpan sebuah instance dari UrlPathHelper misalnya sebagai variabel anggota kelas ...
James
Bagaimana kami bisa mendapatkan url pemetaan permintaan yang sebenarnya? Harap
pandu di
14

getPathInfo () terkadang mengembalikan null. Dalam dokumentasi HttpServletRequest

Metode ini mengembalikan nol jika tidak ada informasi jalur tambahan.

Saya perlu mendapatkan jalur ke file tanpa jalur konteks di Filter dan getPathInfo () mengembalikan saya null. Jadi saya menggunakan metode lain: 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());
    ...

}
lukastymo
sumber
8

Jika Anda menggunakan request.getPathInfo () di dalam Filter, Anda sepertinya selalu mendapatkan null (setidaknya dengan jetty).

Bug + respons singkat yang tidak valid ini menyinggung masalah yang menurut saya:

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

Saya menduga ini terkait dengan fakta bahwa filter dijalankan sebelum servlet mendapat permintaan. Ini mungkin bug kontainer, atau perilaku yang diharapkan yang belum dapat saya identifikasi.

ContextPath tersedia, jadi solusi fforws bekerja bahkan dalam filter. Saya tidak suka melakukannya dengan tangan, tetapi implementasinya rusak atau

thetoolman
sumber
5

Cara untuk melakukannya adalah dengan menghentikan jalur konteks servelet dari URI permintaan.

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

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

Baca disini .

PeterMmm
sumber
-1

Mungkin Anda bisa menggunakan metode split untuk menghilangkan '/ myapp' misalnya:

string[] uris=request.getRequestURI().split("/");
string uri="/"+uri[1]+"/"+uris[2];
Colin
sumber
3
Ini akan menimbulkan masalah jika saya menerapkan aplikasi saya sebagai root dan URL dasarnya menjadi localhost: 8080 . Dalam kasus ini request.getRequestURI () akan mengembalikan "/ secure / user" dan metode pemisahan Anda akan menyebabkan masalah di sini. Kode tidak boleh bergantung pada penerapan.
pengrajin