Unterschied zwischen / und / * im URL-Muster der Servlet-Zuordnung


175

Der bekannte Code:

<servlet-mapping>
    <servlet-name>main</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>

<servlet-mapping>
    <servlet-name>main</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

Mein Verständnis ist, dass /*Karten zu http://host:port/context/*.

Wie wäre es /? Es wird sicher nicht http://host:port/contextnur root zugeordnet. In der Tat wird es akzeptieren http://host:port/context/hello, aber ablehnen http://host:port/context/hello.jsp.

Kann jemand erklären, wie http://host:port/context/helloabgebildet wird?

Antworten:


267

<url-pattern>/*</url-pattern>

Das /*On-Servlet überschreibt alle anderen Servlets, einschließlich aller vom Servlet-Container bereitgestellten Servlets, z. B. das Standardservlet und das JSP-Servlet. Was auch immer Sie anfordern, es wird in diesem Servlet enden. Dies ist daher ein schlechtes URL-Muster für Servlets. Normalerweise möchten Sie nur /*auf einem verwenden Filter. Es ist möglich, die Anforderung an jedes der Servlets weiterzuleiten, die durch Aufrufen ein spezifischeres URL-Muster abhören FilterChain#doFilter().

<url-pattern>/</url-pattern>

Das /überschreibt kein anderes Servlet. Es ersetzt nur das integrierte Standardservlet des Servletcontainers für alle Anforderungen, die keinem anderen registrierten Servlet entsprechen. Dies wird normalerweise nur für statische Ressourcen (CSS / JS / image / etc) und Verzeichnislisten aufgerufen. Das integrierte Standardservlet des Servletcontainers kann auch HTTP-Cache-Anforderungen, Medien-Streaming (Audio / Video) und das Herunterladen von Dateien verarbeiten. Normalerweise möchten Sie das Standardservlet nicht überschreiben, da Sie sich sonst um alle seine Aufgaben kümmern müssten, was nicht gerade trivial ist (die JSF-Dienstprogrammbibliothek OmniFaces verfügt über ein Open Source- Beispiel). Dies ist daher auch ein schlechtes URL-Muster für Servlets. Der Grund, warum JSP-Seiten dieses Servlet nicht treffen, liegt daran, dass das integrierte JSP-Servlet des Servletcontainers aufgerufen wird, das standardmäßig bereits dem spezifischeren URL-Muster zugeordnet ist *.jsp.

<url-pattern></url-pattern>

Dann gibt es noch das leere String-URL-Muster . Dies wird aufgerufen, wenn der Kontextstamm angefordert wird. Dies unterscheidet sich von dem <welcome-file>Ansatz, dass es nicht aufgerufen wird, wenn ein Unterordner angefordert wird. Dies ist höchstwahrscheinlich das URL-Muster, nach dem Sie tatsächlich suchen, falls Sie ein " Homepage-Servlet " möchten . Ich muss nur zugeben, dass ich intuitiv erwarten würde, dass das URL-Muster für leere Zeichenfolgen und das URL-Muster /für Schrägstriche genau umgekehrt definiert werden, sodass ich verstehen kann, dass viele Starter diesbezüglich verwirrt waren. Aber es ist was es ist.

Front Controller

Falls Sie tatsächlich beabsichtigen , ein Front - Controller - Servlet haben, dann würden Sie am besten auf einem bestimmten URL - Muster Karte wie *.html, *.do, /pages/*, /app/*usw. Sie können die Front - Controller - URL - Muster und Abdeckung statischen Ressourcen auf einem gemeinsamen URL - Muster verstecken wie /resources/*, /static/*etc. mit Hilfe eines Servlet - Filter. Siehe auch So verhindern Sie, dass statische Ressourcen vom Front-Controller-Servlet verarbeitet werden, das auf / * zugeordnet ist . Beachten Sie, dass Spring MVC über ein integriertes Servlet /für statische Ressourcen verfügt. Daher können Sie den Front-Controller zuordnen, wenn Sie in Spring ein allgemeines URL-Muster für statische Ressourcen konfigurieren. Siehe auch Wie gehe ich mit statischen Inhalten in Spring MVC um?


9
Vielen Dank. Nach einigen Recherchen möchte ich einen subtilen Punkt klarstellen. / überschreibt das Standardservlet, das der Webserver installiert. Beispielsweise installiert Tomcat ein DefaultServlet, das statische Ressourcen bereitstellt. Die Verwendung von / beseitigt das Standard-Servlet als (höchstwahrscheinlich unerwünschte) Nebenwirkung.
Candy Chiu

Nun, ich würde es nicht "Überschreiben" nennen, sondern "Ersetzen". Es kann nützlich sein, das Standardservlet so zu ersetzen.
BalusC

1
<url-pattern> </ url-pattern> löst einen Fehler aus: Ungültiges <url-pattern> in der Servlet-Zuordnung
schlank

Die Fehlermeldung stammte von Tomcat, nicht von meiner IDE. Ich benutze jedoch Tomcat 6, also ist das wahrscheinlich das Problem;)
schlank

2
@BalusC, kannst du mir bitte sagen, welches /**Muster anzeigt?
Sajib Acharya

45

Ich möchte die Antwort von BalusC durch die Zuordnungsregeln und ein Beispiel ergänzen.

Zuordnungsregeln aus der Servlet 2.5-Spezifikation:

  1. Ordnen Sie die genaue URL zu
  2. Platzhalterpfade zuordnen
  3. Kartenerweiterungen
  4. Dem Standardservlet zuordnen

In unserem Beispiel gibt es drei Servlets. / ist das von uns installierte Standardservlet. Tomcat installiert zwei Servlets für jsp und jspx. Also zu kartierenhttp://host:port/context/hello

  1. Als nächstes werden keine genauen URL-Servlets installiert.
  2. Als nächstes werden keine Servlets für Platzhalterpfade installiert.
  3. Stimmt nicht mit den nächsten Erweiterungen überein.
  4. Dem Standardservlet zuordnen, zurückgeben.

Zuordnen http://host:port/context/hello.jsp

  1. Als nächstes werden keine genauen URL-Servlets installiert.
  2. Als nächstes werden keine Servlets für Platzhalterpfade installiert.
  3. Erweiterungsservlet gefunden, zurück.

25

Vielleicht müssen Sie auch wissen, wie URLs zugeordnet werden, da ich 404stundenlang gelitten habe . Es gibt zwei Arten von Handlern, die Anforderungen bearbeiten. BeanNameUrlHandlerMappingund SimpleUrlHandlerMapping. Wenn wir a definiert haben servlet-mapping, verwenden wir SimpleUrlHandlerMapping. Eine Sache, die wir wissen müssen, ist, dass diese beiden Handler eine gemeinsame Eigenschaft haben, alwaysUseFullPathdie standardmäßig lautet false.

falseDies bedeutet, dass Spring nicht den vollständigen Pfad verwendet, um eine URL einem Controller zuzuordnen. Was heißt das? Es bedeutet, wenn Sie Folgendes definieren servlet-mapping:

<servlet-mapping>
    <servlet-name>viewServlet</servlet-name>
    <url-pattern>/perfix/*</url-pattern>
</servlet-mapping>

Der Handler verwendet das *Teil tatsächlich , um die Steuerung zu finden. Auf dem folgenden Controller wird beispielsweise ein 404Fehler angezeigt, wenn Sie ihn mit anfordern/perfix/api/feature/doSomething

@Controller()
@RequestMapping("/perfix/api/feature")
public class MyController {
    @RequestMapping(value = "/doSomething", method = RequestMethod.GET) 
    @ResponseBody
    public String doSomething(HttpServletRequest request) {
        ....
    }
}

Es passt perfekt zusammen, oder? Aber warum 404. Wie bereits erwähnt, ist der Standardwert von alwaysUseFullPathfalse. Dies bedeutet, dass in Ihrer Anfrage nur /api/feature/doSomethingein entsprechender Controller gefunden wird, aber kein Controller kümmert sich um diesen Pfad. Sie müssen entweder Ihre URL ändern /perfix/perfix/api/feature/doSomethingoder perfixaus der MyController-Basis entfernen @RequestingMapping.


8

Ich denke, Candys Antwort ist größtenteils richtig. Es gibt einen kleinen Teil, den ich anders denke.

So ordnen Sie den Host zu: port / context / hello.jsp

  1. Als nächstes werden keine genauen URL-Servlets installiert.
  2. Servlets für Platzhalterpfade gefunden , zurückgeben.

Ich glaube, warum "/ *" nicht mit host: port / context / hello übereinstimmt, weil es "/ hello" als Pfad anstelle einer Datei behandelt (da es keine Erweiterung hat).


2

Der wesentliche Unterschied zwischen /*und /besteht darin, dass ein Servlet mit Zuordnung /*vor jedem Servlet mit einer Erweiterungszuordnung (wie *.html) ausgewählt wird, während ein Servlet mit Zuordnung /erst ausgewählt wird, nachdem Erweiterungszuordnungen berücksichtigt wurden (und für jede Anforderung verwendet wird, die dies nicht tut). passt zu nichts anderem --- es ist das "Standard-Servlet").

Insbesondere wird eine /*Zuordnung immer vor einer /Zuordnung ausgewählt. Beides verhindert, dass Anforderungen das eigene Standardservlet des Containers erreichen.

Entweder wird nur nach Servlet-Zuordnungen ausgewählt, die exakte Übereinstimmungen (wie /foo/bar) aufweisen, und nach Pfadzuordnungen, die länger als /*(wie /foo/*) sind. Beachten Sie, dass die Zuordnung leerer Zeichenfolgen genau mit dem Kontext root ( http://host:port/context/) übereinstimmt .

Siehe Kapitel 12 der Java-Servlet-Spezifikation, verfügbar in Version 3.1 unter http://download.oracle.com/otndocs/jcp/servlet-3_1-fr-eval-spec/index.html .

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.