상세 컨텐츠

본문 제목

sts4 spring boot 세번쨍

스프링부트

by e7e 2023. 7. 10. 08:03

본문

2023.07.04 - [스프링부트] - sts4 spring boot 두번쨍

까지 잘 따라 했다면 이제 프론트단(화면) 을  간단히 구현해서  AJAX와 RESTFUL을 연계해보장

 

확인용 더미 데이터를 아래 insert문을 이용해서 데이타베이스에 넣도록 하장.

insert into sujin(sujin_num,sujin_name,sujin_content,sujin_file)
    values ( seq_sujin.nextval, '운제경', '교육과정이 ...', '/merong/roze1.jpg' );
insert into sujin(sujin_num,sujin_name,sujin_content,sujin_file)
    values ( seq_sujin.nextval, '빙지형', '만족스러운 ...', '/merong/roze2.jpg' );
insert into sujin(sujin_num,sujin_name,sujin_content,sujin_file)
    values ( seq_sujin.nextval, '정호연', '8개월간 좋...', '/merong/roze3.jpg' );
insert into sujin(sujin_num,sujin_name,sujin_content,sujin_file)
    values ( seq_sujin.nextval, '순에스라', '교육과정이 ...', '/merong/roze4.jpg' );
insert into sujin(sujin_num,sujin_name,sujin_content,sujin_file)
    values ( seq_sujin.nextval, '차규찬', '교수님들께서...', '/merong/roze5.jpg' );
insert into sujin(sujin_num,sujin_name,sujin_content,sujin_file)
    values ( seq_sujin.nextval, '혁유재', '교육과정이 ...', '/merong/roze6.jpg' );
insert into sujin(sujin_num,sujin_name,sujin_content,sujin_file)
    values ( seq_sujin.nextval, '빙민', '8개월간 좋...', '/merong/roze7.jpg' );
insert into sujin(sujin_num,sujin_name,sujin_content,sujin_file)
    values ( seq_sujin.nextval, '성하웅', '선생님들이 ...', '/merong/roze8.jpg' );
insert into sujin(sujin_num,sujin_name,sujin_content,sujin_file)
    values ( seq_sujin.nextval, '제갈선하', '만족스러운 ...', '/merong/roze9.jpg' );
insert into sujin(sujin_num,sujin_name,sujin_content,sujin_file)
    values ( seq_sujin.nextval, '섭려환', '8개월 동안...', '/merong/roze10.jpg' );
insert into sujin(sujin_num,sujin_name,sujin_content,sujin_file)
    values ( seq_sujin.nextval, '즙준렬', '8개월간 좋...', '/merong/roze11.jpg' );
insert into sujin(sujin_num,sujin_name,sujin_content,sujin_file)
    values ( seq_sujin.nextval, '조명선', '교수님들께서...', '/merong/roze12.jpg' );
insert into sujin(sujin_num,sujin_name,sujin_content,sujin_file)
    values ( seq_sujin.nextval, '정화린', '커리큘럼이 ...', '/merong/roze13.jpg' );
insert into sujin(sujin_num,sujin_name,sujin_content,sujin_file)
    values ( seq_sujin.nextval, '다리환', '실력이 많이...', '/merong/roze14.jpg' );
insert into sujin(sujin_num,sujin_name,sujin_content,sujin_file)
    values ( seq_sujin.nextval, '제갈규준', '커리큘럼이 ...', '/merong/roze15.jpg' );
insert into sujin(sujin_num,sujin_name,sujin_content,sujin_file)
    values ( seq_sujin.nextval, '즙제이슨', '한국 최고의...', '/merong/roze16.jpg' );
insert into sujin(sujin_num,sujin_name,sujin_content,sujin_file)
    values ( seq_sujin.nextval, '증하다', '너무 알찬 ...', '/merong/roze17.jpg' );
insert into sujin(sujin_num,sujin_name,sujin_content,sujin_file)
    values ( seq_sujin.nextval, '옥에반', '교수님들께서...', '/merong/roze18.jpg' );
insert into sujin(sujin_num,sujin_name,sujin_content,sujin_file)
    values ( seq_sujin.nextval, '탁수만', '너무 알찬 ...', '/merong/roze19.jpg' );
insert into sujin(sujin_num,sujin_name,sujin_content,sujin_file)
    values ( seq_sujin.nextval, '온엘리', '교육과정이 ...', '/merong/roze20.jpg' );

commit;

 

부트에서는 src/main/resources 에 보면 static 폴더가 누네 들어온당.

말그대로 정적파일(html,css,js 등등 서버입장에서 정적파일)을 저장하는 곳이당.

 

여기에 index.html을 만들어주면 자동으로 시작페이지가 된당.

(당근 controller에 "/"에 맵핑된 것이 없어야 한당!)

브라우져 주소표시줄에 http://localhost:포트번호  를 입력하면 index.html화면이  보일거시당.

index.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>RESTFUL API 테스트</title>
<style>
	* {
		box-sizing: border-box;
	}
	#wrapper {
		text-align: center;
	}
	#list {
		width:70%;
		height: 400px;
		border:5px solid rgb(166, 0, 255);
		overflow: auto;
	}
	#toolbar{
		width:70%;
		border:5px solid orange;
		padding-bottom: 5%;
		
		/*height: 50px;*/
	}
	div {
		margin: 0 auto;
		min-width: 400px;
	}
	input[type=button] {
		/* 아래로 9px 이동 크기 1.3배 */
		transform: translateY(9px) scale(1.3); 
	}
	#muTable {
		margin: 0 auto;
	}
</style>
</head>
<body>
<div id="wrapper">
	<h1>RESTFUL API 테스통</h1>
	<div id="list"></div>
	<div id="toolbar">
		<br>
		<form>
			<table id="muTable">
				<tr>
					<td>넘</td>
					<td><input type="text" name="sujinNum" value="" ></td>
				</tr>
				<tr>
					<td>이름</td>
					<td><input type="text" name="sujinName" value="" ></td>
				</tr>
				<tr>
					<td>내용</td>
					<td><input type="text" name="sujinContent" value="" ></td>
				</tr>
				<tr>
					<td>파일</td>
					<td><input type="text" name="sujinFile" value="" ></td>
				</tr>
			</table>
		</form>
		<input type="button" value="입력" onclick="fPostInput()">&nbsp;&nbsp;
		<input type="button" value="수정" onclick="fPutUpdate()">&nbsp;&nbsp;
		<input type="button" value="삭제" onclick="fDeleteDel()">&nbsp;&nbsp;
	</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.0/jquery.min.js"></script>
<script>
	const myForm = document.forms[0];
	const myList = document.querySelector("#list");

	// 기능 함수
	// 테이블 TR 요런건 기본으로 제공하는 게 좋음
	const fTrClickMouseOverOut = ()=>{
		let trs = document.querySelectorAll("tr");
		for(let i=0; i<trs.length; i++){			
			trs[i].addEventListener("mouseover",()=>{
				trs[i].style.backgroundColor = "black";
				trs[i].style.color = "orange";
			});

			trs[i].addEventListener("mouseout",function(){
				this.style.backgroundColor="white";
				this.style.color = "black";
				this.style.fontWeight = "normal";
			});
		}
	}

	// 테이블 맹그는 함수
	const fMakeTable = (sujins) =>{
		let tableStr = `<table border=1 style="width:100%"><tbody>`;
		tableStr += `<tr><th>Num</th><th>Name</th><th>Content</th><th>File</th></tr>`;
		for(let i=0; i<sujins.length; i++){
			let sujin = sujins[i];
			tableStr += `<tr onclick="fGetOne(${sujin.sujinNum})">`;
		    tableStr += `<td>${sujin.sujinNum}</td>`;		
		    tableStr += `<td>${sujin.sujinName}</td>`;		
		    tableStr += `<td>${sujin.sujinContent}</td>`;		
		    tableStr += `<td>${sujin.sujinFile}</td>`;		
			tableStr += `</tr>`;
		}
		tableStr += `<tr></tbody></table>`;
		myList.innerHTML = tableStr;
		
		//테이블이 동적으로 새로 맹글어지므로, TR이벤트도 그때마당
		fTrClickMouseOverOut();
	}


	// 백엔드 Restful SujinController에 대응하는 함수들
	// get으로 list(sujins)가져오깅
	const fGetList = ()=>{
		let xhr = new XMLHttpRequest();
		xhr.open("get","/api/sujins",true);
		xhr.onreadystatechange = ()=>{
			if(xhr.readyState == 4 && xhr.status == 200){
				//console.log("항상먼저화깅:",xhr.responseText);
				let voList = JSON.parse(xhr.responseText);
				fMakeTable(voList.sort((a,b)=>{
					return a.sujinNum - b.sujinNum;
				})); 
			}
		}
		xhr.send();
	}
	fGetList(); // 그냥 바로 리스트 콜!

	// get으로 1개 row(sujin) 가져오깅
	const fGetOne = (sujinNum)=>{
		let xhr = new XMLHttpRequest();
		xhr.open("get",`/api/sujin/${sujinNum}`,true);
		xhr.onreadystatechange = ()=>{
			if(xhr.readyState == 4 && xhr.status == 200){
				//console.log("항상먼저화깅:",xhr.responseText);
				let sujinVO = JSON.parse(xhr.responseText);
				// form안의 element요소에 가져온 값 넣어주깅
				myForm.sujinNum.value = sujinVO.sujinNum;
				myForm.sujinName.value = sujinVO.sujinName;
				myForm.sujinContent.value = sujinVO.sujinContent;
				myForm.sujinFile.value = sujinVO.sujinFile;
			}
		}
		xhr.send();
	}

	// post로 insert 1개 row(sujin) 
	const fPostInput = ()=>{
		// 아작스 쓸땡, 넘기는 데이타는 누네 잘 보이도록..디버깅 용이
		// FormData를 이용하지 않을 때는 JSON문자열로 보내는 거시 확장성이 좋당
		// 자바는 자바스크립트의 객체를 이해못한당.(문자열은 글자임을 안당)
		let sujinVO = JSON.stringify({
//			sujinNum : myForm.sujinNum.value,  // sequence 쓰므로 필요없음
			sujinName : myForm.sujinName.value,
			sujinContent : myForm.sujinContent.value,
			sujinFile : myForm.sujinFile.value,
		});

		let xhr = new XMLHttpRequest();
		xhr.open("post","/api/sujin",true);
		xhr.setRequestHeader("Content-Type","application/json;charset=utf-8");
		xhr.onreadystatechange = ()=>{
			if(xhr.readyState == 4 && xhr.status == 200){
				console.log("항상먼저화깅:",xhr.responseText);
				let rowCnt = xhr.responseText;
				if(rowCnt != 0){
					alert("잘 추가 되었다네용");
					fGetList();  // 리스트 다시 가져오깅, 일부렁?(다른방법은?)
					console.log("체킁:",myList.scrollHeight);

					//그려지고 있는동안(Rendering중)에 움직이면 쪼메 모자라게 됨)
					setTimeout(()=>{  
						myList.scrollTo(0,myList.scrollHeight);
					},30);
				}
			}
		}
		xhr.send(sujinVO);   
	}

	// 참고 postInput을 jqury $.ajax로 고친다면 
	const fPostInput2 = ()=>{
		let sujinVO = JSON.stringify({
//			sujinNum : myForm.sujinNum.value,  // sequence 쓰므로 필요없음
			sujinName : myForm.sujinName.value,
			sujinContent : myForm.sujinContent.value,
			sujinFile : myForm.sujinFile.value,
		});

		$.ajax({
			type:"post",
			url:"/api/sujin",
			contentType:"application/json;charset=utf-8",
			dataType:"text",
			data: sujinVO,
			success:function(rslt){
				console.log("항상먼저화깅:",rslt);
				let rowCnt = rslt;
				if(rowCnt != 0){
					alert("잘 추가 되었다네용");
					fGetList();  // 리스트 다시 가져오깅, 일부렁?(다른방법은?)
					console.log("체킁:",myList.scrollHeight);

					//그려지고 있는동안(Rendering중)에 움직이면 쪼메 모자라게 됨)
					setTimeout(()=>{  
						myList.scrollTo(0,myList.scrollHeight);
					},30);
				}
			}
		})
	}

	// put으로 update 수정 부르깅
	const fPutUpdate = ()=>{
		let sujinVO = JSON.stringify({
			sujinNum : myForm.sujinNum.value,
			sujinName : myForm.sujinName.value,
			sujinContent : myForm.sujinContent.value,
			sujinFile : myForm.sujinFile.value,
		});

		let xhr = new XMLHttpRequest();
		xhr.open("put","/api/sujin",true);
		xhr.setRequestHeader("Content-Type","application/json;charset=ut-8");
		xhr.onreadystatechange = ()=>{
			if(xhr.readyState == 4 && xhr.status == 200){
				let rowCnt = xhr.responseText;
				if(rowCnt != 0){
					alert("잘 수정 되었다네용");
					fGetList();  // 리스트 다시 가져오깅, 일부렁?(다른방법은?)
				}
			}
		}
		xhr.send(sujinVO);
	}

	// delete 메소드로 요청해서 지우깅
	const fDeleteDel = ()=>{
		let	sujinNum = myForm.sujinNum.value;
		
		let xhr = new XMLHttpRequest();
		xhr.open("delete",`/api/sujin/${sujinNum}`,true);
		xhr.setRequestHeader("Content-Type","application/json;charset=ut-8");
		xhr.onreadystatechange = ()=>{
			if(xhr.readyState == 4 && xhr.status == 200){
				console.log("항상먼저화깅:",xhr.responseText);
				let rowCnt = xhr.responseText;
				if(rowCnt != 0){
					alert("잘 지워졌다네용");
					fGetList(); // 리스트 다시 가져오깅, 일부렁?(다른방법은?)
				}
			}
		}
		xhr.send();
	}
</script>
</body>
</html>

참고로 fPostInput은 Jquery $.ajax사용시에 변환모습을 보여주기 위해서 

fPostInput2를 추가로 소스에 담아버렸당.

script src에 jquery를 가져와야함을 잊지말장.

최초에 list를 불러오고, 테이블을 클릭하면 해당 글을 불러오고,

입력/수정/삭제는 처리 후에 무조건 list를 다시 불러오도록 작성하였는데, 백엔드 restful에

1:1로 맵핑되도록 하기 위한 것일 뿐, 생각을 좀 더 하면, 좀더 나은 방법이 보일 거시당.!

 

Restful + AJAX는 웹 개발자라면 당연 필수라 하디 아늘수 업지 않지 않지 안탕!

JSP가 구지 필요없음을 느꼈는강?

[상황에 따라(검색엔진 친화적) 필요하기도 하고, SSG도 하나의 흐름이당당당!!]

 

JSP 나를 알아도, 나는 JSP 잘 몰라용

Form 나를 알아도, 나는 Form 잘 몰라용

RESTFUL 위에 .....

AJAX 지나가면..........

 

https://www.youtube.com/watch?v=qEgnbQUD_vk 

 

'스프링부트' 카테고리의 다른 글

sts4 spring boot 두번쨍  (0) 2023.07.04
sts4 spring boot 첫번쨍  (0) 2023.07.03

관련글 더보기