Jak uzyskać identyfikator URI żądania bez ścieżki kontekstu?

127

Metoda request.getRequestURI () zwraca identyfikator URI ze ścieżką kontekstu.

Na przykład, jeśli adres URL podstawa wniosku jest http://localhost:8080/myapp/(czyli ścieżka kontekstu jest MojaApl ) i wzywam request.getRequestURI()do http://localhost:8080/myapp/secure/users, powróci /myapp/secure/users.

Czy jest jakiś sposób, abyśmy mogli uzyskać tylko tę część /secure/users, tj. Identyfikator URI bez ścieżki kontekstu?

rzemieślnik
źródło

Odpowiedzi:

158

Jeśli jesteś wewnątrz serwletu przedniego kontrolera, który jest mapowany na wzorzec prefiksu, możesz po prostu użyć HttpServletRequest#getPathInfo().

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

Zakładając, że serwlet w twoim przykładzie jest odwzorowany /secure, to zwróci to, /usersco będzie jedyną interesującą informacją wewnątrz typowego serwletu kontrolera frontowego.

Jeśli jednak serwlet jest mapowany na wzorzec sufiksu (przykłady adresów URL nie wskazują jednak, że tak jest), lub gdy faktycznie znajdujesz się w filtrze (gdy aplet, który ma zostać wywołany, nie jest jeszcze koniecznie określony, więc getPathInfo()może powrócić null), najlepszym rozwiązaniem jest samodzielne przesłanie podciągu URI żądania na podstawie długości ścieżki kontekstu przy użyciu zwykłej Stringmetody:

HttpServletRequest request = (HttpServletRequest) req;
String path = request.getRequestURI().substring(request.getContextPath().length());
// ...
BalusC
źródło
Czy jest powód, aby używać tego zamiast getServletPath()? Piszę filtr i zauważyłem, że getPathInfo()zwraca null, ale getServletPath()zwraca ścieżkę bez kontekstu (nadaje się do przekazania do dyspozytora żądania).
Jason C,
@JasonC: Zgodnie z odpowiedzią getPathInfo()zwraca wartość null, jeśli serwlet kontrolera frontowego nie jest odwzorowany na wzorzec prefiksu.
BalusC
Tak. Miałem na myśli: czy jest jakiś powód, dla którego wolisz getPathInfo zamiast getServletPath? Wiele innych wysoko ocenionych odpowiedzi również nie używa getServletPath, co sprawia, że ​​jestem podejrzliwy i zastanawiam się. Mam projekt serwletu, nad którym pracuję i próbuję trochę dopracować swoje umiejętności.
Jason C
1
@JasonC: ścieżka serwletu może ulec zmianie, jeśli masz zainstalowaną platformę MVC opartą na serwletach, taką jak JSF lub Spring MVC. Będzie wtedy reprezentować wewnętrzną ścieżkę struktury MVC (np. /foo.xhtmlZamiast /foo.jsf), a nie rzeczywisty identyfikator URI żądania (ten, który użytkownik końcowy zobaczy na pasku adresu przeglądarki). Oryginalna ścieżka serwletu jest w takim przypadku możliwa do rozwiązania jako atrybut żądania z kluczem RequestDispatcher.FORWARD_SERVLET_PATH. W każdym razie pytanie wyraźnie prosi o podanie identyfikatora URI żądania (jak w pasku adresu przeglądarki), więc odpowiedź jest oparta na tym.
BalusC
74
request.getRequestURI().substring(request.getContextPath().length())
fforw
źródło
Niesamowite! To jest dokładnie to, czego szukałem.
rzemieślnik
4
+1 Myślę, że to lepsza odpowiedź niż getPathInfo ze względu na fakt, że getPathInfo może mieć wartość null i inne dziwactwa. Różne kody Spring wykonują metodę getContextPath i usuwają ją z identyfikatora URI, tak jak zrobiłeś to zamiast getPathInfo.
Adam Gent,
32

Dzięki Springowi możesz:

String path = new UrlPathHelper().getPathWithinApplication(request);
James
źródło
1
Oczywiście miałoby sens zachowanie instancji UrlPathHelper np. Jako zmiennej składowej klasy ...
James
Jak możemy uzyskać rzeczywisty adres URL mapowania żądań? Proszę poprowadzić tutaj: stackoverflow.com/questions/60446807/…
Pra_A
14

getPathInfo () czasami zwraca wartość null. W dokumentacji HttpServletRequest

Ta metoda zwraca wartość null, jeśli nie ma dodatkowych informacji o ścieżce.

Potrzebuję ścieżki do pliku bez ścieżki kontekstowej w filtrze i getPathInfo () zwraca mi wartość null. Więc używam innej metody: 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
źródło
8

Jeśli używasz request.getPathInfo () wewnątrz filtru, zawsze wydaje się, że otrzymujesz wartość null (przynajmniej z jetty).

Ten zwięzły, nieprawidłowy błąd + odpowiedź nawiązuje do problemu, który moim zdaniem:

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

Podejrzewam, że jest to związane z faktem, że filtry działają, zanim serwlet otrzyma żądanie. Może to być błąd kontenera lub oczekiwane zachowanie, którego nie byłem w stanie zidentyfikować.

Dostępna jest jednak ścieżka contextPath, więc rozwiązanie fforws działa nawet w filtrach. Nie lubię robić tego ręcznie, ale implementacja jest zepsuta lub

thetoolman
źródło
5

Sposobem na to jest wyłączenie ścieżki kontekstu serwletu z identyfikatora URI żądania.

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

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

Przeczytaj tutaj .

Peter Mmm
źródło
-1

Być może możesz po prostu użyć metody podziału, aby wyeliminować `` / myapp '', na przykład:

string[] uris=request.getRequestURI().split("/");
string uri="/"+uri[1]+"/"+uris[2];
Colin
źródło
3
Spowoduje to problem, jeśli wdrożę moją aplikację jako root, a jej podstawowy adres URL stanie się localhost: 8080 . W tym przypadku request.getRequestURI () zwróci „/ secure / user”, a metoda podziału spowoduje tutaj problem. Kod nie powinien być zależny od wdrożenia.
rzemieślnik