실행순서
0.Filter 모든 요청에 걸러져서 dispatcherServlet으로 들어간다.
1.웹 브라우저를 통해 클라이언트 요청이 dispatcherServlet에게 들어온다.
2.dispatcherServlet은 HandlerMappging에게 어떤 컨트롤러가 처리할지 결과를 받아온다.
3.HandlerAdapter는 DispatcherServlet의 처리 요청을 변환해서 컨트롤러에게 전달하고 컨트롤러의 응답 결과를 DispatcherServlet 요구하는 결과 방식으로 변환한다.
웹 브라우저, 캐시들도 설정한다.
4.Controllers는 클라이언트 요청을 처리한 뒤 결과를 DispatcherServlet에게 리턴한다.
5.HandlerAdapter는 controller의 실행결과를 ModelAndView로 변환해서 DispatcherServlet에게 리턴한다.
6.DispatcherServlet은 viewResolver에게 컨트롤러의 처리결과를 보여줄 view를 결정한다.
7.해당 view에게 처리결과 화면을 생성한다. jsp나 velocity 탬플리 파일을 이용해 응답 결과를 전송한다.
1.Filter
- 공통적인 업무(로그인, 로그, 권한체크...)를 할때 공통관심으로 분리하는데 이떄 사용할 수 있는 것이 서블릿 필터,스프링 프레임워크를 사용하면 interceptor, AOP가 있다.
이 세가지의 실행시점은 서버실행시 서블릿이 올라오는 동안 init이 실행되고 filter가 실행, 컨트롤러가 실행되기전에 intercepter의 preHandler, 그리고
AOP의 작업 후에 역으로 postHandler, atfer Completion, filter로 진행되고 destory 된다.
init(), doFilter(), destory()
필터는 스프링과 무관하게 지정된 자원에 대해 동작한다. 즉 스프링 외부에 존재한다.
그래서 servlet에서 처리하기 전후에 사용되기 편하며 servletRequest 혹은 response를 교체하는것이 가능하다.
web.xml에 설정한다.
*interceptor의 차이점
실행시점에 속하는 영역(Context)이다. intercepter는 스프링내부에 존재하며 dispatcherServlet이 컨트롤 호출 전후로 작동한다.
preHandler(), postHandler(), afterCompletion()
예외처리가 spring annotation으로 작동하므로 관리의 편의성이 있다.
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="className"/>
</mvc:interceptor>
</mvc:interceptors>
*AOP와 interceptor의 차이점
spring의 AOP은 joinPoint등을 활용해서 호출대상이 되는 메소드의 파라미터를 받는 구조이나 intercepter는 filter와 유사하게 HttpServletRequest, httpServletRequest로 파라미터를 받는 구조이다.
포인트 컷으로 @after, @Before....
예외처리가 spring annotation으로 작동하므로 관리의 편의성이 있다.
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
2.dispatcherServlet
컨테이너를 생성한다.
web.xml을 먼저 읽어와 [서블리이름]-servlet.xml 파일의 정보로 설정한다. 이떄 servlet.xml 형식이 아닌 다른 파일을 사용했다면 contextConfigLocation 태그로 설정을 변경하며
xml이 아닌 annotation(@Configuration)으로 설정했다면 contextClass를 AnnotationConfigWebApplicationtext를 xml에 추가해주고 contextConfigLocation에 해당 시작 클래스를 등록해야한다.
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/context-*.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
3.handlerMapping & handlerAdapter
스프링은 Url이 들어오면 어떤 컨트롤러 오브젝트가 이를 처리하게 할지 매핑해주는 전략을 만들어 DI로 제공한다.
오브젝트 어댑터 패턴을 사용해서 특정 컨트롤러를 호출해야 할때는 해당 컨트롤러 타입을 지원하는 어댑터를 중간에 껴서 호출하는것이다. DIspatcherServlet은 컨트롤러가 어떤 메소드를 가졌고 어떤 인터페이스를 구현했는지 전혀 알지못한다. 대신 컨트롤러의 종류에 따라 적절한 어뎁터를 사용한다. 이렇게 하면 하나의 dispatcherServlet이 동시에 여러가지 타입이 컨트롤러를 사용할수있다.
dispathcherServlet은 컨트롤러를 직접 실행하지 않고 HandlerAdapterf를 사용하여 간접적으로 컨트롤러을 실행하는데 실제 반환하는 핸들러의 객체 타입이 무엇인지 신경쓰지않는다. ModelAndVIew가 아닌 string 타입이 될수도 있다. 이때 중간에서 string을 modelAndview로 변경해주어야 하는데 그때 사용되는 것이 HandlerAdapter이다
<mvc:annotatinon-driven>설정이나 @EnaleWebMvc 애노테이션을 사용하면 handlerMapping과 HandlerAdapter를 등록한다.
RequestMappingHandlerMapping : @controller 적용 빈객체를 핸들러로 사용하는 HandlerMapping구현, 적용 우선순위가 높다.
SimpleUrlHandlerMapping : <mvc:default-servlet-handler> <mvc:view-controller> <mvc:resources> 태그 사용
RequestMappingHandlerAdapter: RequestMappingHandlerMapping 에 대한 어뎁터
HttpRequestHandlerAdaper: HttpRequestHandler에 대한 어뎁터
SimpleControllerHandlerAdapter: Controller 인터페이스를 구현한 객체에 대한 어뎁터
4.viewResolver
컨트롤러가 지정한 뷰이름으로부터 응답 결과 화면을 생성하는 view객체를 구현할때 사용
주요 구현클래스
internalResourceViewResolver / velocityViewResolver / velocityLayoutViewResolver / BeanNameViewResolver
servlet-context.xml 의 internalResourceViewResolver
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
servlet-context.xml 의 BeanNameViewResolver
bean에서 BeanNameViewResolver 등록하고 bean의 id가 download인 클래스를 등록하면
return new ModelAndVIew( "download", "downloadFile", downloadFile )이 실행가능하다.
이름이 download인 DownloadVIew객체를 뷰로 검색하며 DIspatcherServlet은 downloadView를 이용해 DownLoadController의 처리결과를 출력하게 된다.
다수의 viewResolver는 우선순위 설정할것
<bean id="internalResource" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/application/" />
<property name="suffix" value=".jsp" />
<property name="order" value="2"/>
</bean>
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>
<property name="order" value="1"/>
</bean>
order이 작을수록 우선순위가 높으며 우선순위가 높은 viewResolver가 null을 리턴하면 다음 우선순위를 찾는다. 이떄 internalResoureceviewResolver는 항상 뷰 이름에 매핑되는 뷰 객체를 리턴하기때문에 null을 리턴할수없다. internalResoureceviewResolver후에 지정된 viewResolver는 탐색하지않고 없을경우 404에러를 출력한다. 따라서 internalResoureceviewResolver는 마지막 우선순위를 지정하도록 해야한다.
뷰 생성까지 모든 작업을 마쳤으면 dispatchServlet은 HttpServletResponse에 담긴 최종 결과를 서블릿 컨테이너에게 돌려준다.
그리고 이 컨테이너는 httpServletResponse에 담긴 정보를 Http응답으로 만들어 사용자의 브라우저나 클라이언트에게 전송하고 작업을 종료한다.
'STUDY > SPRING' 카테고리의 다른 글
Aspect Oriented Programming (0) | 2018.11.06 |
---|---|
TRANSACTION (0) | 2018.11.06 |
[코드로 배우는 스프링 웹프로젝트] (0) | 2018.10.31 |
Annotation (0) | 2018.10.30 |
스프링 컨테이너와 빈 (0) | 2018.10.30 |