static 안에 저거 혼자 있으면 SPA (Single Page Application)가 된다.

Untitled

Untitled

Controller.java

package com.jeungsu.silver.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import com.jeungsu.silver.service.SujinService;
import com.jeungsu.silver.vo.SujinVO;

import lombok.extern.slf4j.Slf4j;

// Restful api 구현
@RestController
@RequestMapping("/api")
@Slf4j
public class SujinController {
   
   // 컨트롤러는 서비스를 부름
   @Autowired
   private SujinService sujinService;
   
   // 리스트 조회
   @GetMapping(value="/sujins", produces = "application/json;charset=utf-8")
   public List<SujinVO> sujinList(){
      return sujinService.sujinList();
   }
   
   // 한개 조회
   @GetMapping(value="/sujin/{num}", produces = "application/json;charset=utf-8")
   public SujinVO sujinOne(@PathVariable("num") int sujinNum) {
      return sujinService.sujinOne(sujinNum);
   }
   
   // 삽입
   @PostMapping(value="/sujin", produces = "application/json;charset=utf-8")
   public int sujinInsert(@RequestBody SujinVO sujinVO) {
      return sujinService.sujinInsert(sujinVO);
   }
   
   // 수정
   @PutMapping(value="/sujin", produces = "application/json;charset=utf-8")
   public int sujinUpdate(@RequestBody SujinVO sujinVO) {
      return sujinService.sujinUpdate(sujinVO);
   }
   
   // 삭제
   @DeleteMapping(value="/sujin/{num}", produces = "application/json;charset=utf-8")
   public int sujinDelete(@PathVariable("num") int sujinNum) {
      return sujinService.sujinDelete(sujinNum);
   }
   
}

indet.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<style>
	#list{
		height:50vh;
		overflow: scroll;
	}
</style>
</head>
<body>
	<h1>혼자있음 SPA(Single Page Application)</h1>
	<div id="list"></div>
	<div id="gitae">
		<form action="">
			번호 <input type="text" name="sujinNum" value=""><br>
			이름 <input type="text" name="sujinName" value=""><br>
			내용 <input type="text" name="sujinContent" value=""><br>
			<input type="button" onclick="fInsert()" value="입력">
			<input type="button" onclick="fUpdate()" value="수정">
			<input type="button" onclick="fDel()" value="삭제">
		</form>
	</div>
<script>
		// Sujin 삭제
	function fDel(){
		let sujinNum = myForm.sujinNum.value;
		
		let xhr = new XMLHttpRequest();
		xhr.open("delete", `/api/sujin/${sujinNum}`, true);
		xhr.setRequestHeader("Content-Type", "application/json;charset=utf-8");
		xhr.onreadystatechange = function(){
			if(xhr.readyState == 4 && xhr.status == 200){
				if(xhr.responseText != 0){
					alert("서버에서 잘 처리 완료");
					fList();	// 일단 간단하게 다시 리스트를 부르는 걸로
								// 실제는 tr만 추가적으로 붙여주는 것이 효율적
				}
			}
		}
		xhr.send();
	}

		// Sujin 수정
	function fUpdate(){
		let data = {
			sujinNum:myForm.sujinNum.value,
			sujinName:myForm.sujinName.value,
			sujinContent:myForm.sujinContent.value
		}
		let xhr = new XMLHttpRequest();
		xhr.open("put", `/api/sujin`, true);
		xhr.setRequestHeader("Content-Type", "application/json;charset=utf-8");
		xhr.onreadystatechange = function(){
			if(xhr.readyState == 4 && xhr.status == 200){
				if(xhr.responseText != 0){
					alert("서버에서 잘 처리 완료");
					fList();	// 일단 간단하게 다시 리스트를 부르는 걸로
								// 실제는 tr만 추가적으로 붙여주는 것이 효율적
				}
			}
		}
		xhr.send(JSON.stringify(data));
	}

	// Sujin 넣기
	function fInsert(){
		
		// 개발시에는 넘기는 data가 눈에 잘 들어오게 하는 게 디버깅에 효율적
		let data = {
			sujinName:myForm.sujinName.value,
			sujinContent:myForm.sujinContent.value
		}
		let xhr = new XMLHttpRequest();
		xhr.open("post", `/api/sujin`, true);
		xhr.setRequestHeader("Content-Type", "application/json;charset=utf-8");
		xhr.onreadystatechange = function(){
			if(xhr.readyState == 4 && xhr.status == 200){
				if(xhr.responseText != 0){
					alert("서버에서 잘 처리 완료");
					fList();	// 일단 간단하게 다시 리스트를 부르는 걸로
								// 실제는 tr만 추가적으로 붙여주는 것이 효율적
				}
			}
		}
		xhr.send(JSON.stringify(data));
	}

	const myList = document.querySelector("#list")

	// 리스트 출력함수
	function fList(){
		let xhr = new XMLHttpRequest();
		xhr.open("get", "/api/sujins", true);
		xhr.onreadystatechange = function(){
			if(xhr.readyState == 4 && xhr.status == 200){
				let dataList = JSON.parse(xhr.responseText);
				let tblStr = "<table border=1>"
				tblStr += "<tr><th>넘버</th><th>이름</th><th>내용</th></tr>"
				for(let i=0; i<dataList.length; i++){
					tblStr += "<tr>";
					tblStr += `<td><a href="#" onclick="fOne('${dataList[i].sujinNum}')">${dataList[i].sujinNum}</a></td>`
					tblStr += `<td>${dataList[i].sujinName}</td>`
					tblStr += `<td>${dataList[i].sujinContent}</td>`
					tblStr += "</tr>";
				}
				tblStr += "</table>";
				myList.innerHTML = tblStr;
			}
		}
		xhr.send();
	}

	// Sujin 1개만 가져오기
	const myForm = document.forms[0]
	function fOne(pNum){
		event.preventDefault();  // a 태그 내장기능 href로 이동하는 거 막기
		let xhr = new XMLHttpRequest();
		xhr.open("get", `/api/sujin/${pNum}`, true);
		xhr.onreadystatechange = function(){
			if(xhr.readyState == 4 && xhr.status == 200){
				let sujinOne = JSON.parse(xhr.responseText);
				myForm.sujinNum.value = sujinOne.sujinNum;
				myForm.sujinName.value = sujinOne.sujinName;
				myForm.sujinContent.value = sujinOne.sujinContent;
			}
		}
		xhr.send();
	}
	window.addEventListener("DOMContentLoaded", fList);
</script>
</body>
</html>

Untitled