표준 Spring MVC 애플리케이션은 DispatcherServlet
Servlet 컨테이너에 등록한를 통해 모든 요청을 처리합니다 .
DispatcherServlet
의에서 외모 ApplicationContext
와는 가능한 경우 ApplicationContext
에 등록 ContextLoaderListener
이 설정의 요청을 제공하는 로직이 필요 특별한 콩을 위해. 이러한 빈은 문서에 설명되어 있습니다 .
틀림없이 가장 중요한 유형 HandlerMapping
맵의 빈
핸들러에 대한 수신 요청과 HandlerMapping
구현에 따라 세부 사항이 다른 일부 기준에 기반한 전 처리기 및 후 처리기 (핸들러 인터셉터) 목록 . 가장 널리 사용되는 구현은 주석이 달린 컨트롤러를 지원하지만 다른 구현도 존재합니다.
의 javadoc는HandlerMapping
더는 구현이 행동해야하는 방법에 대해 설명합니다.
(가) DispatcherServlet
이 유형의 모든 콩을 발견하고 어떤 순서로 등록 (사용자 정의 할 수 있음). 요청을 처리하는 동안 DispatcherServlet
은 이러한 HandlerMapping
객체를 반복 하고 각 객체를 테스트 getHandler
하여 표준으로 표시되는 수신 요청을 처리 할 수있는 객체 를 찾습니다 HttpServletRequest
. 4.3.x에서 현재로, 이 중 하나를 찾을 수없는 경우 , 그것은 경고 기록 이 표시되는지를
이름이 SomeName 인 URI가 [/some/path]
있는 HTTP 요청에 대한 매핑이 없습니다.DispatcherServlet
그리고 하나는 를 발생 NoHandlerFoundException
즉시 404 찾을 수 없음 상태 코드로 응답을 얻어냅니다.
내 요청을 처리 할 수있는를 DispatcherServlet
찾지 못한 이유는 무엇 HandlerMapping
입니까?
가장 일반적인 HandlerMapping
구현은이며 RequestMappingHandlerMapping
, @Controller
빈을 핸들러 (실제로 @RequestMapping
주석이 달린 메서드) 로 등록하는 것을 처리합니다 . 이 유형의 bean을 직접 선언 @Bean
하거나 ( <bean>
또는 기타 메커니즘을 사용 하여) 내장 옵션을 사용할 수 있습니다 . 이것들은:
- 당신의 주석
@Configuration
과 클래스를 @EnableWebMvc
.
<mvc:annotation-driven />
XML 구성에서 멤버를 선언 하십시오.
위의 링크에서 설명했듯이 두 가지 모두 RequestMappingHandlerMapping
빈 (및 기타 여러 가지)을 등록합니다. 그러나 HandlerMapping
핸들러 없이는별로 유용하지 않습니다. RequestMappingHandlerMapping
일부 @Controller
bean을 예상 하므로 @Bean
Java 구성의 메소드 또는 <bean>
XML 구성의 선언을 통해 또는 @Controller
둘 중 하나에서 주석 이 달린 클래스 의 구성 요소 스캔을 통해이를 선언 해야합니다. 이 콩이 있는지 확인하십시오.
경고 메시지와 404가 표시되고 위의 모든 사항을 올바르게 구성한 경우 감지 된 주석 처리기 메서드에서 처리하지 않는 잘못된 URI로 요청을 보내는 것@RequestMapping
입니다.
spring-webmvc
라이브러리 이벤트 다른 내장 HandlerMapping
구현. 예 : BeanNameUrlHandlerMapping
지도
URL에서 슬래시 ( "/")로 시작하는 이름을 가진 Bean으로
언제든지 직접 작성할 수 있습니다. 당연히 보내려는 요청이 등록 된 HandlerMapping
객체의 핸들러 중 하나 이상과 일치하는지 확인해야합니다 .
암시 적 또는 명시 적으로 등록하지 당신이 경우 HandlerMapping
콩 (또는 경우 detectAllHandlerMappings
이다 true
)의 DispatcherServlet
레지스터 일부 기본값을 . 이들은 클래스 DispatcherServlet.properties
와 동일한 패키지에 정의되어 DispatcherServlet
있습니다. 그들은이다 BeanNameUrlHandlerMapping
와 DefaultAnnotationHandlerMapping
(과 유사하다 RequestMappingHandlerMapping
하지만 사용되지 않음).
디버깅
Spring MVC는 RequestMappingHandlerMapping
. 예를 들어, @Controller
좋아요
@Controller
public class ExampleController {
@RequestMapping(path = "/example", method = RequestMethod.GET, headers = "X-Custom")
public String example() {
return "example-view-name";
}
}
INFO 수준에서 다음을 기록합니다.
Mapped "{[/example],methods=[GET],headers=[X-Custom]}" onto public java.lang.String com.spring.servlet.ExampleController.example()
등록 된 매핑에 대해 설명합니다. 핸들러를 찾을 수 없다는 경고가 표시되면 메시지의 URI를 여기에 나열된 매핑과 비교합니다. @RequestMapping
핸들러를 선택하려면 Spring MVC에 대해 지정된 모든 제한 이 일치해야합니다.
다른 HandlerMapping
구현은 매핑 및 해당 핸들러에 대한 힌트를 제공해야하는 자체 문을 기록합니다.
마찬가지로, DEBUG 수준에서 Spring 로깅을 활성화하여 Spring이 등록하는 Bean을 확인하십시오. 찾은 주석이 달린 클래스, 스캔하는 패키지 및 초기화하는 Bean을보고해야합니다. 예상 한 항목이 없으면 ApplicationContext
구성 을 검토하십시오 .
기타 일반적인 실수
A DispatcherServlet
는 일반적인 Java EE Servlet
입니다. 전형적인으로 당신은 그것을 등록 <web.xml>
<servlet-class>
및 <servlet-mapping>
신고, 직접을 통해 ServletContext#addServlet
A의 WebApplicationInitializer
, 또는 어떤 메커니즘 봄 부팅 용도로. 따라서 서블릿 사양에 지정된 URL 매핑 논리 에 의존해야합니다 ( 12 장 참조).
이를 염두에두고를 DispatcherServlet
URL 매핑 으로 등록하고 핸들러 메서드 /*
에서 뷰 이름을 반환 @RequestMapping
하고 JSP가 렌더링 될 것으로 예상하는 실수가 있습니다. 예를 들어, 다음과 같은 핸들러 메소드를 고려하십시오.
@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
보고
URI [/Example/WEB-INF/jsps/example-view-name.jsp]
가 DispatcherServlet
'dispatcher'인 HTTP 요청에 대한 매핑을 찾을 수 없습니다.
이 때문에 DispatcherServlet
에 매핑 /*
하고 /*
(높은 우선 순위가 정확히 일치 제외) 모든 일치는이 DispatcherServlet
핸들로 선택 될 forward
로부터 JstlView
(에 의해 반환을 InternalResourceViewResolver
). 거의 모든 경우에 DispatcherServlet
이러한 요청을 처리하도록 구성되지 않습니다 .
대신,이 단순한 경우에, 당신은 등록해야 DispatcherServlet
에를 /
기본 서블릿으로 표시. 기본 서블릿은 요청에 대한 마지막 일치입니다. 이렇게하면 일반적인 서블릿 컨테이너가 기본 서블릿으로 시도하기 전에 *.jsp
JSP 리소스 (예 : Tomcat has JspServlet
) 를 처리하기 위해에 매핑 된 내부 서블릿 구현을 선택할 수 있습니다 .
그것이 귀하의 예에서 보는 것입니다.