본문 바로가기
자바과정/스프링

스프링 Web(DispatcherServlet, HandlerMapping, HandlerAdapter, viewResolver)

by Parkej 2021. 4. 8.

- 출처

더보기
출처1 : https://m.blog.naver.com/PostView.nhn?blogId=todoskr&logNo=220845006916&proxyReferer=https:%2F%2Fwww.google.com%2F
출처1-1 : 
https://m.blog.naver.com/PostView.nhn?blogId=todoskr&logNo=220856216311

출처2 : https://mangkyu.tistory.com/18


출처3 : https://joont92.github.io/spring/HandlerMapping-HandlerAdapter-HandlerInterceptor/
Spring Web MVC를 공부하기 전 간단한 프로젝트를 생성하고 기본 구조에관한 공부 내용을 정리하고자 합니다.
- DispatcherServlet
- HandlerMapping
- HandlerAdapter
- viewResolver

DispatcherServlet

Servlet Container에서 HTTP프로토콜을 통해 들어오는 모든 요청을 프레젠테이션 계층의 제일앞에 둬서 중앙집중식으로 처리해주는 프론트 컨트롤러(Front Controller)
이것을 설명해주자면, 클라이언트로부터 어떠한 요청이 오면 Tomcat(톰캣)과 같은 서블릿컨테이너가 요청을 받는데, 이때 제일 앞에서 서버로 들어오는 모든 요청을 처리하는 *프론트 컨트롤러를 Spring에서 정의하였고, 이를 Dispatcher-Servlet이라고 합니다. 그래서 공통처리 작업을 Dispatcher 서블릿이 처리한 후, 적절한 세부 컨트롤러로 작업을 위임해줍니다. 
물론 Dispatcher-Servlet이 처리하는 url 패턴을 지정해주어야 하는데 일반적으로는 /*.do와 같으 /로 시작하며 .do로 끝나는 url 패턴에 대해서 처리하라고 지정해줍니다. 


Q) Front Controller(프론트 컨트롤러)란?

Front Controller는 주로 서블릿 컨테이너의 제일 앞에서 서버로 들어오는 클라이언트의 모든 요청을 받아서 
처리해주는 컨트롤러인데, MVC 구조에서 함께 사용되는 패턴이다.

- Spring MVC 흐름도

- Dispatcherservlet-context => serlvet-context

- web.xml 

- web.xml 안의 서블릿 매핑 구성
- 스프링의 DispatcherServlet 은 설정 파일을 이용해서 스프링 컨테이너를 생성하는데,기본적으로 WEB-INF 폴더 안의 WEB-INF/[서블릿 이름]-servlet.xml 파일을 설정 파일로 이용한다.
- 설정 파일을 직접 지정하고 싶으면 contextConfiguration 초기화 파라미터를 설정하면 된다.




HandlerMapping, HandlerAdapter, 컨트롤러, ViewResolver 등의 객체는 
DisptacherServlet 이 생성하는 스프링 컨테이너로 부터 구하기 때문에,
DistacherServlet 이 사용하는 설정 파일에 이들 객체를 빈 으로 설정해야 한다.

DispatcherServlet -> 설정 파일 로딩 -> 스프링 컨테이너 생성 -> 스프링 컨테이너 안에 빈으로 설정된 HandlerMapping, HandlerAdapter, 컨트롤러, ViewResolver 객체 이용 그리고 이렇게 생성되는 스프링 컨테이너는 WebApplicationContext 컨테이너이다.



HandlerMapping

- HandlerMapping : dispatcher servlet으로 들어온 모든 요청을
각각의 Controller로 위임 처리를 하는 handler mapping 설정을
바로 dispatcher servlet 설정 파일에서한다

 

HTTP 요청정보를 이용해서 컨트롤러를 찾아주는 기능을 수행한다.

HandlerMapping 인터페이스를 구현해서 생성한다.
public interface HandlerMapping{
	HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
}
DispatcherServlet은 등록된 HandlerMapping 전략들에게 HttpServletRequest를 전달하면서 매칭되는 오브젝트를 찾는다.(이게 곧 세부 컨트롤러!)

스프링이 제공하는 핸들러 매핑 전략은 총 5가지이다.
- BeanNameUrlHandlerMapping
- ControllerBeanNameHandlerMapping
- ControllerClassNameHandlerMapping
- SimpleUrlHandlerMapping
- DefaultAnnotationHandlerMapping

HandlerAdapter
HandlerMapping을 통해 찾은 컨트롤러를 직접 실행하는 기능을 수행한다.

핸들러 어댑터는 HandlerAdapter 인터페이스를 구현해서 생성한다.
public interface HandlerAdapter{
	boolean supports(Object handler);

	ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;

	long getLastModified(HttpServletRequest request, Object handler);
}
HandlerMapping으로 찾은 오브젝트(컨트롤러)를 등록된 HandlerAdaptor들의 supports 메서드에 대입하며 지원 여부를 살핀다.

부합할 경우 handler 메서드를 실행하여 ModelAndView를 리턴한다!

스프링 MVC가 지원하는 컨트롤러는 총 4개이므로, 핸들러 어댑터도 4개이다.

- SimpleServletHandlerAdapter(Servlet interface)
- HttpRequestHandlerAdapter(HttpRequestHandler interface)
- SimpleControllerHandlerAdapter(Controller interface)
- AnnotationMethodHandlerAdapter

View Resolver
뷰 리졸버는 ViewResolver 인터페이스를 구현해서 만들어집니다.
뷰 리졸버를 빈으로 등록하지 않는다면 DispatcherServlet의 디폴트 뷰 리졸버인 InternalResourceViewResolver가 사용됩니다.
핸들러 매핑과 마찬가지로 뷰 리졸버도 하나 이상을 빈으로 등록해서 사용할 수 있습니다.

주요 뷰 리졸버와 그 사용방법을 알아 보겠습니다.

- UrlBasedViewResolver

논리적인 뷰의 이름과 실제 view 객체의 이름이 같을 때 사용할 수 있는 뷰 리졸버입니다.

사용법은 아래와 같습니다.
<bean class="org.springframework.web.servlet.view.UrlBasedViewResolver">
    <property name="prefix" value="/WEB-INF/view"/>
    <property name="suffix" value=".jsp"/>
</bean>
위와 같이 설정을 하고 메서드에서 hello라는 뷰 이름을 String 타입으로 리턴하면 prefix, suffix를 적용해서 WEB-INF/view/hello.jsp를 뷰로 사용하게 됩니다. 컨트롤러에서도 뷰 이름을 매우 간결하게 작성할 수 있고, 논리적인 뷰 이름을 JSP 뷰에 종속시키지 않을 수 있다는 장점도 있습니다.
뷰 리졸버를 변경해서 hello라는 뷰 이름을 다른 뷰로 매핑해줄 수도 있기 때문입니다.

 

- InternamResourceViewResolver

InternamResourceViewResolver는 뷰 리졸버를 지정하지 않았을 때 자동 등록되는디폴트 뷰 리졸버입니다. 주로 JSP를 뷰로 사용하고자 할 때 쓰입니다.
UrlBasedViewResolver를 상속받았으며 사용법도 UrlBasedViewResolver과 유사합니다.

디폴트 상태의 InternamResourceViewResolver를 사용할 경우 뷰의 전체 경로를 다 적어줘야 합니다.

그렇기 때문에 디폴트 상태를 그대로 사용하는 일은 피해 prefix와 suffix를 명시해주어야 합니다.
사용법은 아래와 같습니다.
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/view"/>
    <property name="suffix" value=".jsp"/>
</bean>

 

 

- ResourceBundleViewResolver, XmlViewResolver

여러 가지 종류의 뷰를 혼용하거나 뷰의 종류를 코드 밖에서 변경해줘야 하는 경우가 있습니다. 단순히 모든 뷰의 종류를 변경하는 것이라면 기본 뷰 리졸버를 바꾸고 prefix, suffix를 활용하면 됩니다.

하지만 컨트롤러마다 뷰의 종류가 달라질 수 있다면 한 가지 뷰만을 지원하는 뷰 리졸버를 사용할 수 없습니다.
이런 경우에는 외부 리소스 파일에 각 뷰 이름에 해당하는 뷰 클래스와 설정을 담아두고 이를 참조하는 ResourceBundleViewResolver와 XmlViewResolver를 사용하면 됩니다.

ResourceBundleViewResolver는 기본적으로 클래스 패스의 views.properties파일을 사용합니다.
view.properties 파일에 정의한 뷰 정보의 예입니다.
hello.(class) = org.springframework.web.servlet.view.JstlView
hello.url = /WEB-INF/view/hello.jsp

main.(class) = org.springframework.web.servlet.view.velocity.VelocityView
main.url = main.vm

 

<bean class="org.springframework.web.servlet.view.ResourceBundleViewResolver">
    <property name="order" value="0"/>
</bean>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"/>
InternalResourceViewResolver의 order 프로퍼티는 기본적으로 가장 마지막으로 사용하게
되므로 두 개의 ViewResolver를 위와 같이 등록할 수 있습니다.

Dispatcher Servlet은 일단 ResourceBundleViewResolver에 대응되는 뷰가 있는지 확인하고
만약 없다면 InternalResourceViewResolver가 처리하도록 만들 수 있습니다.

- View
웹 환경에서 뷰가 생성하는 결과물은 일반적으로 브라우저에 나타낼 수 있는 HTML입니다.

앞서 이야기한 것처럼 뷰 리졸버를 통해 논리적인 뷰 이름을 실질적인 View 객체로 바꾸어 줍니다.

뷰 객체는 스프링의 View 인터페이스를 구현해야 합니다.
그러나 View 인터페이스를 직접 구현해서 뷰를 만들어야 할 필요는 없습니다.
스프링이 웹에서 자주 사용되는 타입의 콘텐츠를 생성해주는 다양한 뷰를 이미 구현해 놓았기 때문입니다.

 

반응형

댓글