JUST WRITE

MappingJackson2JsonView 본문

Programing/Spring

MappingJackson2JsonView

천재보단범재 2021. 10. 9. 21:48

MappingJackson2JsonView

MappingJackson2JsonView

MappingJackson2JsonView는 org.springframework.web.servlet.view의 하위 클래스입니다.

View를 Json 타입 View로 변환할 때 사용합니다.

MappingJackson2JsonView 동작

Spring에서는 Request가 들어오면 web.xml에 정의된 DispatcherServlet에서 가장 먼저 처리한다.

몇 가지 가정을 거치고 Handler(Controller)에서 처리한 결과물을 DispatcherServlet에서 받는다.

그럼 그 결과물을 ViewResolver가 View Template에 맞게 렌더링 한다.

processDispatchResult() -> render() -> view.render() 

render()

protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception { 
	//localeResolver를 통하여 locale 설정 
    Locale locale = this.localeResolver.resolveLocale(request); 
    response.setLocale(locale); 
    
    View view; 
    
    if (mv.isReference()) { 
	    // 뷰 설정이 레퍼런스라면(String 이라면, viewResolver를 통한  
        view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request); 
        
        if (view == null) { 
	        throw new ServletException("Could not resolve view with name '" + mv.getViewName() + 
                        "' in servlet with name '" + getServletName() + "'"); 
        } 

    } else { 
        // No need to lookup: the ModelAndView object contains the actual View object. 
        view = mv.getView();
        
        if (view == null) { 
	        throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a " + 
                       "View object in servlet with name '" + getServletName() + "'"); 
        } 

    }
    
    // 뷰 (View) 구현체에 위임하여 렌더링을 하도록 한다. 
    if (logger.isDebugEnabled()) { 
	    logger.debug("Rendering view [" + view + "] in DispatcherServlet with name '" + getServletName() + "'"); 
    } 

    try { 
	    if (mv.getStatus() != null) { 
	        response.setStatus(mv.getStatus().value()); 
        } 
        //ViewResolver에서 반환할 View 구현체에 의해 렌더링 
        view.render(mv.getModelInternal(), request, response); 

    } catch (Exception ex) { 
        //예외 처리 생략 
    } 
}

MappingJackson2JsonView render()

MappingJackson2JsonView는 AbstractJackson2View를 상속받아 정의한 Class이다.

AbstractJackson2View Class의 renderMergedOutputModel Method를 실행한다.

@Override 
	protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, 
	    HttpServletResponse response) throws Exception { 
        
	    OutputStream stream = (this.updateContentLength ? createTemporaryOutputStream() : response.getOutputStream()); 
        Object value = filterAndWrapModel(model, request); 
        
        // Stream에 JSON String 넣기
        writeContent(stream, value); 

        if (this.updateContentLength) { 
	        writeToResponse(response, (ByteArrayOutputStream) stream); 
        } 

}

writeContent Method를 통해 Stream에 JSON String을 생성한다.

protected void writeContent(OutputStream stream, Object object) throws IOException { 
	
    JsonGenerator generator = this.objectMapper.getFactory().createGenerator(stream, this.encoding); 

    writePrefix(generator, object); 

    Class<?> serializationView = null; 

    FilterProvider filters = null; 

    Object value = object; 
  
    if (value instanceof MappingJacksonValue) { 
	    MappingJacksonValue container = (MappingJacksonValue) value; 
        value = container.getValue(); 
        serializationView = container.getSerializationView(); 
        filters = container.getFilters(); 

    } 

    if (serializationView != null) { 
	    this.objectMapper.writerWithView(serializationView).writeValue(generator, value); 
    } else if (filters != null) { 
        this.objectMapper.writer(filters).writeValue(generator, value); 
    } else { 
        this.objectMapper.writeValue(generator, value); 
    } 

    writeSuffix(generator, object); 
    generator.flush(); 
}

wrtieToResponse Method에서 ContentType, ContentLength 2가지 값을 Response Header에 설정한다.

protected void writeToResponse(HttpServletResponse response, ByteArrayOutputStream baos) throws IOException { 
	// Write content type and also length (determined via byte array). 
    response.setContentType(getContentType()); 
    response.setContentLength(baos.size()); 
    
    // Flush byte array to servlet output stream. 
    ServletOutputStream out = response.getOutputStream(); 
    baos.writeTo(out); 
    out.flush(); 
}

MappingJackson2JsonView 사용

Jackson Library

Jackson LibaryJava Object -> JSON, JSON -> Java Object로 변환하는 데 사용하는 Java Library입니다.

  • Stream API => Stream 형식이라 성능 좋음
  • Tree Model => Node 형태로 데이터 다룰 수 있어 유연성 좋음
  • Data Binding => POJO 기반의 Java 객체들을 JSON 변환

Dependency 추가

Jackson-databind Library를 추가합니다.

Jackson-databind Library는 jackson-core, jackson-annotaion Libarary 의존성을 포함합니다.

<dependency>
	<groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>${jackson-version}</version>
</dependency>

ServletContext에 Bean 등록

ServletContext에 MappingJackson2JsonView객체를 jsonView라는 이름으로 Bean 등록한다.

<bean id="jsonView" class="org.springframework.web.servlet.view.json.MappingJackson2JsonView">
	<property name="contentType" value="text/html;charset=UTF-8"/>
</bean>

위에서 정의한 'jsonView' 이름의 Bean을 View객체로 사용하기 위해서 BeanNameViewResolver를 정의한다.

<bean id="beanNameResolver" class="org.springframework.web.servlet.view.BeanNameViewResolver">
	<property name="order" value="0"/>
</bean>

Controller에서 해당 View를 사용하도록 한다.

@Controller
public class JsonDataController {
	...
	public ModelAndView exec(HttpServletRequest request, HttpServletResponse response) throws Exception {
    	...
         // returnMap이 JSON String으로 변환해서 Response로 보낼 Java Object
         return new ModelAndView ("jsonView", returnMap);
    }
	...
}

[참고사이트]

더보기
728x90
반응형

'Programing > Spring' 카테고리의 다른 글

@Autowired  (0) 2021.10.22
DispatcherSerlvet  (0) 2021.10.15
Singleton Registry  (0) 2021.10.02
Bean LifeCycle  (0) 2021.09.29
Spring Bean Scopes  (0) 2021.09.28
Comments