Ihre Standard-Spring-MVC-Anwendung bedient alle Anforderungen über eine DispatcherServlet
, die Sie bei Ihrem Servlet-Container registriert haben.
Das DispatcherServlet
prüft seine ApplicationContext
und, falls verfügbar, die ApplicationContext
mit einem ContextLoaderListener
für spezielle Beans registrierten , die es benötigt, um seine Anforderungs-Serving-Logik einzurichten. Diese Beans sind in der Dokumentation beschrieben .
Die wohl wichtigsten Bohnen vom Typ HandlerMapping
Map
Eingehende Anforderungen an Handler und eine Liste von Vor- und Nachprozessoren (Handler-Interceptors) basierend auf einigen Kriterien, deren Details je nach HandlerMapping
Implementierung variieren . Die beliebteste Implementierung unterstützt kommentierte Controller, es gibt jedoch auch andere Implementierungen.
Das Javadoc vonHandlerMapping
beschreibt weiter, wie sich Implementierungen verhalten müssen.
Das DispatcherServlet
findet alle Beans dieses Typs und registriert sie in einer bestimmten Reihenfolge (kann angepasst werden). Während der Bearbeitung einer Anforderung DispatcherServlet
werden diese HandlerMapping
Objekte durchlaufen und jedes von ihnen getestet getHandler
, um eines zu finden, das die eingehende Anforderung verarbeiten kann, die als Standard dargestellt wird HttpServletRequest
. Ab 4.3.x, wenn es irgendwelche nicht finden , es protokolliert die Warnung , dass Sie sehen ,
Keine Zuordnung gefunden für HTTP - Anforderung mit URI [/some/path]
in DispatcherServlet
mit dem Namen Somenamen
und löst entweder a aus NoHandlerFoundException
oder schreibt die Antwort sofort mit einem 404 Not Found-Statuscode fest.
Warum hat das nicht DispatcherServlet
eine finden , HandlerMapping
die meine Anfrage umgehen konnte?
Die häufigste HandlerMapping
Implementierung ist RequestMappingHandlerMapping
die Registrierung von @Controller
Beans als Handler (eigentlich ihre mit @RequestMapping
Anmerkungen versehenen Methoden). Sie können eine Bean dieses Typs entweder selbst (mit @Bean
oder mit einem <bean>
anderen Mechanismus) deklarieren oder die integrierten Optionen verwenden . Diese sind:
- Kommentieren Sie Ihre
@Configuration
Klasse mit @EnableWebMvc
.
- Deklarieren Sie ein
<mvc:annotation-driven />
Mitglied in Ihrer XML-Konfiguration.
Wie der obige Link beschreibt, registrieren beide eine RequestMappingHandlerMapping
Bean (und eine Reihe anderer Dinge). Allerdings ist eine HandlerMapping
nicht sehr nützlich ist, ohne einen Handler. RequestMappingHandlerMapping
erwartet einige @Controller
Beans, daher müssen Sie diese auch deklarieren, durch @Bean
Methoden in einer Java-Konfiguration oder <bean>
Deklarationen in einer XML-Konfiguration oder durch Komponentenscannen von @Controller
annotierten Klassen in beiden. Stellen Sie sicher, dass diese Bohnen vorhanden sind.
Wenn Sie die Warnmeldung und einen 404 erhalten und alle oben genannten Punkte korrekt konfiguriert haben, senden Sie Ihre Anfrage an den falschen URI , der nicht von einer erkannten @RequestMapping
Methode für kommentierte Handler verarbeitet wird.
Die spring-webmvc
Bibliothek bietet weitere integrierte HandlerMapping
Implementierungen. Zum Beispiel BeanNameUrlHandlerMapping
Karten
von URLs zu Beans mit Namen, die mit einem Schrägstrich beginnen ("/")
und du kannst immer deine eigenen schreiben. Natürlich müssen Sie sicherstellen, dass die Anforderung, die Sie senden, mindestens einem der HandlerMapping
Handler des registrierten Objekts entspricht.
Wenn Sie keine HandlerMapping
Beans implizit oder explizit registrieren (oder wenn dies der FalldetectAllHandlerMappings
ist true
), DispatcherServlet
werden einige Standardeinstellungen registriert . Diese werden im DispatcherServlet.properties
selben Paket wie die DispatcherServlet
Klasse definiert. Sie sind BeanNameUrlHandlerMapping
und DefaultAnnotationHandlerMapping
(ähnlich, RequestMappingHandlerMapping
aber veraltet).
Debuggen
Spring MVC protokolliert registrierte Handler RequestMappingHandlerMapping
. Zum Beispiel ein @Controller
Like
@Controller
public class ExampleController {
@RequestMapping(path = "/example", method = RequestMethod.GET, headers = "X-Custom")
public String example() {
return "example-view-name";
}
}
protokolliert Folgendes auf INFO-Ebene
Mapped "{[/example],methods=[GET],headers=[X-Custom]}" onto public java.lang.String com.spring.servlet.ExampleController.example()
Dies beschreibt die registrierte Zuordnung. Wenn Sie die Warnung sehen, dass kein Handler gefunden wurde, vergleichen Sie den URI in der Nachricht mit der hier aufgeführten Zuordnung. Alle im Abschnitt angegebenen Einschränkungen @RequestMapping
müssen übereinstimmen, damit Spring MVC den Handler auswählt.
Andere HandlerMapping
Implementierungen protokollieren ihre eigenen Anweisungen, die auf ihre Zuordnungen und die entsprechenden Handler verweisen sollen.
Aktivieren Sie auf ähnliche Weise die Spring-Protokollierung auf DEBUG-Ebene, um zu sehen, welche Beans Spring registriert. Es sollte angeben, welche mit Anmerkungen versehenen Klassen gefunden werden, welche Pakete gescannt und welche Beans initialisiert werden. Wenn die erwarteten nicht vorhanden sind, überprüfen Sie Ihre ApplicationContext
Konfiguration.
Andere häufige Fehler
A DispatcherServlet
ist nur ein typischer Java EE Servlet
. Sie registrieren es mit Ihrer typischen <web.xml>
<servlet-class>
und <servlet-mapping>
Deklaration oder direkt ServletContext#addServlet
in einem WebApplicationInitializer
oder mit einem beliebigen Mechanismus, den Spring Boot verwendet. Daher müssen Sie sich auf die in der Servlet-Spezifikation angegebene URL-Zuordnungslogik verlassen , siehe Kapitel 12. Siehe auch
In diesem Sinne besteht ein häufiger Fehler darin, das DispatcherServlet
mit einer URL-Zuordnung von zu registrieren /*
, einen Ansichtsnamen von einer @RequestMapping
Handler-Methode zurückzugeben und zu erwarten, dass eine JSP gerendert wird. Betrachten Sie beispielsweise eine Handlermethode wie
@RequestMapping(path = "/example", method = RequestMethod.GET)
public String example() {
return "example-view-name";
}
mit einem InternalResourceViewResolver
@Bean
public InternalResourceViewResolver resolver() {
InternalResourceViewResolver vr = new InternalResourceViewResolver();
vr.setPrefix("/WEB-INF/jsps/");
vr.setSuffix(".jsp");
return vr;
}
Sie könnte die Anforderung erwarten werden weitergeleitet auf dem Weg zu einer JSP Ressource /WEB-INF/jsps/example-view-name.jsp
. Das wird nicht passieren. Unter der Annahme eines Kontextnamens von wird stattdessen Example
der DisaptcherServlet
Bericht erstellt
Keine Zuordnung gefunden für HTTP - Anforderung mit URI [/Example/WEB-INF/jsps/example-view-name.jsp]
in DispatcherServlet
mit dem Namen ‚Dispatcher‘
Da das DispatcherServlet
auf alles abgebildet ist /*
und /*
mit allem übereinstimmt (mit Ausnahme von exakten Übereinstimmungen, die eine höhere Priorität haben), wird das DispatcherServlet
ausgewählt, um das forward
von dem JstlView
(von dem zurückgegebenen InternalResourceViewResolver
) zu verarbeiten. In fast allen Fällen wird der DispatcherServlet
nicht für die Verarbeitung einer solchen Anforderung konfiguriert .
In diesem vereinfachten Fall sollten Sie stattdessen das DispatcherServlet
to registrieren /
und es als Standardservlet markieren. Das Standardservlet ist die letzte Übereinstimmung für eine Anforderung. Auf diese Weise kann Ihr typischer Servlet-Container eine interne Servlet-Implementierung auswählen *.jsp
, die der JSP-Ressource zugeordnet ist (z. B. Tomcat JspServlet
), bevor Sie es mit dem Standardservlet versuchen.
Das sehen Sie in Ihrem Beispiel.