개인공부/SPRING
Spring MVC 동작원리
- -
1. 스프링 MVC 핵심 구성 요소
구성요소 이름 | 설명 |
DispatcherServlet | 클라이언트의 요청을 받아 컨트롤러에게 전달, 컨트롤러가 리턴한 결과값을 View에 전달하여 알맞은 응답을 생성하도록 한다. |
HandlerMapping | 클라이언트의 요청 URL을 어떤 컨트롤러가 처리할지 결정한다. |
HandlerAdapter | DispatcherServlet의 처리 요청을 변환해서 컨트롤러에게 전달, 그 응답 결과를 DispatcherServlet이 요구하는 형식으로 변환한다. |
Controller | 클라이언트의 요청을 처리한 뒤, 결과를 리턴한다. |
ModelAndView | 컨트롤러가 처리한 결과 정보 및 뷰 선택에 필요한 정보를 담는다. |
ViewResolver | 컨트롤러의 처리 결과를 보여줄 뷰를 결정한다. |
View | 컨트롤러의 처리 결과 화면을 생성한다. JSP 템플릿 파일등을 이용한다. |
MVC2
MVC 프레임워크의 흐름은 다음과 같다.
- DispatcherServlet이 모든 연결을 담당하며, 웹 브라우저로부터 요청을 받음
- 요청이 들어오면 DispathcerServlet는 HandlerMapping Bean 객체에게 컨트롤러 검색을 요청
- HandlerMapping은 클라이언트의 요청 경로를 이용해 컨트롤러 Bean객체를 DispathcerServlet에게 전달
- DispathcerServlet은 전달받은 객체를 처리할 수 있는 HandlerAdapter Bean에게 요청 처리를 위임
- HandlerAdapter는 컨트롤러의 알맞은 메서드를 호출해 요청을 처리
- 그 후, 결과를 ModelAndView라는 객체로 DispathcerServlet에게 반환
- DispathcerServlet는 전달받은 결과를 보여줄 뷰를 찾기 위해 ViewResolver Bean 객체를 사용
- ViewResolver는 ModelAndView 내부에 있는 뷰 이름에 해당하는 View 객체를 찾거나 생성후 리턴
- DispathcerServlet는 VeiwResolver가 리턴한 View 객체에게 응답 결과 생성을 요청
1-1. 컨트롤러와 핸들러
- 클라이언트의 요청을 실제로 처리하는 것은 컨트롤러
- DispathcerServlet는 클라이언트의 요청을 전달받는 창구 역할
- HandlerMapping은 특정 요청 경로를 처리해주는 핸들러를 찾아주는 역할
- HandlerAdapter는 핸들러의 처리결과를 ModelAndView 객체로 변환하여 DispathcerServlet에게 전달
2. @Controller를 위한 HandlerMapping과 HandlerAdapter
// ControllerConfig.java
@Configuration
@EnableWebMvc
public class MvcConfig{
...
}
- @EnableWebMvc 어노테이션을 통해 HandlerMapping이나 HandleAdapter 설정을 자동으로 추가
// HelloController.java
@Controller
public class HelloController {
@GetMapping("/hello")
public String hello(Model model,
@RequestParam(value = "name", required = false) String name)
{
model.addAttribute("greeting", "안녕하세요, " + name);
return "hello";
}
}
- @EnableWebMvc 어노테이션은 @Controller 타입의 핸들러 객체를 처리하기 위한 클래스를 포함
- 그중 하나가 RequestMappingHandlerMapping이며,
이 어노테이션은 @GetMapping 어노테이션 값을 이용해서 웹 브라우저의 요청을 처리할 컨트롤러 Bean을 찾음 - 앞선 코드에서 @GetMapping에서 “/hello”라는 요청 경로에 대해 hello() 메서드를 호출
이때 Model 객체를 생성해 첫 번째 파라미터로, HTTP 요청 파라미터를 두 번째 파라미터로 전달 - RequestMappingHandlerAdapter는 컨트롤러 메서드 결과 값이 String 타입이면,
해당 값을 뷰 이름으로 갖는 ModleAndView 객체를 생성해 DispatcherServlet에 리턴위의 예제에서 결국 뷰의 이름은 hello가 된다.
3. JSP를 위한 ViewResolver
- 컨트롤러 처리 결과를 JSP를 이용해서 생성하기 위해 다음 설정을 사용
- WebMvcConfigurer 인터페이스에 정의된,
- configureViewResolvers() 매서드의 파라미터 ViewResolverRegistry의 jsp() 매서드를 이용해 ViewResolver를 설정 가능
- 내부 클래스를 이용하여 다음과 같이 뷰 이름에 해당하는 객체를 요청
@Bean
public ViewResolver viewResolver(){
InternalResourceViewResolver vr = new InternalResourceViewResolver();
vr.setPrefix("/WEB-INF/view/");
vr.setSurfix(".jsp");
return vr;
}
- 앞선 코드의 구성처럼, "prefix + 뷰 이름 " surfix"에 해당하는 경로를 할당
- DispatcherServlet이 View 생성을 요청하면 InternalResourceViewResolver는 이 JSP 코드를 실행하여 결과 생성
// MvcConfig.java
@Configuration
@EnableWebMvc
public class MvcConfig implements WebMvcConfigurer {
...
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.jsp("/WEB-INF/view/", ".jsp"); // 접두사, 접미사 설정
}
}
4. 디폴트 핸들러와 HandlerMapping의 우선순위
- web.xml 파일을 참조하면, DispatcherServlet에 대한 매핑 경로가 다음과 같이 '/'로 설정
- 매핑 경로가 ‘/’인 경우. jsp로 끝나는 요청을 제외한 모든 요청을 DispatcherServlet이 처리
- 하지만 앞선 코드에서처럼 HandlerMapping으로 @GetMapping(“/hello”) 설정을 사용하였다면, /hello 경로만 처리 가능하므로 “/index.html”등의 요청을 처리할 컨트롤러를 찾을 수 없음
- 이러한 경로를 처리하기 위한 컨트롤러 객체를 직접 구현할 수도 있지만 다음과 같이,
WebMvcConfigurer의 configureDefaultServletHandling() 매서드를 사용하는 것이 편리// MvcConfig.java @Configuration @EnableWebMvc public class MvcConfig implements WebMvcConfigurer { @Override public void configureDefaultServletHandling (DefaultServletHandlerConfigurer configurer) { configurer.enable(); } ...
- 위 설정에서 enable() 매서드는 다음의 두 Bean 객체를 추가
- DefaultServletRequestHandler
- SimpleUrlHandlerMapping
- DefaultServletRequestHandler는 클라이언트의 모든 요청을 WAS가 제공하는 디폴트 서블릿에 전달“/index.html”에 대한 처리를 결국 디폴트 서블릿이 처리하도록 만듦
- 그리고 SimpleUrlHandlerMapping를 이용하여 모든 경로(“/**“)를 DefaultServletHttp RequestHandler를 이용해 처리하도록 함
- @EnableWebMvc 어노테이션이 등록하는 HandlerMapping의 적용 우선순위가 enable() 매서드가 등록하는 디폴트 핸들러보다 높음
- 따라서 다음과 같은 방식으로 요청을 처리
- RequestMappingHandlerMapping을 사용해 요청 처리할 핸들러 검색
- 존재하면 해당 컨트롤러를 이용해 요청을 처리
- 존재하지 않으면 SimpleUrlHandlerMapping을 사용해 요청을 처리할 핸들러 검색
- 모든 경로에 대해 DefaultServletHttpRequestHandler를 리턴
- DispatcherServlet은 DefaultServletHttpRequestHandler에 처리를 요청
- DefaultServletHttpRequestHandler는 디폴트 서블릿에 처리를 위임예를 들어 “/index.html” 경로로 요청이 들어오면, 1 과정에서 해당하는 경로를 찾지 못하므로,
2 과정을 통해 디폴트 서블릿이 /index.html 요청을 처리하게 됨
- RequestMappingHandlerMapping을 사용해 요청 처리할 핸들러 검색
<!-- web.xml -->
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
종류 | URL pattern | 매칭 URL |
1. exact(정확한) mapping | /login/hello.do | http://localhost/login/hello.do |
2. path(경로) mapping | /login/* | http://localhost/login/ http://localhost/login/hello http://localhost/login/hello.do http://localhost/login/test/ |
3. extension(확장자) mapping | *.do | http://localhost/hi.do http://localhost/login/hello.do |
4. default mapping | / | http://localhost/ http://localhost/hello.do http://localhost/login/ http://localhost/login/hello http://localhost/login/hello.do |
참조 URL
'개인공부 > SPRING' 카테고리의 다른 글
Spring DI(의존주입) @Autowired (의존 자동주입) 간의 관계 (1) | 2023.10.30 |
---|---|
spring bean scope (0) | 2022.10.26 |
프로젝트 개발시 참고 (0) | 2022.10.19 |
프로젝트 하면서 알아낸것 (1) | 2022.10.18 |
[Spring] @Controller와 @RestController 차이 (1) | 2022.10.15 |
Contents
소중한 공감 감사합니다