Twoja standardowa aplikacja Spring MVC będzie obsługiwać wszystkie żądania za pośrednictwem DispatcherServletkonta zarejestrowanego w kontenerze serwletów.
Te DispatcherServletspojrzenia na jego ApplicationContextoraz, jeśli jest dostępny, ApplicationContextzarejestrowany w ContextLoaderListenerspecjalnych ziaren potrzebnych do konfiguracji jego wniosek służąc logicznego. Te ziarna są opisane w dokumentacji .
Chyba najważniejsza, fasolowa HandlerMappingmapa typu
przychodzące żądania do osób obsługujących oraz lista pre- i postprocesorów (przechwytywaczy obsługi) w oparciu o pewne kryteria, których szczegóły różnią się w zależności od HandlerMappingimplementacji. Najpopularniejsza implementacja obsługuje kontrolery z adnotacjami, ale istnieją również inne implementacje.
Dokument javadoc ofHandlerMapping dalej opisuje, jak muszą zachowywać się implementacje.
DispatcherServletWyszukuje wszystkie ziarna tego typu i rejestruje je w jakimś celu (można dostosować). Obsługując żądanie, DispatcherServletpętle przechodzą przez te HandlerMappingobiekty i testują każdy z nich, getHandleraby znaleźć taki, który może obsłużyć przychodzące żądanie, reprezentowane jako standard HttpServletRequest. Od wersji 4.3.x, jeśli nie znajdzie żadnego , rejestruje ostrzeżenie , które widzisz
Nie znaleziono mapowania dla żądania HTTP z identyfikatorem URI [/some/path]w DispatcherServletnazwie SomeName
i albo zgłasza, NoHandlerFoundExceptionalbo natychmiast zatwierdza odpowiedź z kodem stanu 404 Not Found.
Dlaczego nie DispatcherServletznaleziono elementu, HandlerMappingktóry mógłby obsłużyć moją prośbę?
Najpowszechniejszą HandlerMappingimplementacją jest RequestMappingHandlerMapping, która obsługuje rejestrowanie @Controllerfasoli jako programów obsługi (tak naprawdę ich @RequestMappingmetody z adnotacjami). Możesz samodzielnie zadeklarować ziarno tego typu (za pomocą @Beanlub <bean>lub innego mechanizmu) lub skorzystać z wbudowanych opcji . To są:
- Dodaj adnotację do swojej
@Configurationklasy za pomocą @EnableWebMvc.
- Zadeklaruj
<mvc:annotation-driven />członka w konfiguracji XML.
Jak opisuje powyższy link, oba zarejestrują RequestMappingHandlerMappingfasolę (i kilka innych rzeczy). Jednak HandlerMappingnie jest zbyt przydatny bez programu obsługi. RequestMappingHandlerMappingoczekuje niektórych komponentów @Controllerbean, więc musisz je również zadeklarować za pomocą @Beanmetod w konfiguracji Java lub <bean>deklaracji w konfiguracji XML lub przez skanowanie komponentów @Controllerklas z adnotacjami w obu. Upewnij się, że te ziarna są obecne.
Jeśli otrzymujesz komunikat ostrzegawczy i 404, a wszystkie powyższe elementy zostały poprawnie skonfigurowane, to wysyłasz żądanie do niewłaściwego identyfikatora URI , który nie jest obsługiwany przez wykrytą @RequestMappingmetodę obsługi z adnotacjami.
Do spring-webmvcoferty Biblioteka Inne wbudowane w HandlerMappingimplementacji. Na przykład BeanNameUrlHandlerMappingmapy
od adresów URL do fasoli z nazwami zaczynającymi się od ukośnika („/”)
i zawsze możesz napisać własne. Oczywiście musisz się upewnić, że wysyłane żądanie pasuje do co najmniej jednego z HandlerMappingmodułów obsługi zarejestrowanego obiektu.
Jeśli nie zarejestrujesz niejawnie lub jawnie żadnych HandlerMappingziaren (lub jeśli detectAllHandlerMappingstak true), DispatcherServletzarejestruje niektóre wartości domyślne . Są one zdefiniowane w DispatcherServlet.propertiestym samym pakiecie co DispatcherServletklasa. Są BeanNameUrlHandlerMappingi DefaultAnnotationHandlerMapping(co jest podobne do, RequestMappingHandlerMappingale przestarzałe).
Debugowanie
Spring MVC będzie rejestrować programy obsługi zarejestrowane za pośrednictwem RequestMappingHandlerMapping. Na przykład @Controllerpolubienie
@Controller
public class ExampleController {
@RequestMapping(path = "/example", method = RequestMethod.GET, headers = "X-Custom")
public String example() {
return "example-view-name";
}
}
zarejestruje następujące informacje na poziomie INFO
Mapped "{[/example],methods=[GET],headers=[X-Custom]}" onto public java.lang.String com.spring.servlet.ExampleController.example()
Opisuje zarejestrowane mapowanie. Gdy zobaczysz ostrzeżenie, że nie znaleziono programu obsługi, porównaj identyfikator URI w komunikacie z mapowaniem wymienionym tutaj. Wszystkie ograniczenia określone w pliku @RequestMappingmuszą być zgodne, aby Spring MVC wybrał procedurę obsługi.
Inne HandlerMappingimplementacje rejestrują własne instrukcje, które powinny wskazywać na ich mapowania i odpowiadające im funkcje obsługi.
Podobnie, włącz rejestrowanie Springa na poziomie DEBUG, aby zobaczyć, które ziarna rejestruje Spring. Powinien raportować, które klasy z adnotacjami znajdzie, które pakiety skanuje i które fasole inicjuje. Jeśli nie ma tych, których się spodziewałeś, sprawdź swoją ApplicationContextkonfigurację.
Inne typowe błędy
A DispatcherServletto po prostu typowy Java EE Servlet. Rejestrujesz to za pomocą typowego <web.xml> <servlet-class>i <servlet-mapping>deklaracji, lub bezpośrednio przez ServletContext#addServleta WebApplicationInitializer, lub z jakimkolwiek mechanizmem używanym przez Spring boot. W związku z tym musisz polegać na logice odwzorowywania adresów URL określonej w specyfikacji serwletu , patrz Rozdział 12. Zobacz także
Mając to na uwadze, częstym błędem jest rejestrowanie DispatcherServletadresu URL z mapowaniem adresu /*, zwracanie nazwy widoku z @RequestMappingmetody obsługi i oczekiwanie na renderowanie strony JSP. Na przykład rozważmy metodę obsługi, taką jak
@RequestMapping(path = "/example", method = RequestMethod.GET)
public String example() {
return "example-view-name";
}
z InternalResourceViewResolver
@Bean
public InternalResourceViewResolver resolver() {
InternalResourceViewResolver vr = new InternalResourceViewResolver();
vr.setPrefix("/WEB-INF/jsps/");
vr.setSuffix(".jsp");
return vr;
}
można oczekiwać, że żądanie zostanie przekazane do zasobu JSP w ścieżce /WEB-INF/jsps/example-view-name.jsp. To się nie stanie. Zamiast tego, zakładając nazwę kontekstu Example, DisaptcherServletraport zgłosi
Nie znaleziono mapowanie żądania HTTP z URI [/Example/WEB-INF/jsps/example-view-name.jsp]w DispatcherServleto nazwie „dyspozytora”
Ponieważ DispatcherServletjest odwzorowany na /*i /*dopasowuje wszystko (z wyjątkiem dokładnych dopasowań, które mają wyższy priorytet), DispatcherServletzostanie wybrany do obsługi forwardz JstlView(zwróconego przez InternalResourceViewResolver). W prawie każdym przypadku DispatcherServletnie zostanie skonfigurowany do obsługi takiego żądania .
Zamiast tego, w tym uproszczonym przypadku, powinieneś zarejestrować DispatcherServletto /, oznaczając go jako domyślny serwlet. Domyślnym serwletem jest ostatnie dopasowanie dla żądania. Umożliwi to typowemu kontenerowi serwletów wybranie wewnętrznej implementacji serwletu, odwzorowanej na *.jsp, do obsługi zasobu JSP (na przykład Tomcat JspServlet), przed próbą z domyślnym serwletem.
To właśnie widzisz na swoim przykładzie.