Wie erhalte ich einen Anforderungs-URI ohne Kontextpfad?

127

Die Methode request.getRequestURI () gibt den URI mit dem Kontextpfad zurück.

Zum Beispiel, wenn die Basis - URL einer Anwendung ist http://localhost:8080/myapp/(dh der Kontextpfad ist myapp ), und ich rufe request.getRequestURI()für http://localhost:8080/myapp/secure/users, kehrt es /myapp/secure/users.

Gibt es eine Möglichkeit, nur diesen Teil zu erhalten /secure/users, dh den URI ohne Kontextpfad?

Handwerker
quelle

Antworten:

158

Wenn Sie sich in einem Front-Controller-Servlet befinden, das einem Präfixmuster zugeordnet ist, können Sie es einfach verwenden HttpServletRequest#getPathInfo().

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

Angenommen, das Servlet in Ihrem Beispiel ist zugeordnet /secure, wird dies zurückgegeben. Dies sind /usersdie Informationen, die innerhalb eines typischen Front-Controller-Servlets von alleinigem Interesse sind.

Wenn das Servlet jedoch einem Suffixmuster zugeordnet ist (Ihre URL-Beispiele zeigen jedoch nicht an, dass dies der Fall ist) oder wenn Sie sich tatsächlich in einem Filter befinden (wenn das aufzurufende Servlet noch nicht unbedingt bestimmt ist) getPathInfo()könnte zurückkehren null), dann ist es am besten, den Anforderungs-URI basierend auf der Länge des Kontextpfads mit der üblichen StringMethode selbst zu unterteilen:

HttpServletRequest request = (HttpServletRequest) req;
String path = request.getRequestURI().substring(request.getContextPath().length());
// ...
BalusC
quelle
Gibt es einen Grund, dies anstelle von zu verwenden getServletPath()? Ich schreibe einen Filter und habe festgestellt, dass er getPathInfo()zurückgibt null, aber getServletPath()den Pfad abzüglich des Kontexts zurückgibt (geeignet für die Weitergabe an den Anforderungs-Dispatcher).
Jason C
@JasonC: Gibt wie beantwortet getPathInfo()null zurück, wenn das Front-Controller-Servlet keinem Präfixmuster zugeordnet ist.
BalusC
Ja. Ich meinte: Gibt es einen Grund, warum Sie getPathInfo gegenüber getServletPath bevorzugen? Viele der anderen hoch bewerteten Antworten hier verwenden auch nicht getServletPath, was mich misstrauisch macht und warum ich mich frage. Ich habe ein Servlet-Projekt, an dem ich arbeite, und ich versuche, meine Fähigkeiten zu verbessern.
Jason C
1
@JasonC: Der Servlet-Pfad kann sich ändern, wenn ein servletbasiertes MVC-Framework wie JSF oder Spring MVC installiert ist. Es stellt dann den internen Pfad des MVC-Frameworks dar (z. B. /foo.xhtmlanstelle von /foo.jsf) und nicht den tatsächlichen Anforderungs-URI (der als Endbenutzer in der Adressleiste des Browsers angezeigt wird). Der ursprüngliche Servlet-Pfad ist in diesem Fall jedoch als Anforderungsattribut mit Schlüssel auflösbar RequestDispatcher.FORWARD_SERVLET_PATH. In jedem Fall fragt die Frage explizit nach dem Anforderungs-URI (wie in der Adressleiste des Browsers), sodass die Antwort darauf basiert.
BalusC
74
request.getRequestURI().substring(request.getContextPath().length())
fforw
quelle
Genial! Genau das habe ich gesucht.
Handwerker
4
+1 Ich denke, dies ist eine bessere Antwort als getPathInfo, da getPathInfo null und andere Kuriositäten sein kann. Verschiedene Spring-Codes führen getContextPath aus und entfernen es aus dem URI, genau wie Sie es anstelle von getPathInfo getan haben.
Adam Gent
32

Mit Spring können Sie Folgendes tun:

String path = new UrlPathHelper().getPathWithinApplication(request);
James
quelle
1
Natürlich wäre es sinnvoll, eine Instanz des UrlPathHelper zu behalten, z. B. als Klassenmitgliedsvariable ...
James
Wie können wir die tatsächliche Anforderungszuordnungs-URL erhalten? Bitte führen Sie hier: stackoverflow.com/questions/60446807/…
Pra_A
14

getPathInfo () gibt manchmal null zurück. In der Dokumentation HttpServletRequest

Diese Methode gibt null zurück, wenn keine zusätzlichen Pfadinformationen vorhanden waren.

Ich muss den Pfad zur Datei ohne Kontextpfad in Filter abrufen und getPathInfo () gibt mir null zurück. Also benutze ich eine andere Methode: 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
quelle
8

Wenn Sie request.getPathInfo () in einem Filter verwenden, scheinen Sie immer null zu erhalten (zumindest mit Anlegestelle).

Dieser knappe ungültige Fehler + Antwort spielt auf das Problem an, das ich denke:

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

Ich vermute, es hängt damit zusammen, dass Filter ausgeführt werden, bevor das Servlet die Anforderung erhält. Möglicherweise handelt es sich um einen Containerfehler oder ein erwartetes Verhalten, das ich nicht identifizieren konnte.

Der contextPath ist jedoch verfügbar, sodass die fforws-Lösung auch in Filtern funktioniert. Ich mag es nicht, es von Hand machen zu müssen, aber die Implementierung ist kaputt oder

der Werkzeugmann
quelle
5

Eine Möglichkeit, dies zu tun, besteht darin, den Servelet-Kontextpfad vom Anforderungs-URI abzusetzen.

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

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

Lesen Sie hier .

PeterMmm
quelle
-1

Vielleicht können Sie einfach die Split-Methode verwenden, um das '/ myapp' zu entfernen, zum Beispiel:

string[] uris=request.getRequestURI().split("/");
string uri="/"+uri[1]+"/"+uris[2];
Colin
quelle
3
Dies führt zu Problemen, wenn ich meine Anwendung als Root bereitstelle und ihre Basis-URL zu localhost: 8080 wird . In diesem Fall würde request.getRequestURI () "/ secure / user" zurückgeben und Ihre Split-Methode wird hier Probleme verursachen. Der Code sollte nicht von der Bereitstellung abhängig sein.
Handwerker