Ihre Standard-Spring-MVC-Anwendung bedient alle Anforderungen über eine DispatcherServlet, die Sie bei Ihrem Servlet-Container registriert haben.
Das DispatcherServletprüft seine ApplicationContextund, falls verfügbar, die ApplicationContextmit einem ContextLoaderListenerfü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 HandlerMappingMap
Eingehende Anforderungen an Handler und eine Liste von Vor- und Nachprozessoren (Handler-Interceptors) basierend auf einigen Kriterien, deren Details je nach HandlerMappingImplementierung 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 DispatcherServletfindet alle Beans dieses Typs und registriert sie in einer bestimmten Reihenfolge (kann angepasst werden). Während der Bearbeitung einer Anforderung DispatcherServletwerden diese HandlerMappingObjekte 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 DispatcherServletmit dem Namen Somenamen
und löst entweder a aus NoHandlerFoundExceptionoder schreibt die Antwort sofort mit einem 404 Not Found-Statuscode fest.
Warum hat das nicht DispatcherServleteine finden , HandlerMappingdie meine Anfrage umgehen konnte?
Die häufigste HandlerMappingImplementierung ist RequestMappingHandlerMappingdie Registrierung von @ControllerBeans als Handler (eigentlich ihre mit @RequestMappingAnmerkungen versehenen Methoden). Sie können eine Bean dieses Typs entweder selbst (mit @Beanoder mit einem <bean>anderen Mechanismus) deklarieren oder die integrierten Optionen verwenden . Diese sind:
- Kommentieren Sie Ihre
@ConfigurationKlasse mit @EnableWebMvc.
- Deklarieren Sie ein
<mvc:annotation-driven />Mitglied in Ihrer XML-Konfiguration.
Wie der obige Link beschreibt, registrieren beide eine RequestMappingHandlerMappingBean (und eine Reihe anderer Dinge). Allerdings ist eine HandlerMappingnicht sehr nützlich ist, ohne einen Handler. RequestMappingHandlerMappingerwartet einige @ControllerBeans, daher müssen Sie diese auch deklarieren, durch @BeanMethoden in einer Java-Konfiguration oder <bean>Deklarationen in einer XML-Konfiguration oder durch Komponentenscannen von @Controllerannotierten 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 @RequestMappingMethode für kommentierte Handler verarbeitet wird.
Die spring-webmvcBibliothek bietet weitere integrierte HandlerMappingImplementierungen. Zum Beispiel BeanNameUrlHandlerMappingKarten
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 HandlerMappingHandler des registrierten Objekts entspricht.
Wenn Sie keine HandlerMappingBeans implizit oder explizit registrieren (oder wenn dies der FalldetectAllHandlerMappings ist true), DispatcherServletwerden einige Standardeinstellungen registriert . Diese werden im DispatcherServlet.propertiesselben Paket wie die DispatcherServletKlasse definiert. Sie sind BeanNameUrlHandlerMappingund DefaultAnnotationHandlerMapping(ähnlich, RequestMappingHandlerMappingaber veraltet).
Debuggen
Spring MVC protokolliert registrierte Handler RequestMappingHandlerMapping. Zum Beispiel ein @ControllerLike
@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 @RequestMappingmüssen übereinstimmen, damit Spring MVC den Handler auswählt.
Andere HandlerMappingImplementierungen 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 ApplicationContextKonfiguration.
Andere häufige Fehler
A DispatcherServletist nur ein typischer Java EE Servlet. Sie registrieren es mit Ihrer typischen <web.xml> <servlet-class>und <servlet-mapping>Deklaration oder direkt ServletContext#addServletin einem WebApplicationInitializeroder 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 DispatcherServletmit einer URL-Zuordnung von zu registrieren /*, einen Ansichtsnamen von einer @RequestMappingHandler-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 Exampleder DisaptcherServletBericht erstellt
Keine Zuordnung gefunden für HTTP - Anforderung mit URI [/Example/WEB-INF/jsps/example-view-name.jsp]in DispatcherServletmit dem Namen ‚Dispatcher‘
Da das DispatcherServletauf alles abgebildet ist /*und /*mit allem übereinstimmt (mit Ausnahme von exakten Übereinstimmungen, die eine höhere Priorität haben), wird das DispatcherServletausgewählt, um das forwardvon dem JstlView(von dem zurückgegebenen InternalResourceViewResolver) zu verarbeiten. In fast allen Fällen wird der DispatcherServletnicht für die Verarbeitung einer solchen Anforderung konfiguriert .
In diesem vereinfachten Fall sollten Sie stattdessen das DispatcherServletto 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.