구리

TIL_210624_Spring 데이터 변환 본문

SPRING FRAMEWORK

TIL_210624_Spring 데이터 변환

guriguriguri 2021. 6. 23. 14:46

목차

1. JSON으로 변환
2. XML로 변환

 

 

 

 

1. JSON으로 변환

(1) Jackson2 라이브러리 내려 받기

pom.xml 파일에서 <dependency> 추가

<!-- Jackson2 -->
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-databind</artifactId>
			<version>2.7.2</version>
		</dependency>

 

(2) HttpMessageConvertor 등록

일반적으로 서블릿이나 JSP 요청시, Http 응답 프로토콜 메시지 Body에 저장하여 브라우저에 전송합니다.

일반적인 JSP 요청 과정

그런데 이 결과를  JSON이나 XML로 변환하여 메시지 Body에 저장하려면 스프링이 제공하는 Converter를 사용합니다.

자바 객체를 JSON 응답 보디로 변환할 때는 MappingJackson2HttpMessageConverter를 사용합니다.

 

(XML 변환도 처리할 예정이므로 presentation.xml에 엘리먼트 추가)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd">

	
	<context:component-scan base-package="com.springbook.view"></context:component-scan>
	<mvc:annotation-driven></mvc:annotation-driven>
</beans>

다음과 같이 설정하면 HttpMessageConverter를 구현한 모든 변환기가 생성됩니다.

 

(3) 링크 추가 및 Controller 수정

 

index.jsp에 링크 추가

<hr />
		
		<a href="login.do">로그인</a><br /><br />
		<a href="getBoardList.do">글 목록 바로 가기</a><br /><br />
		<a href="dataTransform.do">글 목록 변환 처리</a>
<hr />

 

BoardController에 메서드 추가

package com.springbook.view.board;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.multipart.MultipartFile;

import com.springbook.biz.board.BoardService;
import com.springbook.biz.board.BoardVO;

@Controller
@SessionAttributes("board")
public class BoardController {
	@Autowired
	private BoardService boardService;
	
	@RequestMapping("/dataTransform.do")
	@ResponseBody
	public List<BoardVO> dataTransform(BoardVO vo){
		vo.setSearchCondition("TITLE");
		vo.setSearchKeyword("");
		List<BoardVO> boardList = boardService.getBoardList(vo);
		return boardList;
	}
}

@ResponseBody : 자바 객체를 Http 응답 프로토콜의 몸체로 변환하기 위해 사용합니다.

앞에서 스프링 설정 파일에 <mvc:annotation-driven>를 추가하여 스프링 컨테이너가 MappingJackson2HttpMessageConverter 변환기를 생성하였기에 @ResponseBody 가 적용된 dataTransform() 메서드의 실행 결과는 JSON으로 변환되어 HTTP 응답 Body에 설정됩니다.

 

(4) 실행 결과 확인

index.jsp 파일 요청 후 글 목록 변환 처리 버튼 클릭시 아래와 같은 실행 결과가 출력됩니다.

 

 

그런데 출력되지 않아도 될 정보들(searchkeyword, searchCondition, uploadFile)도 있기에 JSON 형태 변환시 특정 변수를 제외하고 싶다면 @JSONIgnore 어노테이션을 이용합니다.

 

@JSONIgnore 

예시

package com.springbook.biz.board;

import java.sql.Date;

import org.springframework.web.multipart.MultipartFile;

import com.fasterxml.jackson.annotation.JsonIgnore;

// VO
public class BoardVO {
	
	@JsonIgnore
	public String getSearchCondition() {
		return searchCondition;
	}

	public void setSearchCondition(String searchCondition) {
		this.searchCondition = searchCondition;
	}

	@JsonIgnore
	public String getSearchKeyword() {
		return searchKeyword;
	}

	public void setSearchKeyword(String searchKeyword) {
		this.searchKeyword = searchKeyword;
	}

	@JsonIgnore
	public MultipartFile getUploadFile() {
		return uploadFile;
	}

	public void setUploadFile(MultipartFile uploadFile) {
		this.uploadFile = uploadFile;
	}
}

@JsonIgnore는 자바 객체를 JSON으로 변환시 사용하며, 특정 변수를 변환에서 제외시킵니다.

@JsonIgnore는 변수 위에서 설정하지 않고 Getter 메소드 위에 설정해야 합니다.

 

<없는 페이지>

 

2. XML로 변환

- BoardVO 수정

package com.springbook.biz.board;

import java.util.Date;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlTransient;

import org.springframework.web.multipart.MultipartFile;

import com.fasterxml.jackson.annotation.JsonIgnore;

// VO
@XmlAccessorType(XmlAccessType.FIELD)
public class BoardVO {
	@XmlAttribute
	private int seq;
	
	private String title;
	private String writer;
	private String content;
	private Date regDate;
	private int cnt;
	@XmlTransient
	private String searchCondition;
	@XmlTransient
	private String searchKeyword;
	@XmlTransient
	private MultipartFile uploadFile;
	
	public BoardVO() {}
	
	public int getSeq() {
		return seq;
	}
	public void setSeq(int seq) {
		this.seq = seq;
	}
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	public String getWriter() {
		return writer;
	}
	public void setWriter(String writer) {
		this.writer = writer;
	}
	public String getContent() {
		return content;
	}
	public void setContent(String content) {
		this.content = content;
	}
	public Date getRegDate() {
		return regDate;
	}
	public void setRegDate(Date regDate) {
		this.regDate = regDate;
	}
	public int getCnt() {
		return cnt;
	}
	public void setCnt(int cnt) {
		this.cnt = cnt;
	}
	
	public String getSearchCondition() {
		return searchCondition;
	}

	public void setSearchCondition(String searchCondition) {
		this.searchCondition = searchCondition;
	}

	public String getSearchKeyword() {
		return searchKeyword;
	}

	public void setSearchKeyword(String searchKeyword) {
		this.searchKeyword = searchKeyword;
	}

	public MultipartFile getUploadFile() {
		return uploadFile;
	}

	public void setUploadFile(MultipartFile uploadFile) {
		this.uploadFile = uploadFile;
	}

	@Override
	public String toString(){
		return "BoardVO [seq=" + seq + ", title=" + title + ", writer=" + writer + ",content= " + content + ", regDate = " + regDate + ", cnt = " + cnt +"]";
		
	}

}

- @XmlAccessorType : 해당 객체를 XML로 변환할 수 있다는 의미

- XmlAccessType.FIELD : 이 객체가 가진 필드, 즉 변수들은 자동으로 자식 엘리먼트로 표현한다는 의미

- @XmlAttribute : 해당 변수에만 속성으로 표현

- @XmlTransient : 해당 변수는 XML 변환에서 제외(@JsonIgnore과 비슷한 의미)

또한, regDate 변수의 타입이 java.util.Date로 변경되었는데 특정 자바 객체를 XML로 변환하려면 반드시 해당 클래스에 기본 생성자가 존재해야 하기에 변경하였습니다.

 

 

-BoardListVO 추가

package com.springbook.biz.board;

import java.util.List;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name="boardList")
@XmlAccessorType(XmlAccessType.FIELD)
public class BoardListVO {
	
	@XmlElement(name="board")
	private List<BoardVO> boardList;

	public List<BoardVO> getBoardList() {
		return boardList;
	}

	public void setBoardList(List<BoardVO> boardList) {
		this.boardList = boardList;
	}
}

 

2. Controller 수정

package com.springbook.view.board;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.multipart.MultipartFile;

import com.springbook.biz.board.BoardListVO;
import com.springbook.biz.board.BoardService;
import com.springbook.biz.board.BoardVO;

@Controller
@SessionAttributes("board")
public class BoardController {
	@Autowired
	private BoardService boardService;
	
	@RequestMapping("/dataTransform.do")
	@ResponseBody
	public BoardListVO dataTransform(BoardVO vo){
		vo.setSearchCondition("TITLE");
		vo.setSearchKeyword("");
		List<BoardVO> boardList = boardService.getBoardList(vo);
		BoardListVO boardListVO = new BoardListVO();
		boardListVO.setBoardList(boardList);
		return boardListVO;
	}
}

 

3. 실행 결과 확인

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring" %>


<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title><spring:message code="message.board.list.mainTitle" /></title>
</head>
<body>
	<center>
		<h1><spring:message code="message.board.list.mainTitle" /></h1>
		<h3>${userName }<spring:message code="message.board.list.welcomeMsg" />~~ 
		<a href="logout.do">Log-out</a></h3>
		
		<!-- 검색 시작 -->
		<form action="getBoardList.do" method="post">
			<table border="1" cellpadding="0" cellspacing="0" width="700">
				<tr>
					<td align="right">
						<select name="searchCondition">
						<c:forEach items="${conditionMap }" var="option">
							<option value="${option.value }" />${option.key}
						</c:forEach>
						</select>
						<input name="searchKeyword" type="text" />
						<input value="<spring:message code="message.board.list.search.condition.btn" />" type="submit" />
					</td>
				</tr>
				
			</table>
		</form>
		
		<table border="1" cellpadding="0" cellspacing="0" width="700">
			<tr>
				<th bgcolor="orange" width="100">
				<spring:message code="message.board.list.table.head.seq" /></th>
				<th bgcolor="orange" width="200">
				<spring:message code="message.board.list.table.head.title" /></th>
				<th bgcolor="orange" width="150">
				<spring:message code="message.board.list.table.head.writer" /></th>
				<th bgcolor="orange" width="150">
				<spring:message code="message.board.list.table.head.regDate" /></th>
				<th bgcolor="orange" width="100">
				<spring:message code="message.board.list.table.head.cnt" /></th>
			</tr>
			
			<c:forEach items="${boardList }" var="board">
				<tr>
					<td>${board.seq }</td>
					<td align="left"><a href="getBoard.do?seq=${board.seq }">${board.title }</a></td>
					<td>${board.writer }</td>
					<td><fmt:formatDate value="${board.regDate }" pattern="yyyy-MM-dd" /></td>
					<td>${board.cnt }</td>
				</tr>
			</c:forEach>
			
		</table>
		<br />
		<a href="insertBoard.jsp">
			<spring:message code="message.board.list.link.insertBoard" />
		</a>
	</center>
</body>
</html>

 

결과 이미지

 

 

결과 이미지