Почему Spring MVC отвечает 404 и сообщает "нет сопоставления для HTTP-запроса с URI [ ... ] в DispatcherServlet"?
я пишу приложение Spring MVC, развернутое на Tomcat. См. следующий минимальный, полный и проверяемый пример:
public class Application extends AbstractAnnotationConfigDispatcherServletInitializer {
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[] { };
}
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[] { SpringServletConfig.class };
}
protected String[] getServletMappings() {
return new String[] { "/*" };
}
}
здесь SpringServletConfig и
@Configuration
@ComponentScan("com.example.controllers")
@EnableWebMvc
public class SpringServletConfig {
@Bean
public InternalResourceViewResolver resolver() {
InternalResourceViewResolver vr = new InternalResourceViewResolver();
vr.setPrefix("/WEB-INF/jsps/");
vr.setSuffix(".jsp");
return vr;
}
}
наконец, у меня есть @Controller в пакете com.example.controllers
@Controller
public class ExampleController {
@RequestMapping(path = "/home", method = RequestMethod.GET)
public String example() {
return "index";
}
}
имя контекста моего приложения Example. Когда я отправляю запрос на
http://localhost:8080/Example/home
приложение отвечает с HTTP-статусом 404 и регистрирует следующее
WARN o.s.web.servlet.PageNotFound - No mapping found for HTTP request with URI `[/Example/WEB-INF/jsps/index.jsp]` in `DispatcherServlet` with name 'dispatcher'
у меня есть ОСП ресурса на /WEB-INF/jsps/index.jsp Я ожидал, что Spring MVC будет использовать мой контроллер для обработки запроса и пересылки в JSP, так почему же он отвечает 404?
это должно быть каноническое сообщение для вопросов об этом предупреждении.
3 ответов:
ваше стандартное приложение Spring MVC будет обслуживать все запросы через
DispatcherServletчто вы зарегистрировались в своем контейнере сервлетов.The
DispatcherServletсмотрит на своеApplicationContextи, если имеется,ApplicationContextзарегистрированы сContextLoaderListenerдля специальных бобов ему нужно настроить свою логику обслуживания запросов. эти бобы описаны в документации.возможно, самый важный, бобы типа
HandlerMappingкартавходящие запросы к обработчикам и список пре-и постпроцессоров (обработчик перехватчиков) на основе некоторых критериев, детали которых варьируются на
HandlerMappingреализация. Самая популярная реализация поддерживает аннотированные контроллеры, но другие реализации существуют как что ж.The javadoc из
HandlerMappingдалее описывается, как должны вести себя реализации.The
DispatcherServletнаходит все бобы этого введите и зарегистрируйте их в определенном порядке (можно настроить). Во время обслуживания запроса,DispatcherServletпросматривает этиHandlerMappingобъекты и проверяет каждый из них сgetHandlerчтобы найти тот, который может обрабатывать входящий запрос, представленный как стандартныйHttpServletRequest. Как на 4.3.x,если он не найдет никакого, это журналы предупреждение что вы видитене найдено сопоставление для HTTP-запроса с URI
[/some/path]наDispatcherServletС именем Содержатьсяи или бросает a
NoHandlerFoundExceptionили сразу же фиксирует ответ с кодом состояния 404 Not Found.почему
DispatcherServletнайтиHandlerMappingчто может справиться с моей просьбой?самый распространенный
HandlerMappingреализацияRequestMappingHandlerMapping, который обрабатывает регистрации@Controllerфасоль в качестве обработчиков (на самом деле их@RequestMappingаннотированных методов). Вы можете либо объявить Боб этого введите себя (с@Beanили<bean>или другой механизм) или вы можете использовать в размере. Это:
- аннотации
@Configurationкласс@EnableWebMvc.- объявления
<mvc:annotation-driven />член в вашей конфигурации XML.как описано в ссылке выше, оба они будут регистрировать a
RequestMappingHandlerMappingБоб (и куча других вещей). Однако,HandlerMappingне очень полезно без обработчика.RequestMappingHandlerMappingждет@Controllerбобы, поэтому вам нужно объявить их тоже, через@Beanметоды в конфигурации Java или<bean>объявления в конфигурации XML или через компонентное сканирование@Controllerаннотированные классы в любом из них. убедитесь, что эти бобы присутствуют.если вы получаете предупреждающее сообщение и 404 и вы настроили все выше правильно,тогда вы отправляете запрос не на тот URI, который не обрабатывается обнаружено
@RequestMappingаннотированный метод обработчика.The
spring-webmvcбиблиотека предлагает другие встроенныеHandlerMappingреализаций. Например,BeanNameUrlHandlerMappingкартыот URL-адресов до бобов с именами, которые начинаются с косой черты ("/")
и вы всегда можете написать свой собственный. Очевидно,вам нужно будет убедиться, что запрос, который вы отправляете, соответствует хотя бы одному из зарегистрированных
HandlerMappingобъекта дрессировщики.если вы неявно или явно не регистрируете какие-либо
HandlerMappingбобы (или еслиdetectAllHandlerMappingsиtrue), тоDispatcherServletрегистры некоторых по умолчанию. Они определены вDispatcherServlet.propertiesв том же пакете, что иDispatcherServletкласса. ОниBeanNameUrlHandlerMappingиDefaultAnnotationHandlerMapping(что похоже наRequestMappingHandlerMappingно не рекомендуется).отладка
Весна в MVC будет регистрировать обработчики, зарегистрированные через
RequestMappingHandlerMapping. Например,@Controllerкак@Controller public class ExampleController { @RequestMapping(path = "/example", method = RequestMethod.GET, headers = "X-Custom") public String example() { return "example-view-name"; } }будет регистрировать следующее на уровне информации
Mapped "{[/example],methods=[GET],headers=[X-Custom]}" onto public java.lang.String com.spring.servlet.ExampleController.example()это описывает зарегистрированное отображение. Когда вы видите предупреждение о том, что обработчик не найден, сравните URI в сообщении с приведенным здесь сопоставлением. Все ограничения указаны в
@RequestMappingдолжен соответствовать для Spring MVC, чтобы выбрать обработчик.другое
HandlerMappingреализации регистрируют свои собственные операторы, которые должны намек на их сопоставления и соответствующие обработчики.аналогично, включите Spring logging на уровне отладки, чтобы увидеть, какие регистры Beans Spring. Он должен сообщить, какие аннотированные классы он находит, какие пакеты он сканирует, и какие бобы он инициализирует. Если те, которые вы ожидали, не присутствуют, то просмотрите ваш
ApplicationContextконфигурации.другие распространенные ошибки
A
DispatcherServletэто просто типичный Java EEServlet. Вы регистрируете его с вашим типичным<web.xml><servlet-class>и<servlet-mapping>объявление, или сразу черезServletContext#addServletнаWebApplicationInitializer, или с любым механизмом Spring boot использует. Таким образом, вы должны полагаться на преобразование url логика, указанная в спецификацию servlet, см. Главу 12. Смотрите такжеимея это в виду, a распространенной ошибкой является регистрация
DispatcherServletс отображением url/*, возвращая имя представления от@RequestMappingметод-обработчик, и ожидал ССП, которые должны быть оказаны. Например, рассмотрим метод обработчика типа@RequestMapping(path = "/example", method = RequestMethod.GET) public String example() { return "example-view-name"; }с
InternalResourceViewResolver@Bean public InternalResourceViewResolver resolver() { InternalResourceViewResolver vr = new InternalResourceViewResolver(); vr.setPrefix("/WEB-INF/jsps/"); vr.setSuffix(".jsp"); return vr; }вы можете ожидать, что запрос будет переданы к ресурсу JSP по пути
/WEB-INF/jsps/example-view-name.jsp. Этого не будет. Вместо этого, предполагая имя контекстаExampleнаDisaptcherServletбудет докладне найдено сопоставление для HTTP-запроса с URI
[/Example/WEB-INF/jsps/example-view-name.jsp]inDispatcherServletС именем 'диспетчер'потому что
DispatcherServletсопоставляется/*и/*соответствует всему (кроме точных совпадений, которые имеют более высокий приоритет),DispatcherServletбудет выбран для обработкиforwardсJstlView(возвращеноInternalResourceViewResolver). почти в каждом случае,DispatcherServletне будет настроен для обработки такого запрос.вместо этого, в этом простом случае, вы должны зарегистрировать
DispatcherServletдо/, помечая его как сервлет по умолчанию. Сервлет по умолчанию является последним совпадением для запроса. Это позволит вашему типичному контейнеру сервлета выбрать внутреннюю реализацию сервлета, сопоставленную с*.jsp, для обработки ресурса JSP (например, Tomcat имеетJspServlet), прежде чем пытаться использовать сервлет по умолчанию.это то, что вы видите в вашем образец.
я решил свою проблему, когда в дополнение к описанному ранее:'
@Bean public InternalResourceViewResolver resolver() { InternalResourceViewResolver vr = new InternalResourceViewResolver(); vr.setPrefix("/WEB-INF/jsps/"); vr.setSuffix(".jsp"); return vr; }
added tomcat-embed-jasper:<dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> <scope>provided</scope> </dependency>` от кого:JSP-файл не отображается в веб-приложении Spring Boot
я наткнулся на другую причину той же ошибки. Это также может быть связано с файлами классов, не созданными для вашего контроллера.Java-файл. В результате чего сервлет диспетчера упоминается в web.xml не может сопоставить его с соответствующим методом в классе контроллера.
@Controller Class Controller{ @RequestMapping(value="/abc.html")//abc is the requesting page public void method() {.....} }в eclipse в разделе Проект - > выберите Очистить - >построить Project.Do проверьте, был ли создан файл класса для файла контроллера в разделе сборки в рабочей области.
Comments