Twoja standardowa aplikacja Spring MVC będzie obsługiwać wszystkie żądania za pośrednictwem DispatcherServlet
konta zarejestrowanego w kontenerze serwletów.
Te DispatcherServlet
spojrzenia na jego ApplicationContext
oraz, jeśli jest dostępny, ApplicationContext
zarejestrowany w ContextLoaderListener
specjalnych ziaren potrzebnych do konfiguracji jego wniosek służąc logicznego. Te ziarna są opisane w dokumentacji .
Chyba najważniejsza, fasolowa HandlerMapping
mapa 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 HandlerMapping
implementacji. Najpopularniejsza implementacja obsługuje kontrolery z adnotacjami, ale istnieją również inne implementacje.
Dokument javadoc ofHandlerMapping
dalej opisuje, jak muszą zachowywać się implementacje.
DispatcherServlet
Wyszukuje wszystkie ziarna tego typu i rejestruje je w jakimś celu (można dostosować). Obsługując żądanie, DispatcherServlet
pętle przechodzą przez te HandlerMapping
obiekty i testują każdy z nich, getHandler
aby 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 DispatcherServlet
nazwie SomeName
i albo zgłasza, NoHandlerFoundException
albo natychmiast zatwierdza odpowiedź z kodem stanu 404 Not Found.
Dlaczego nie DispatcherServlet
znaleziono elementu, HandlerMapping
który mógłby obsłużyć moją prośbę?
Najpowszechniejszą HandlerMapping
implementacją jest RequestMappingHandlerMapping
, która obsługuje rejestrowanie @Controller
fasoli jako programów obsługi (tak naprawdę ich @RequestMapping
metody z adnotacjami). Możesz samodzielnie zadeklarować ziarno tego typu (za pomocą @Bean
lub <bean>
lub innego mechanizmu) lub skorzystać z wbudowanych opcji . To są:
- Dodaj adnotację do swojej
@Configuration
klasy za pomocą @EnableWebMvc
.
- Zadeklaruj
<mvc:annotation-driven />
członka w konfiguracji XML.
Jak opisuje powyższy link, oba zarejestrują RequestMappingHandlerMapping
fasolę (i kilka innych rzeczy). Jednak HandlerMapping
nie jest zbyt przydatny bez programu obsługi. RequestMappingHandlerMapping
oczekuje niektórych komponentów @Controller
bean, więc musisz je również zadeklarować za pomocą @Bean
metod w konfiguracji Java lub <bean>
deklaracji w konfiguracji XML lub przez skanowanie komponentów @Controller
klas 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ą @RequestMapping
metodę obsługi z adnotacjami.
Do spring-webmvc
oferty Biblioteka Inne wbudowane w HandlerMapping
implementacji. Na przykład BeanNameUrlHandlerMapping
mapy
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 HandlerMapping
modułów obsługi zarejestrowanego obiektu.
Jeśli nie zarejestrujesz niejawnie lub jawnie żadnych HandlerMapping
ziaren (lub jeśli detectAllHandlerMappings
tak true
), DispatcherServlet
zarejestruje niektóre wartości domyślne . Są one zdefiniowane w DispatcherServlet.properties
tym samym pakiecie co DispatcherServlet
klasa. Są BeanNameUrlHandlerMapping
i DefaultAnnotationHandlerMapping
(co jest podobne do, RequestMappingHandlerMapping
ale przestarzałe).
Debugowanie
Spring MVC będzie rejestrować programy obsługi zarejestrowane za pośrednictwem RequestMappingHandlerMapping
. Na przykład @Controller
polubienie
@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 @RequestMapping
muszą być zgodne, aby Spring MVC wybrał procedurę obsługi.
Inne HandlerMapping
implementacje 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ą ApplicationContext
konfigurację.
Inne typowe błędy
A DispatcherServlet
to po prostu typowy Java EE Servlet
. Rejestrujesz to za pomocą typowego <web.xml>
<servlet-class>
i <servlet-mapping>
deklaracji, lub bezpośrednio przez ServletContext#addServlet
a 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 DispatcherServlet
adresu URL z mapowaniem adresu /*
, zwracanie nazwy widoku z @RequestMapping
metody 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
, DisaptcherServlet
raport zgłosi
Nie znaleziono mapowanie żądania HTTP z URI [/Example/WEB-INF/jsps/example-view-name.jsp]
w DispatcherServlet
o nazwie „dyspozytora”
Ponieważ DispatcherServlet
jest odwzorowany na /*
i /*
dopasowuje wszystko (z wyjątkiem dokładnych dopasowań, które mają wyższy priorytet), DispatcherServlet
zostanie wybrany do obsługi forward
z JstlView
(zwróconego przez InternalResourceViewResolver
). W prawie każdym przypadku DispatcherServlet
nie zostanie skonfigurowany do obsługi takiego żądania .
Zamiast tego, w tym uproszczonym przypadku, powinieneś zarejestrować DispatcherServlet
to /
, 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.
@EnableWebMvc
w@Configuration
klasie z adnotacjami tego nie robi. Wszystko, co robi, to dodanie kilku domyślnych komponentów bean obsługi / adapterów Spring MVC do kontekstu aplikacji. Rejestracja wDispatcherServlet
celu wyświetlenia/
to całkowicie oddzielny proces, który można wykonać na kilka sposobów, które opisuję w sekcji Inne typowe błędy . Odpowiadam na pytanie zadane dwa akapity poniżej tego, co zacytowałeś.Rozwiązałem swój problem, gdy oprócz opisanego wcześniej: `
@Bean public InternalResourceViewResolver resolver() { InternalResourceViewResolver vr = new InternalResourceViewResolver(); vr.setPrefix("/WEB-INF/jsps/"); vr.setSuffix(".jsp"); return vr; }
added tomcat-embed-jasper:
`from: plik JSP nie jest renderowany w aplikacji internetowej Spring Boot
źródło
W moim przypadku postępowałem zgodnie z dokumentacją Interceptors Spring dla wersji 5.1.2 (podczas korzystania ze Spring Boot v2.0.4.RELEASE ) i
WebConfig
klasa miała adnotację@EnableWebMvc
, która wydawała się kolidować z czymś innym w mojej aplikacji, co zapobiegało mojemu statycznemu zasoby nie zostały poprawnie rozwiązane (tj. żadne pliki CSS ani JS nie zostały zwrócone do klienta).Po wypróbowaniu wielu różnych rzeczy, próbowałem usunięcie
@EnableWebMvc
i to działa!Edycja: oto dokumentacja referencyjna, która mówi, że należy usunąć
@EnableWebMvc
adnotacjęNajwyraźniej przynajmniej w moim przypadku konfiguruję już swoją aplikację Spring (chociaż nie używam
web.xml
ani żadnego innego pliku statycznego, zdecydowanie programistycznie), więc był tam konflikt.źródło
Spróbuj poprawić swój kod, wprowadzając następującą zmianę w pliku konfiguracyjnym. Konfiguracja Java jest używana zamiast
application.properties
. Nie zapomnij włączyć konfiguracji wconfigureDefaultServletHandling
metodzie.@Configuration @EnableWebMvc @ComponentScan public class WebConfig implements WebMvcConfigurer { @Override public void configureViewResolvers(ViewResolverRegistry registry) { registry.jsp("/WEB-INF/views/", ".jsp"); } @Override public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { configurer.enable(); } }
Używam gradle, twój powinien mieć następujące zależności w
pom.xml
:dependencies { compile group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '2.3.0.RELEASE' compile group: 'org.apache.tomcat.embed', name: 'tomcat-embed-jasper', version: '9.0.35' }
źródło
Natknąłem się na inny powód tego samego błędu. Może to być również spowodowane tym, że pliki klas nie zostały wygenerowane dla pliku controller.java. W rezultacie serwlet dyspozytora wymieniony w pliku web.xml nie może odwzorować go na odpowiednią metodę w klasie kontrolera.
@Controller Class Controller{ @RequestMapping(value="/abc.html")//abc is the requesting page public void method() {.....} }
W eclipse w Project-> wybierz clean -> Build Project. Sprawdź, czy plik klasy został wygenerowany dla pliku kontrolera w builds w twoim obszarze roboczym.
źródło
Dla mnie odkryłem, że moje klasy docelowe zostały wygenerowane we wzorcu folderu, który nie jest taki sam jak źródło. Prawdopodobnie w eclipse dodaję foldery do przechowywania moich kontrolerów i nie dodaję ich jako pakietów. Skończyło się na tym, że zdefiniowałem nieprawidłową ścieżkę w konfiguracji wiosennej.
Moja klasa docelowa generowała klasy w aplikacji, a ja odnosiłem się do com.happy.app
<context:annotation-config /> <context:component-scan base-package="com.happy.app"></context:component-scan>
Dodałem pakiety (nie foldery) dla com.happy.app i przeniosłem pliki z folderów do pakietów w eclipse i rozwiązałem problem.
źródło
Wyczyść swój serwer. Może usuń serwer i dodaj projekt jeszcze raz i uruchom.
Zatrzymaj serwer Tomcat
Kliknij serwer prawym przyciskiem myszy i wybierz „Wyczyść”
Ponownie kliknij serwer prawym przyciskiem myszy i wybierz „Wyczyść katalog roboczy Tomcat”
źródło
W moim przypadku bawiłem się importem pomocniczych plików konfiguracyjnych java do głównego pliku konfiguracyjnego java. Podczas tworzenia pomocniczych plików konfiguracyjnych zmieniłem nazwę głównej klasy konfiguracyjnej, ale nie udało mi się zaktualizować nazwy w web.xml. Tak więc za każdym razem, gdy restartowałem serwer Tomcat, nie widziałem programów obsługi mapowania odnotowanych w konsoli Eclipse IDE, a kiedy próbowałem przejść do mojej strony głównej, widziałem ten błąd:
Poprawka polegała na zaktualizowaniu pliku web.xml tak, aby stara nazwa „WebConfig” była zamiast „MainConfig”, po prostu zmieniając jej nazwę tak, aby odzwierciedlała najnowszą nazwę głównego pliku konfiguracyjnego java (gdzie „MainConfig” jest dowolna, a słowa „ Użyte w tym miejscu słowo „Web” i „Main” nie jest wymaganiem dotyczącym składni). MainConfig był ważny, ponieważ był to plik, który skanował komponent w poszukiwaniu „WebController”, mojej wiosennej klasy kontrolera mvc, która obsługuje moje żądania WWW.
@ComponentScan(basePackageClasses={WebController.class})
web.xml miał to:
Plik web.xml ma teraz:
Teraz widzę mapowanie w oknie konsoli:
Moja strona internetowa ponownie się ładuje.
źródło
Miałem ten sam problem co
**No mapping found for HTTP request with URI [/some/path] in DispatcherServlet with name SomeName**
Po analizowaniu przez 2 do 4 dni odkryłem pierwotną przyczynę. Pliki klas nie zostały wygenerowane po uruchomieniu projektu. Kliknąłem zakładkę projektu.
Wygenerowano pliki klas dla kodu źródłowego. To rozwiązało mój problem. Aby sprawdzić, czy pliki klas zostały wygenerowane, czy nie, sprawdź folder Build w folderze projektu.
źródło