본문 바로가기
프로그래밍/Springboot-토이프로젝트

Springboot + JQuery Ajax로 CRUD 어플리케이션 구현-04【화면 + Jquery Ajax통신】

by 코이킹 2021. 6. 6.
반응형

지난 포스트에 이어서 JSP를 사용하여 화면을 만들고 Jquery로 Ajax 통신을 구현하여 API와 CRUD 통신에 성공하는 것까지 정리하려 합니다.

 

전체 소스코드는 아래에 URL에 있습니다.

https://github.com/leeyoungseung/item-admin

1. 내장 Tomcat에서 JSP사용하기

Spring boot의 내장 Tomcat에서 JSP를 사용하기 위해서는 몇 가지 설정과 라이브러리를 추가해주어야 합니다.

※ 설정 방법

1) build.gradle의존성 추가

 // JSP를 페이지로 인식하기 위한 라이브러리
 implementation 'org.apache.tomcat.embed:tomcat-embed-jasper'
 // JSTL을 사용할 경우 추가해야하는 라이브러리
 implementation 'javax.servlet:jstl:1.2'


2) build.gradle플러그인 추가 

apply plugin: 'war'

2. JSP로 화면 구현하기

- index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script async src="/webjars/jquery/3.6.0/jquery.min.js"></script>
<script async src="/js/ajax-item-admin.js"></script>
<link href="/webjars/bootstrap/4.6.0/css/bootstrap.min.css"
	rel="stylesheet" id="bootstrap-css">
<style type="text/css">
.container {
	max-width: 960px;
}

.form-control-borderless {
	border: none;
}
.form-control-borderless:hover, .form-control-borderless:active,
	.form-control-borderless:focus {
	border: none;
	outline: none;
	box-shadow: none;
}
#item-list {
	border-style: outset;
}
</style>
</head>
<body class="bg-light">

	<div class="container">
		<div class="py-5 text-center">
			<img class="d-block mx-auto mb-4"
				src="/img/item-logo.png"
				alt="" width="72" height="72">
			<h1>Item Admin Page</h1>
			<p class="lead">상품 검색, 등록, 정보수정, 삭제등의 관리를 할 수 있습니다.</p>
		</div>
		<div class="row justify-content-center">
			<div class="col-12 col-md-10 col-lg-8">
				<form class="card card-sm">
					<div class="card-body row no-gutters align-items-center">
						<div class="col-auto">
							<i class="fas fa-search h4 text-body"></i>
						</div>
						<div class="col">
							<input
								class="form-control form-control-lg form-control-borderless"
								type="search"
								placeholder="Please Iuput Item Number And Click Search Button!" id="search">
						</div>
						<div class="col-auto">
							<button class="btn btn-lg btn-success" type="button" id="search-btn" >Search</button>
						</div>
					</div>
				</form>
			</div>
			<!--end of col-->
			<div class="card-body row no-gutters align-items-center">
				<button class="btn btn-lg btn-info" type="button" id="create-form-btn">Apply Item Info</button>
			</div>
		</div>
		<br />
		<div id="item-list">
		</div>
	</div>
	<!-- .container -->
</body>


</html>

3. 부트스트랩 + Jquery 의존성 추가

Jquery나 부트스트랩을 cdn으로 적용하는 방법도 있지만, 이 프로젝트에서는 Jar라이브러리를 추가하여 Jquery와 부트스트랩을 적용합니다.

※ 설정 방법
1) build.gradle의존성 추가

implementation group: 'org.webjars', name: 'jquery', version: '3.6.0'
implementation group: 'org.webjars', name: 'bootstrap', version: '4.6.0'


2) index.jsp에 Jquery와 부트스트랩 적용하기

index.jsp에 Jquery와 부트스트랩을 적용하기 위해서는. jar파일에서 정확한 경로를 먼저 확인해야 합니다.

Project and External Dependencies에서 Jquery와 부트스트랩 라이브러리를 확인합니다.

위의 사진을 보면 알 수 있는데 Jquery라이브러리의 경로는 

'META-INF/resources/webjars/jquery/3.6.0/'인 것을 확인할 수 있습니다.

위의 캡처처럼 'META-INF/resources' 아래의 경로 /webjars/jquery/3.6.0/파일명을 js파일의 경우 <script>의 src속성 값으로 , css파일은 <link>의 href속성 값으로 넣어주면 됩니다.

4. JQuery Ajax 코드 작성

1) CRUD 코드

/**
 * ajax-dev
 */
	var itemApi = "http://localhost:8080/api/items";
	
	$('#search-btn').on("click", function() {
		var itemNo = $("#search").val();
		getItemData(itemNo);
	});
	
	/* Get Item Data*/
	function getItemData(itemNo) {
		//alert(apiUrl+str);
		$.ajax({
			url: itemApi+'/'+itemNo,
			method : 'GET',
			success :  function(item){
				//alert(JSON.stringify(item))
				makeItemView(item);
			},
		    error: function(xhr, textStatus, error){
		      console.log(xhr.statusText);
		      console.log(textStatus);
		      console.log(error);
		    }
		});
	}
	
	function clearItemInfo() {
		$("#item-list").html('<div></div>');
	}
	
	/* Render Item Info */
	function makeItemView(item) {
		var view = '';
		view = view + '<div class="row justify-content-center">';
		view = view + '<div class="col-md-8 order-md-1">';
		view = view + '<h4 class="mb-3">Item Number : '+item.itemId+'</h4>';
		view = view + '	<form class="needs-validation" novalidate>';
		view = view + '		<div class="row col-md-6 mb-3">';
		view = view + '			<label for="itemName">ItemName</label> ';
		view = view + '			<input type="text"class="form-control" id="itemName" value="'+item.itemName+'" readonly>';
		view = view + '		</div>';
		view = view + '		<div class="mb-3">';
		view = view + '			<label for="itemDescription">itemDescription</label>';
		view = view + '			<div class="input-group">';
		view = view + '				<input type="text" class="form-control" id="itemDescription"  value="'+item.itemDescription+'" >';
		view = view + '			</div>';
		view = view + '		</div>';
		view = view + '		<div class="row col-md-6 mb-3">';
		view = view + '			<label for="makerCode">makerCode </label> ';
		view = view + '			<input type="text" class="form-control" id="makerCode"  value="'+item.makerCode+'">';
		view = view + '		</div>';
		view = view + '		<div class="row col-md-6 mb-3">';
		view = view + '			<label for="price">price</label> ';
		view = view + '			<input type="text" class="form-control" id="price" value="'+item.price+'">';
		view = view + '		</div>';
		view = view + '		<div class="mb-3">';
		view = view + '			<label for="saleStatus">saleStatus</label>';
		view = view + '			<div class="input-group">';
		
		var stopChecked = '';
		var startChecked = '';
		if (item.saleStatus === 0) {
			stopChecked = ' checked=checked'
		} else if (item.saleStatus === 1) {
			startChecked = ' checked=checked'
		}
		
		view = view + '				<div class="form-check form-check-inline">';
		view = view + '					<input class="form-check-input" type="radio" name="saleStatus" id="inlineRadio1" value="0" '+stopChecked+'>';
		view = view + '					<label class="form-check-label" for="inlineRadio1">판매정지</label>';
		view = view + '				</div>';
		view = view + '				<div class="form-check form-check-inline">';
		view = view + '					<input class="form-check-input" type="radio" name="saleStatus" id="inlineRadio2" value="1" '+startChecked+'>';
		view = view + '					<label class="form-check-label" for="inlineRadio2">판매중</label>';
		view = view + '				</div>';
		view = view + '			</div>';
		view = view + '		</div>';
		// hidden value
		view = view + '<input type="hidden" id="itemId" name="itemId" value="'+item.itemId+'">';
		view = view + '<input type="hidden" id="old_itemName" name="old_itemName" value="'+item.itemName+'">';
		view = view + '<input type="hidden" id="old_itemDescription" name="old_itemDescription" value="'+item.itemDescription+'">';
		view = view + '<input type="hidden" id="old_makerCode" name="old_makerCode" value="'+item.makerCode+'">';
		view = view + '<input type="hidden" id="old_price" name="old_price" value="'+item.price+'">';
		view = view + '<input type="hidden" id="old_saleStatus" name="old_saleStatus" value="'+item.saleStatus+'">';
		
		view = view + '	</form>';
		view = view + '</div>';
		view = view + '</div>';
		view = view + '<div class="row form-row float-right mx-auto">';
		view = view + '<button class="btn float-left btn-warning mr-3" type="button" id="update-btn">Item Update</button>';
		view = view + '<button class="btn float-right btn-danger mr-3" type="button" id="delete-btn">Item Delete</button>';
		view = view + '<button class="btn float-right btn-primary mr-3" type="button" id="clear-btn">Clear</button>';
		view = view + '</div>';
		
		$("#item-list").html(view);
	}
	
	/* Clear Item Info */
	$(document).on("click", '#clear-btn',function() {
		clearItemInfo();
	});
	
	
	/* Item Create Start*/
	$('#create-form-btn').on("click", function() {
		makeItemFormView();
	});
	
	/* Render Item Create Form */
	function makeItemFormView() {
		var view = '';
		view = view + '<div class="row justify-content-center">';
		view = view + '<div class="col-md-8 order-md-1">';
		view = view + '<h4 class="mb-3">Please Input Item Infomation </h4>';
		view = view + '	<form class="needs-validation" novalidate>';
		view = view + '		<div class="row col-md-6 mb-3">';
		view = view + '			<label for="itemName">ItemName</label> ';
		view = view + '			<input type="text"class="form-control" id="itemName">';
		view = view + '		</div>';
		view = view + '		<div class="mb-3">';
		view = view + '			<label for="itemDescription">itemDescription</label>';
		view = view + '			<div class="input-group">';
		view = view + '				<input type="text" class="form-control" id="itemDescription">';
		view = view + '			</div>';
		view = view + '		</div>';
		view = view + '		<div class="row col-md-6 mb-3">';
		view = view + '			<label for="makerCode">makerCode </label> ';
		view = view + '			<input type="text" class="form-control" id="makerCode">';
		view = view + '		</div>';
		view = view + '		<div class="row col-md-6 mb-3">';
		view = view + '			<label for="price">price</label> ';
		view = view + '			<input type="text" class="form-control" id="price">';
		view = view + '		</div>';
		view = view + '		<div class="mb-3">';
		view = view + '			<label for="saleStatus">saleStatus</label>';
		view = view + '			<div class="input-group">';
		view = view + '				<div class="form-check form-check-inline">';
		view = view + '					<input class="form-check-input" type="radio" name="saleStatus" id="inlineRadio1" value="0" checked=checked>';
		view = view + '					<label class="form-check-label" for="inlineRadio1">판매정지</label>';
		view = view + '				</div>';
		view = view + '				<div class="form-check form-check-inline">';
		view = view + '					<input class="form-check-input" type="radio" name="saleStatus" id="inlineRadio2" value="1">';
		view = view + '					<label class="form-check-label" for="inlineRadio2">판매중</label>';
		view = view + '				</div>';
		view = view + '			</div>';
		view = view + '		</div>';
		view = view + '	</form>';
		view = view + '</div>';
		view = view + '</div>';
		view = view + '<div class="row form-row float-right mx-auto">';
		view = view + '<button class="btn float-left btn-warning mr-3" type="button" id="create-process-btn">Create Item </button>';
		view = view + '<button class="btn float-right btn-danger mr-3" type="button" id="create-cancel-btn">Cancel </button>';
		view = view + '</div>';
		
		$("#item-list").html(view);
	}
	
	$(document).on("click", '#create-process-btn' ,function() {
		var itemName = $("#itemName").val();
		var itemDescription = $("#itemDescription").val();
		var makerCode = $("#makerCode").val();
		var price = $("#price").val();
		var saleStatus = $('input[name="saleStatus"]:checked').val();
		
		var itemObj = {
				"itemName":itemName,
				"itemDescription":itemDescription,
				"makerCode":makerCode,
				"price":price,
				"saleStatus":saleStatus
		};
		
		postItemData(JSON.stringify(itemObj));
	});
	
	/* Post Item Data*/
	function postItemData(newItem) {
		$.ajax({
			url: itemApi,
			method : 'POST',
			contentType : 'application/json; charset=UTF-8',
			data: newItem,
			success :  function(res){
				alert(JSON.stringify(res));
				clearItemInfo();
			},
		    error: function(xhr, textStatus, error){
		      console.log(xhr.statusText);
		      console.log(textStatus);
		      console.log(error);
		      alert(error)
		    }
		});
	}
	
	$(document).on("click", '#create-cancel-btn',function() {
		clearItemInfo();
	});
	
	
	/* Item Update Start*/
	$(document).on("click", '#update-btn' ,function() {
		
		var itemId = $("#itemId").val();
		//var itemName = $("#itemName").val();
		var itemDescription = $("#itemDescription").val();
		var makerCode = $("#makerCode").val();
		var price = $("#price").val();
		var saleStatus = $('input[name="saleStatus"]:checked').val();
		
		// Is it change?
		//var old_itemName = $("#old_itemName").val();
		var old_itemDescription = $("#old_itemName").val();
		var old_makerCode = $("#old_itemName").val();
		var old_price = $("#old_itemName").val();
		var old_saleStatus = $("#old_saleStatus").val(); 
		
		if (itemName === old_itemName && 
			itemDescription === old_itemDescription &&
			makerCode === old_makerCode &&
			price === old_price && 
			saleStatus == old_saleStatus) {
			
			return false;
		}
		
		var itemObj = {
				//"itemName":itemName,
				"itemDescription":itemDescription,
				"makerCode":makerCode,
				"price":price,
				"saleStatus":saleStatus
		};
		
		putItemData(itemId, JSON.stringify(itemObj));
	});
	
	/* PUT Item Data*/
	function putItemData(itemId, updateItem) {
		$.ajax({
			url: itemApi +'/'+itemId,
			method : 'PUT',
			contentType : 'application/json; charset=UTF-8',
			data: updateItem,
			success :  function(res){
				alert("Success Item Info Update "+res.itemId)
				makeItemView(res);
			},
		    error: function(xhr, textStatus, error){
		      console.log(xhr.statusText);
		      console.log(textStatus);
		      console.log(error);
		      alert(error)
		    }
		});
	}
	
	/* Item Delete Start*/
	$(document).on("click", '#delete-btn',function() {
		var itemId = $("#itemId").val();
		var itemName = $("#itemName").val();
		var check = confirm('Do you want to delete Item info : [ '+itemName+' ]')
		
		if (!check) {
			alert('Item Delete Cancel');
		    return
		}
		
		deleteItemData(itemId);
		
	});
	
	
	/* PUT Item Data*/
	function deleteItemData(itemId) {
		$.ajax({
			url: itemApi +'/'+itemId,
			method : 'DELETE',
			success :  function(res){
				alert("Success Item Info Delete "+itemId)
				clearItemInfo();
			},
		    error: function(xhr, textStatus, error){
		      console.log(xhr.statusText);
		      console.log(textStatus);
		      console.log(error);
		      alert(error)
		    }
		});
	}


2) index.jsp에 적용하기

위의 캡처처럼 <script> 태그의 src속성 값으로 Jquery코드의 경로를 기재해주면 됩니다. 


5. 애플리케이션 동작확인

 

 

 

반응형

댓글