1. ViewResolver 설정
뷰 영역 구현
컨트롤러는 최종적으로 결과를 출력할 뷰와 뷰에 전달할 객체를 담고 있는 ModelAndView 객체를 리턴한다.
DispatherServlet은 ViewResolver를 사용하여 결과를 출력할 View 객체를 구하고, 구한 View 객체를 이용하여 내용을 생성한다.
JSP를 뷰 기술로 사용할 경우 다음과 같이 InternalResourceViewResolver 구현체를 빈으로 등록해주면 된다.
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="WEB-INF/view"/>
<property name="suffix" value=".jsp/>
// 이는 ViewResolver가 "WEB-INF/view/뷰이름.jsp"를 뷰 JSP로 사용한다는 것을 의미한다.
// 즉, 앞의 예에서 HelloController는 뷰 이름으로 "hello"를 리턴하므로,
// 실제로 사용되는 뷰 파일은 "WEB-INF/view/hello.jsp"파일이 된다.
</bean>
InternalResourceViewResolver는 컨트롤러가 지정한 뷰 이름으로부터 실제로 사용될 뷰를 선택하는데, 이 때 컨트롤러가 지정한 뷰 이름 앞뒤로 prefix 프로퍼티와 suffix 프로퍼티를 추가한 값이 실제로 사용될 자원의 경로가 된다.
2. ViewResolver 구현 클래스
스프링 컨트롤러는 뷰에 의존적이지 않다. 컨트롤러는 아래 코드와 같이 결과를 생성할 뷰의 이름만 지정할 뿐이다.
컨트롤러가 지정한 뷰 이름으로부터 응답 결과 화면을 생성하는 View 객체는 ViewResolver가 구한다.
스프링은 몇 가지 ViewResolver 구현 클래스를 제공하고 있는데, 이중 주료 ViewResolver 구현 클래스는 다음과 같다.
3. ContentNegotiatingViewResolver 이해하기
ContentNegotiatingViewResolver 는 View 를 찾기위해 요청 URL의 확장자와 AcceptHeader를 사용하는 ViewResolver 입니다.
자체적으로 View 를 찾지는 않으며 viewResolvers 에 설정된 ViewResolver 를 사용하여 View 를 찾습니다.
ContentNegotiatingViewResolver의 기본적인 설정방법은 아래와 같습니다.
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<!-- 확장자와 contentType 을 연결해 준다. -->
<property name="mediaTypes">
<map>
<entry key="atom" value="application/atom+xml"/>
<entry key="html" value="text/html"/>
<entry key="json" value="application/json"/>
</map>
</property>
<property name="viewResolvers">
<list>
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver"/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
</list>
</property>
<!-- 위의 viewResolvers 에 의해 view를 얻지 못했을 경우에 사용되는 view -->
<property name="defaultViews">
<list>
<bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
</list>
</property>
<property name="defaultContentType" value="application/json" />
</bean>
mediaType 은 URL 의 확장자와 contentType 을 연결해주는 일종의 맵입니다.
http://localhost/user.html 이 들어왔을 경우에는 URL 의 확장자인 html 에 연결된 text/html (ContentType) 을 처리하는 View 를 찾게되고
http://localhost/user.json 이 요청되었을 경우에는 위와 마찬가지로 URL의 확장자인 json 과 연결된 application/json (ContentType) 을 처리하는 View 를 찾습니다.
viewResolvers ContentNegotiatingViewResolver 가 View 를 찾기위해 사용하는 ViewResolver 들
defaultViews 는 viewResolvers 에 의해 view 를 찾지 못했을 경우에 사용되는 view 입니다.
json 이 MappingJacksonJsonView 와 연결되는 방법
org.springframework.web.servlet.View
org.springframework.web.servlet.AbstractView
org.springframework.web.servlet.view.json.MappingJacksonJsonView
MappingJacksonJsonView 상속 관계를 보면 최상위에 org.springframework.web.servlet.View 인터페이스가 있습니다.
org.springframework.web.servlet.View 인터페이스 내에는 해당 View 가 처리할 수 있는 ContextType 를 정의해야 하는 getContentType() 메소드가 있는데 여기서 리턴되는 값을 통해서 해당 View 가 처리해야할 ContentType 을 정의하고 있습니다.
MappingJacksonJsonView 에서 직접적으로 getContentType() 메소드를 구현하지 않는데 구현은 AbstractView 에 이미 들어가 있습니다.
AbstractView 소스를 들여다보면 setContextType( String contextType), getContextType() 메소드가 존재합니다.
따라서 MappingJacksonJsonView 에서는
setContentType( "application/json"); 메소드로 해당 View 에서 처리해야할 ContextType을 정의하게 됩니다.
4. @ResponseBody
@ResponseBodysms @RequestBody와 비슷한 방식으로 동작함
@ResponseBody가 메서드 레벨에 부여되면, 메서드가 리턴하는 객체는 바로 HTTP 응답의 메시지 본문으로 전환됨. (뷰를 통해 결과를 만들어내는 모델로 사용되지 않음)
@RequestMapping("/hello")
@ResponseBody
public String hello(){
return "<html><body>Hello Spring</body></html>";
}
만약 메서드에 @ResponseBody가 없다면, 스트링 타입의 리턴값은 뷰이름으로 인식 될것.
하지만 @ResponseBody가 붙었으므로, HttpServletResponse의 출력 스트림에 넣어 버림.
Reference
https://devbox.tistory.com/entry/Spring-ViewResolver-설정
'Dev > Web' 카테고리의 다른 글
[Spring] 스프링기초 - @RequestBody, @ResponseBody 사용법 (0) | 2019.10.29 |
---|---|
[Spring] Application Context와 Servlet Context 설정과 Transaction (0) | 2019.10.28 |
[Spring] 스프링 기초 - Controller 여러개 맵핑하기 (0) | 2019.10.25 |
[Spring] 4. MVC 프로젝트 구조 및 생성 및 @Controller, @RequestMapping, @RequestParam, @PathVariable 등 (0) | 2019.10.24 |
[Spring] 스프링 기초 - 소개, DI, IoC 컨테이너 개념2 (0) | 2019.10.23 |