Почему 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?





это должно быть каноническое сообщение для вопросов об этом предупреждении.

2509   3  

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> или другой механизм) или вы можете использовать в размере. Это:

  1. аннотации @Configuration класс @EnableWebMvc.
  2. объявления <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 EE Servlet. Вы регистрируете его с вашим типичным <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] in DispatcherServlet С именем 'диспетчер'

потому что 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

    Ничего не найдено.