Twoja standardowa aplikacja Spring MVC będzie obsługiwać wszystkie żądania poprzez numer DispatcherServlet
, który został zarejestrowany w kontenerze Serwlet.
DispatcherServlet
patrzy na jego ApplicationContext
i, jeśli są dostępne, w ApplicationContext
zarejestrowany z ContextLoaderListener
specjalnego fasola potrzebuje skonfigurować swój wniosek serwującą logiki. These beans are described in the documentation.
zapewne najważniejszym, fasola typu HandlerMapping
mapy
przychodzące żądania do ładowarki oraz wykaz pre- i post-procesorów (przechwytujących obsługę) w oparciu o pewne kryteria szczegóły, które różnią się od Implementacja HandlerMapping
. Najpopularniejsza implementacja obsługuje kontrolery z adnotacjami, ale inne implementacje istnieją również dobrze jako .
W dalszej części opisu opisano sposób implementacji.
Urządzenie DispatcherServlet
wyszukuje wszystkie ziarna tego typu i rejestruje je w dowolnej kolejności (można dostosować). Podczas obsługi żądania, DispatcherServlet
wykonuje pętle za pośrednictwem tych obiektów HandlerMapping
i testuje je za pomocą getHandler
, aby znaleźć taki, który może obsłużyć przychodzące żądanie, reprezentowane jako standard HttpServletRequest
. Począwszy od 4.3.x, jeśli nie znajdzie żadnego, to logs the warning że widać
Nie znaleziono mapowanie żądania HTTP z URI [/some/path]
w DispatcherServlet
o nazwie somename
i either rzuca NoHandlerFoundException
lub bezpośrednio zatwierdza odpowiedź z kodem statusu 404 Not Found.
Dlaczego DispatcherServlet
nie znalazł HandlerMapping
, który mógłby obsłużyć moją prośbę?
Najczęstszym HandlerMapping
realizacja jest RequestMappingHandlerMapping
, który obsługuje rejestracji @Controller
fasolę jako ładowarki (naprawdę ich @RequestMapping
adnotacją metody). Możesz zadeklarować tego typu fasolę (z @Bean
lub <bean>
lub innym mechanizmem) lub możesz użyć the built-in options. Są to:
- Opisz swoją klasę
@Configuration
za pomocą @EnableWebMvc
.
- Zadeklaruj element
<mvc:annotation-driven />
w konfiguracji XML.
Jak opisuje powyższy link, obie z nich zarejestrują fasolę RequestMappingHandlerMapping
(i kilka innych rzeczy). Jednak HandlerMapping
nie jest zbyt przydatny bez obsługi. RequestMappingHandlerMapping
oczekuje niektórych fasoli @Controller
, więc należy je zadeklarować również za pomocą metod @Bean
w konfiguracji Java lub deklaracji <bean>
w konfiguracji XML lub poprzez skanowanie komponentów w klasach z przypisami w @Controller
. Upewnij się, że te ziarna są obecne.
Jeśli otrzymujesz komunikat ostrzegawczy i 404 i skonfigurowaniu wszystkich powyższych poprawnie, następnie wysyłasz prośbę o niewłaściwym URI taki, który nie jest obsługiwany przez wykrytą @RequestMapping
Metoda obsługi adnotowanych.
Biblioteka spring-webmvc
oferuje inne wbudowane implementacje HandlerMapping
. Na przykład, BeanNameUrlHandlerMapping
odwzorowuje
z adresów URL do ziaren o nazwach zaczynających się od ukośnika („/”)
i zawsze można napisać własne. Oczywiście, musisz upewnić się, że wysłane zapytanie pasuje do co najmniej jednego z zarejestrowanych obiektów obiektu HandlerMapping
.
nie Jeśli nie jawnie lub niejawnie zarejestrować żadnych HandlerMapping
fasoli (lub jeśli detectAllHandlerMappings
jest true
), The DispatcherServlet
rejestrów niektóre defaults. Są one zdefiniowane w DispatcherServlet.properties
w tym samym pakiecie co klasa DispatcherServlet
. Są to: BeanNameUrlHandlerMapping
i DefaultAnnotationHandlerMapping
(które są podobne do RequestMappingHandlerMapping
, ale są przestarzałe).
Debugowanie
Wiosna MVC będzie koparki zarejestrowane przez RequestMappingHandlerMapping
zalogować. Na przykład, @Controller
jak
@Controller
public class ExampleController {
@RequestMapping(path = "/example", method = RequestMethod.GET, headers = "X-Custom")
public String example() {
return "example-view-name";
}
}
będzie rejestrować następujące INFO na poziomie
Mapped "{[/example],methods=[GET],headers=[X-Custom]}" onto public java.lang.String com.spring.servlet.ExampleController.example()
ten opisuje odwzorowanie zarejestrowany. Po wyświetleniu ostrzeżenia o tym, że nie znaleziono programu obsługi, porównaj identyfikator URI w komunikacie z wymienionym tutaj mapowaniem. Wszystkie ograniczenia określone w @RequestMapping
muszą pasować do Spring MVC, aby wybrać handler.
Inne implementacje HandlerMapping
rejestrują własne instrukcje, które powinny wskazywać na ich odwzorowania i odpowiednie programy obsługi.
W podobny sposób włącz rejestrację sprężyny na poziomie DEBUG, aby zobaczyć, które ziarna rejestruje sprężyna. Powinien on raportować, które z adnotowanych klas znajduje, które pakiety skanuje i które z nich inicjuje. Jeśli te, których oczekiwałeś, nie są obecne, przejrzyj konfigurację ApplicationContext
.
Inne częste błędy
DispatcherServlet
jest po prostu typowy Java EE Servlet
. Zarejestrować go z typowej deklaracji <web.xml>
<servlet-class>
i <servlet-mapping>
lub bezpośrednio przez ServletContext#addServlet
w WebApplicationInitializer
lub z dowolnym mechanizmem Spring boot używa. Jako takie, trzeba polegać na url odwzorowania logiką określoną w Servlet specification Rozdział 12. Patrz także
Mając to na uwadze, częstym błędem jest, aby zarejestrować DispatcherServlet
z mapowaniem adresów URL pod numerem /*
, zwracając nazwę widoku z metody obsługi obsługi @RequestMapping
i oczekując na renderowanie strony JSP. Na przykład, rozważmy metodę uchwytu 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 się spodziewać prośba być forwarded do zasobu JSP na ścieżce /WEB-INF/jsps/example-view-name.jsp
. To się nie stanie. Zamiast tego, przyjmując nazwę kontekstu Example
The DisaptcherServlet
zgłosi
Nie mapowanie znalezionych dla żądania HTTP z URI [/Example/WEB-INF/jsps/example-view-name.jsp]
w DispatcherServlet
o nazwie 'dyspozytora'
Ponieważ DispatcherServlet
jest odwzorowywany /*
i /*
dopasowuje wszystko (oprócz dokładnych dopasowań, które mają wyższy priorytet), forward
zostanie wybrany do obsługi forward
z JstlView
(zwrócony przez InternalResourceViewResolver
).W prawie każdym przypadku DispatcherServlet
nie zostanie skonfigurowany do obsługi takich żądań.
Zamiast tego w tym uproszczonym przypadku należy zarejestrować DispatcherServlet
na /
, oznaczając go jako domyślny serwlet. Domyślny serwlet to ostatnie dopasowanie dla żądania. Pozwoli to typowemu kontenerowi serwletu wybrać wewnętrzną implementację serwletu, zmapowaną na *.jsp
, aby obsłużyć zasoby JSP (na przykład Tomcat ma JspServlet
), zanim spróbujesz z domyślnym serwletem.
To właśnie widzisz w swoim przykładzie.
Jak można "zarejestrować DispatcherServlet do /, znakowanie to jest domyślny serwlet. " ? Czy możesz podzielić się tym fragmentem kodu? –
@SaifMasadeh Jeśli spojrzysz na link do specyfikacji serwletu w odpowiedzi (lub wpisie SO poniżej), zobaczysz, że '/' jest specjalnym mapowaniem dla kontenerów serwletów, wskazującym "domyślny" serwlet, który zostanie wybrany jeśli nie zostaną dopasowane żadne inne odwzorowania. –
@SotiriosDelimanolis Czy możesz rzucić okiem na repozytorium github, które utworzyłem https://github.com/saifmasadeh/WeatherBoard/blob/master/src/main/java/com/demo/controller/RootController.java? –