웹_프론트_백엔드/JAVA프레임윅기반_풀스택

2020.05.26

shine94 2020. 5. 26. 09:02

1. AJAX JSON/XML response 하기

 : 게시판 목록 list를 request 받아서 response 하기

 

[AJAX 첫번째 미션] response는 JSON 포맷, XML 포맷 양측 다 작성해보기

 

[AJAX 두번째 미션] response 받는 클라이언트 측에서 JSON, XML 포맷을 받아서 화면 업데이트 하기

 

 

2. [AJAX 첫번째 미션] Java로 JSON와 XML 만들 수 있는 방법 
1) Java로 JSON을 만드는 방법

방법1. StringBuilder 사용해서  JSON 텍스트 모두 만듦(단순하지만 노가다)
방법2. 외부 라이브러리 사용

 

2) Java로 XML을 만드는 방법
방법1. StringBuilder 사용해서 XML 텍스트 모두 만듦(단순하지만 노가다)

방법2. org.w3c.dom.*에 있는 기본 객체로 만듦(엄청 복잡하고 어렵다) 
방법3. 외부 라이브러리 사용

 

 

3. JSON과 XML의 외부 라이브러리 이클립스에 다운받기

1) JSON : JSON 라이브러리 다운로드

 : mvnrepository.com/artifact/org.json/json > 20180813 버전 선택

> Files의 bundle 선택하여 다운 받기

2) XML : JDOM 라이브러리 다운로드

: www.jdom.org > Downloads의 Binaries 클릭 > JDOM 2.0.6 다운 받기

 

> 필요한 라이브러리 다운로드 완..!!

> WebContent > WEB-INF > lib에 다운받은 라이브러리 파일 복사

 

 

4. JSP19_AJAX

<< 기존에 만든 JSP18_MVC의 common, beans 사용 >>

** common > D 클래스

 : DB 접속 정보, 쿼리문, 테이블명, 컬럼명 등 관리하는 클래스

package common;

/*
 * DB 접속 정보, 쿼리문, 테이블명, 컬럼명 등은
 * 별도로 관리하든지
 * XML, 초기화 파라미터 등에서 관리하는 것이 좋다.
 */
public class D {
	public static final String DRIVER = "oracle.jdbc.driver.OracleDriver";  // JDBC 드라이버 클래스
	public static final String URL = "jdbc:oracle:thin:@localhost:1521:XE";  // DB 접속 URL
	public static final String USERID = "scott0316";  // DB 접속 계정 정보
	public static final String USERPW = "tiger0316";
	
	public static final String SQL_WRITE_SELECT = 
			"SELECT * FROM test_write ORDER BY wr_uid DESC"; 

	public static final String SQL_WRITE_INSERT = "INSERT INTO test_write " +
		"(wr_uid, wr_subject, wr_content, wr_name) " +
		"VALUES(test_write_seq.nextval, ?, ?, ?)";

	public static final String SQL_WRITE_INC_VIEWCNT =  // 조회수 증가
			"UPDATE test_write SET wr_viewcnt = wr_viewcnt + 1 WHERE wr_uid = ?";

	public static final String SQL_WRITE_SELECT_BY_UID =  // 글 읽어 오기
			"SELECT * FROM test_write WHERE wr_uid = ?";

	public static final String SQL_WRITE_UPDATE = 
			"UPDATE test_write SET wr_subject = ?, wr_content = ? WHERE wr_uid = ?";

	public static final String SQL_WRITE_DELETE_BY_UID = 
			"DELETE FROM test_write WHERE wr_uid = ?";

}

 

[네이밍 일치 : 클래스 필드명 = DB 필드명 = form의 name명]

 

** com.lec.beans > WriteDTO 클래스

 : DTO(Data Transfer Object) 데이터를 담아 나르기 위한 객체

package com.lec.beans;

// DTO : Data Transfer Object
//    데이터를 담아 나르기 위한 객체

// 게시글DTO, 회원DTO, ... 필요한 데이터 객체들 만큼 정의
// Bean 객체

public class WriteDTO {
	private int uid;     // wr_uid
	private String subject;   //wr_subject
	private String content;   //wr_content
	private String name;  // wr_name
	private int viewCnt;   // wr_viewcnt
	private String regDate;   // wr_regdate
	
	// 개발시..
	// 다음 3가지 네이밍은 일치시켜주는 것이 좋다 .
	// 클래스 필드명 = DB 필드명  = form 의 name명
	
	// 기본생성자, 매개변수 생성자
	public WriteDTO() {
		super();
		System.out.println("WriteDTO() 객체 생성");
	}
	public WriteDTO(int uid, String subject, String content, String name, int viewCnt) {
		super();
		this.uid = uid;
		this.subject = subject;
		this.content = content;
		this.name = name;
		this.viewCnt = viewCnt;
		System.out.println("WriteDTO(uid, subject, content, name, viewCnt) 객체 생성");
	}
	
	// getter / setter
	public int getUid() {
		System.out.println("getUid() 호출");
		return uid;
	}
	public void setUid(int uid) {
		System.out.println("setUid(" + uid + ") 호출");
		this.uid = uid;
	}
	public String getSubject() {
		System.out.println("getSubject() 호출");
		return subject;
	}
	public void setSubject(String subject) {
		System.out.println("setSubject(" + subject + ") 호출");
		this.subject = subject;
	}
	public String getContent() {
		System.out.println("getContent() 호출");
		return content;
	}
	public void setContent(String content) {
		System.out.println("setContent(" + content + ") 호출");
		this.content = content;
	}
	public String getName() {
		System.out.println("getName() 호출");
		return name;
	}
	public void setName(String name) {
		System.out.println("setName(" + name + ") 호출");
		this.name = name;
	}
	public int getViewCnt() {
		System.out.println("getViewCnt() 호출");
		return viewCnt;
	}
	public void setViewCnt(int viewCnt) {
		System.out.println("setViewCnt(" + viewCnt + ") 호출");
		this.viewCnt = viewCnt;
	}
	public String getRegDate() {
		System.out.println("getRegDate() 호출");
		return regDate;
	}
	public void setRegDate(String regDate) {
		System.out.println("setRegDate(" + regDate + ") 호출");
		this.regDate = regDate;
	}
	
	// 테스트, 개발용으로 toString() 오버라이딩 하면 좋다.
	@Override
	public String toString() {
		return "WriteDTO] " + uid + " : " + subject + " : " 
			+ content + " : " + name + " : " + viewCnt + " : " + regDate;
	}
	
} // end DTO

 

** com.lec.beans > WriteDAO 클래스

 : DAO(Data Access Object) DB에 접속하여 트랜젝션을 수행하는 객체 

package com.lec.beans;

import java.sql.Connection;
import java.sql.Date;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Time;
import java.text.SimpleDateFormat;
import java.util.ArrayList;

import common.D;

// DAO : Data Access Object
//   DB 에 접속하여 트랜잭션을 수행하는 객체

// 다루는 데이터 소스의 종류에 따라 DAO는 여러개 정의 사용 가능

public class WriteDAO {
	Connection conn = null;
	Statement stmt = null;
	PreparedStatement pstmt = null;
	ResultSet rs = null;   // SELECT 결과, executeQuery()
	
	// DAO 객체가 생성될때 Connection 도 생성된다.
	public WriteDAO() {
		
		try {
			Class.forName(D.DRIVER);
			conn = DriverManager.getConnection(D.URL, D.USERID, D.USERPW);
			System.out.println("WriteDAO 생성, 데이터 베이스 연결!");
		} catch(Exception e) {
			e.printStackTrace();
			// throw e;
		}		
		
	} // 생성자

	// DB 자원 반납 메소드,
	public void close() throws SQLException {
		if(rs != null) rs.close();
		if(pstmt != null) pstmt.close();
		if(stmt != null) stmt.close();
		if(conn != null) conn.close();
	} // end close()
	
	// 새글 작성 <-- DTO
	public int insert(WriteDTO dto) throws SQLException {
		String subject = dto.getSubject();
		String content = dto.getContent();
		String name = dto.getName();
		
		int cnt = this.insert(subject, content, name);
		return cnt;
	}
	
	// 새글 작성 <-- 제목, 내용, 작성자 
	public int insert(String subject, String content, String name) throws SQLException {
		int cnt = 0;
		
		try {			
			pstmt = conn.prepareStatement(D.SQL_WRITE_INSERT);
			pstmt.setString(1, subject);
			pstmt.setString(2, content);
			pstmt.setString(3, name);
			
			cnt = pstmt.executeUpdate();
		} finally {
			close();			
		}

		return cnt;
	}
	
	// ResultSet --> DTO 배열로 리턴
	public WriteDTO [] createArray(ResultSet rs) throws SQLException {
		WriteDTO [] arr = null;  // DTO 배열
		
		ArrayList<WriteDTO> list = new ArrayList<WriteDTO>();
		
		while(rs.next()) {
			int uid = rs.getInt("wr_uid");
			String subject = rs.getString("wr_subject");
			String name = rs.getString("wr_name");
			String content = rs.getString("wr_content");
			int viewCnt = rs.getInt("wr_viewcnt");
			Date d = rs.getDate("wr_regdate");
			Time t = rs.getTime("wr_regdate");
			
			String regDate = "";
			if(d != null){
				regDate = new SimpleDateFormat("yyyy-MM-dd").format(d) + " "
						+ new SimpleDateFormat("hh:mm:ss").format(t);
			}
			
			WriteDTO dto = new WriteDTO(uid, subject, content, name, viewCnt);
			dto.setRegDate(regDate);
			list.add(dto);
			
		} // end while
		
		int size = list.size();
		
		if(size == 0) return null;
		
		arr = new WriteDTO[size];
		list.toArray(arr);  // List -> 배열		
		return arr;
	}
	
	// 전체 SELECT
	public WriteDTO [] select() throws SQLException {
		WriteDTO [] arr = null;
		
		try {
			pstmt = conn.prepareStatement(D.SQL_WRITE_SELECT);
			rs = pstmt.executeQuery();
			arr = createArray(rs);
		} finally {
			close();
		}		
		
		return arr;
	} // end select()
	
	// 특정 uid 의 글 내용 읽기, 조회수 증가
	// viewCnt 도 1 증가 해야 하고, 글 읽어와야 한다 --> 트랜잭션 처리
	public WriteDTO [] readByUid(int uid) throws SQLException{
		int cnt = 0;
		WriteDTO [] arr = null;
		
		try {
			// 트랜잭션 처리
			// Auto-commit 비활성화
			conn.setAutoCommit(false);
			
			// 쿼리들 수행
			pstmt = conn.prepareStatement(D.SQL_WRITE_INC_VIEWCNT);
			pstmt.setInt(1, uid);
			cnt = pstmt.executeUpdate();
			
			pstmt.close();
			
			pstmt = conn.prepareStatement(D.SQL_WRITE_SELECT_BY_UID);
			pstmt.setInt(1, uid);
			rs = pstmt.executeQuery();
			
			arr = createArray(rs);
			conn.commit();
			
		} catch(SQLException e) {
			conn.rollback();
			throw e;
		} finally {
			close();
		}
		
		return arr;
	} // end readByUid()
	
	
	// 특정 uid 의 글 만 SELECT (조회수 증가 없슴!)
	public WriteDTO [] selectByUid(int uid) throws SQLException {
		WriteDTO [] arr = null;
		
		try {
			pstmt = conn.prepareStatement(D.SQL_WRITE_SELECT_BY_UID);
			pstmt.setInt(1, uid);
			rs = pstmt.executeQuery();
			arr = createArray(rs);
		} finally {
			close();
		}
		return arr;
	}
	
	
	// 특정 uid 의 글 수정 (제목, 내용)
	public int update(int uid, String subject, String content) throws SQLException {
		int cnt = 0;
		try {
			pstmt = conn.prepareStatement(D.SQL_WRITE_UPDATE);
			pstmt.setString(1, subject);
			pstmt.setString(2, content);
			pstmt.setInt(3, uid);
			
			cnt = pstmt.executeUpdate();
		} finally {
			close();
		}		
		
		return cnt;
	} // end update()
	
	// 특정 uid 글 삭제하기
	public int deleteByUid(int uid) throws SQLException {
		int cnt = 0;
		try {
			pstmt = conn.prepareStatement(D.SQL_WRITE_DELETE_BY_UID);
			pstmt.setInt(1, uid);
			cnt = pstmt.executeUpdate();
		} finally {
			close();
		}		
		return cnt;
	} // end deleteByUid()
	
} // end DAO

 

** AJAX 용 Controller 작성하기

 : com.controller.write > WriteController 서블릿

package com.controller;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.command.write.AjaxListCommand;
import com.command.write.Command;
import com.command.write.ListCommand;

@WebServlet("*.ajax")
public class AjaxController extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    public AjaxController() {
        super();
    }

	protected void doGet(HttpServletRequest request, HttpServletResponse response) 
			throws ServletException, IOException {
		ajaxAction(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) 
			throws ServletException, IOException {
		ajaxAction(request, response);
	}
	
	protected void ajaxAction(HttpServletRequest request, HttpServletResponse response) 
			throws ServletException, IOException {
		System.out.println("ajaxAction()");
		
		request.setCharacterEncoding("UTF-8");
		
		// 컨트롤러는 다음 두개를 선택해야 한다.
		String viewPage = null;   // 어떠한 뷰? --> 페이지
		Command command = null;   // 어떠한 커맨드? --> 어떠한 로직 수행.
		
		// URL로부터 URI, ContextPath, Command 분리 
		String uri = request.getRequestURI();
		String conPath = request.getContextPath();
		String com = uri.substring(conPath.length());
		
		// 테스트 출력
		System.out.println("uri: " + uri);
		System.out.println("conPath: " + conPath);
		System.out.println("com: " + com);
		
		// 컨트롤러는 커멘드에 따라, 로직을 수행하고
		// 결과를 내보낼 view를 결정한다.
		switch(com) {
		case "/list.ajax":	// 글 목록 AJAX 요청
			// 글 목록 읽기
			new ListCommand().execute(request, response);
			// 읽어온 데이터를 다음 커멘드에 넘겨줌(request에 담겨 있다)
			new AjaxListCommand().execute(request, response);
			break;
		} // end switch
		
	}

}

 

** AJAX 용 Command 만들기

 : com.command.write > AjaxListCommand 클래스

package com.command.write;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;
import org.json.JSONArray;
import org.json.JSONObject;

import com.lec.beans.WriteDTO;

public class AjaxListCommand implements Command {

	@Override
	public void execute(HttpServletRequest request, HttpServletResponse response) {
		// parameter 받아오기, 없으면 json 동작 디폴트로
		String reqType = request.getParameter("reqType");
		if(reqType == null) {reqType = "json";}
		
		// "xml" 혹은 "json"으로 response 하기
		switch(reqType) {
		case "xml":
			responseXML(request, response);
			break;
			
		case "json":
			responseJSON(request, response);
			break;
			
		default:
			responseJSON(request, response);
			
		} // end switch
		
	} // end execute()
	
	private void responseJSON(HttpServletRequest request, HttpServletResponse response) {
		WriteDTO[] dtoArr = (WriteDTO[])request.getAttribute("list");
		
		JSONObject jsonOutput = new JSONObject();	// 최종 결과는 object
		
		if(dtoArr == null) {
			jsonOutput.put("status", "FAIL");
		} else {
			jsonOutput.put("status", "OK");	// object에 property-value 추가
			int count = dtoArr.length;
			jsonOutput.put("count", count);
			
			// 글 목록
			JSONArray dataArr = new JSONArray();	// array
			
			for(int i = 0; i < count; i++) {
				JSONObject dataObj = new JSONObject();
				
				dataObj.put("uid", dtoArr[i].getUid());
				dataObj.put("name", dtoArr[i].getName());
				dataObj.put("subject", dtoArr[i].getSubject());
				dataObj.put("content", dtoArr[i].getContent());
				dataObj.put("viewCnt", dtoArr[i].getViewCnt());
				dataObj.put("regdate", dtoArr[i].getRegDate());
				
				// array에 추가
				dataArr.put(dataObj);
			}
			
			jsonOutput.put("data", dataArr);
			
		}
		
		String jsonString = jsonOutput.toString();	// JSON 객체 --> String 변환
		
		response.setContentType("application/json; charset=utf-8");	// MIME 설정
		
		try {
			response.getWriter().write(jsonString);	// response 내보내기
			
		} catch (IOException e) {
			e.printStackTrace();
			
		}
		
	} // end responseJSON()
	
	private void responseXML(HttpServletRequest request, HttpServletResponse response) {
		WriteDTO[] dtoArr = (WriteDTO[])request.getAttribute("list");
		
		Document dom = new Document();
		
		Element rootElement = new Element("WriteList");	// <WriteList>..</WriteList>
		
		dom.setRootElement(rootElement);
		
		Element statusElement = new Element("status");
		if(dtoArr == null ) {
			statusElement.setText("FAIL");
			
		} else {
			statusElement.setText("OK");
			
			// 데이터 개수
			int count = dtoArr.length;
			Element countElement = new Element("Count")
					.setText("" + count)
					.setAttribute("id", "ccc")
					.setAttribute("pw", "xxx")
					;
			rootElement.addContent(countElement);
			
			// 데이터 끌어오기!
			for(int i = 0; i < count; i++) {
				Element dataElement = new Element("Data");
				
				dataElement.addContent(new Element("uid").setText(dtoArr[i].getUid() + ""));
				dataElement.addContent(new Element("name").setText(dtoArr[i].getName() + ""));
				dataElement.addContent(new Element("subject").setText(dtoArr[i].getSubject() + ""));
				dataElement.addContent(new Element("content").setText(dtoArr[i].getContent() + ""));
				dataElement.addContent(new Element("viewCnt").setText(dtoArr[i].getViewCnt() + ""));
				dataElement.addContent(new Element("regdate").setText(dtoArr[i].getRegDate() + ""));
				
				rootElement.addContent(dataElement);
			}
		}
		rootElement.addContent(statusElement);
		
		// new XMLOutputter(Format.getPrettyFormat()) : 콘솔에서도 이쁘게 출력 가능함
		XMLOutputter xmlOutputter = new XMLOutputter(Format.getPrettyFormat());
		System.out.println(xmlOutputter.outputString(dom));	// 테스트용
		
		try {
			response.setContentType("application/xml; charset=utf-8");	// text/xml도 가능.
			response.getWriter().write(xmlOutputter.outputString(dom));
			
		} catch(IOException e) {
			e.printStackTrace();
			
		}
		
	} // end responseXML()

}

 

** 클라이언트  페이지

 : ajaxlist.html

<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>jQuery + AJAX</title>
<style>
table,th,td {
  border : 1px solid black;
  border-collapse: collapse;
}
th,td {
  padding: 5px;
}
</style>
</head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body>
<h1>목록 보기 : AJAX</h1>
<form>
<button id="btn_load" type="button">목록 가져오기</button>
<button id="btn_remove" type="button">목록 지우기</button>
</form>
<br><br>
<h2>AJAX + XML</h2>
<table id="demoXML"></table>
<hr>
<h2>AJAX + JSON</h2>
<table id="demoJSON"></table>
<script>

$(document).ready(function(){
	
	// 목록 가져오기 버튼 클릭시
	$("#btn_load").click(function(){
		
		// XML
		var url = "http://localhost:8082/JSP19_AJAX/list.ajax?reqType=xml";
		
		$.ajax({
			url : url
			, type : "GET"
			, cache : false
			, success : function(data, status) {
				if(status == "success") {parseXML(data);}
			}
		});
		
		// JSON
		var url = "http://localhost:8082/JSP19_AJAX/list.ajax?reqType=json";
		
		$.ajax({
			url : url
			, type : "GET"
			, cache : false
			, success : function(data, status) {
				if(status = "success") {parseJSON(data);}
			}
		});
		
		$("#btn_remove").click(function() {
			$("#demoXML").html("");
			$("#demoJSON").html("");
		});
		
	});

});
 
function parseXML(xmlDOM) {
	var table = "<tr><th>uid</th><th>name</th><th>subject</th>"
		+ "<th>content</th><th>viewCnt</th><th>regdate</th></tr>";
	
	$(xmlDOM).find("Data").each(function(){
		table += "<td>" + $(this).find("uid").text() + "</td>";
		table += "<td>" + $(this).find("name").text() + "</td>";
		table += "<td>" + $(this).find("subject").text() + "</td>";
		table += "<td>" + $(this).find("content").text() + "</td>";
		table += "<td>" + $(this).find("viewCnt").text() + "</td>";
		table += "<td>" + $(this).find("regdate").text() + "</td>";
		table += "</tr>";
	});
	$("#demoXML").html(table);
}

function parseJSON(jsonObj){
	var data = jsonObj.data;
	var i;
	
	var table = "<tr><th>uid</th><th>name</th><th>subject</th>"
		+ "<th>content</th><th>viewCnt</th><th>regdate</th></tr>";
	for(i = 0; i < data.length; i++) {
		table += "<tr>";
		table += "<td>" + data[i].uid + "</td>";
		table += "<td>" + data[i].name + "</td>";
		table += "<td>" + data[i].subject + "</td>";
		table += "<td>" + data[i].content + "</td>";
		table += "<td>" + data[i].viewCnt + "</td>";
		table += "<td>" + data[i].regdate + "</td>";
		table += "</tr>";
	}
	$("#demoJSON").html(table);
}
 
</script>

</body>
</html>

'웹_프론트_백엔드 > JAVA프레임윅기반_풀스택' 카테고리의 다른 글

2020.05.28  (0) 2020.05.28
2020.05.27  (0) 2020.05.27
2020.05.25  (0) 2020.05.25
2020.05.22  (0) 2020.05.22
2020.05.21  (0) 2020.05.21