[Spring][쇼핑몰 프로젝트] 17. 작가 수정 페이지 구현

YB·2023년 2월 16일
0

쇼핑몰

목록 보기
25/40

목표

작가 '수정 페이지(authorModify.jsp)'를 구현합니다. 또 서버단에서 작가 정보 수정 기능을 구현합니다.

1. 수정 페이지 이동 메서드(AdminController.java)

수정 페이지도 동일하게 작가 한 명의 데이터 즉, test_author테이블의 하나의 행 데이터를 가져와야 합니다. 일일이 Mapper, Service, Controller메서드를 작성하지 않고 기존 '작가 상세 페이지'의 url매핑 메서드인 authorGetInfoGET()을 활용하겠습니다.

@GetMapping과 @PostMapping등은 URL을 배열로 처리할 수 있습니다. 기존의 @GetMapping코드를 아래와 같이 수정합니다.

// 수정 전
@GetMapping("/authorDetail")

// 수정 후
@GetMapping({"/authorDetail", "/authorModify"})

2. View처리(authorModify.jsp)

views/admin 경로와 resources/css/admin경로에 'authorModify.jsp', 'authorModify.css' 파일을 각각 생성합니다.

먼저 작가 정보를 출력하고 저장하는 <input>태그 전체를 <form>태그로 감싸고 해당 <form>태그는 작가 정보 수정을 처리하는 메서드에 데이터를 전달하기 위한 용도로 작성하였습니다.

사용자가 수정할 수 있는 데이터는 작가 이름(authorName), 작가 국가(nationId), 작가 소개(authorIntro)입니다. 따라서 해당 <input>, <textarea>, <option>태그에 "readonly"속성과 "disabled"속성을 지우고 class속성 또한 지워줍니다.

Criteria(pageNum, amount, keyword) 데이터를 저장하고 있는 기존의 <form>태그를 그대로 남겨두었습니다. 왜냐하면 '작가 수정 페이지(authorModify.jsp)'에서 다시 '작가 상세 페이지(authorDetail.jsp)'로 이동할 수 있도록 설계하였는데 '작가 상세 페이지'에서 만약 다시 '작가 관리 페이지(authorManage.jsp)'로 이동을 할 경우 Criteria데이터가 필요로 하기 때문입니다.

작가 이름, 작가 소개 <div>태그 내부에 <span>태그와 경고 문구를 추가하였습니다. 이는 수정 버튼을 눌러 서버에 수정 요청을 하기 전 빈 데이터를 전송하지 않기 위해서 유효성 체크를 할 때 빈 데이터일 경우 경고 문구를 띄우기 위한 용도입니다.

authorModify.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>    
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="../resources/css/admin/authorModify.css">

<script
  src="https://code.jquery.com/jquery-3.4.1.js"
  integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU="
  crossorigin="anonymous"></script>
</head>
<body>
				<%@include file="../includes/admin/header.jsp" %>
                <div class="admin_content_wrap">
                    <div class="admin_content_subject"><span>작가 상세</span></div>
                    <div class="admin_content_main">
                    	<form id="modifyForm" action="/admin/authorModify" method="post">
	                   		<div class="form_section">
	                   			<div class="form_section_title">
	                   				<label>작가 번호</label>
	                   			</div>
	                   			<div class="form_section_content">
	                   				<input class="input_block" name="authorId" readonly="readonly" value="<c:out value='${authorInfo.authorId }'></c:out>">
	                   			</div>
	                   		</div>                    
	                   		<div class="form_section">
	                   			<div class="form_section_title">
	                   				<label>작가 이름</label>
	                   			</div>
	                   			<div class="form_section_content">
	                   				<input name="authorName" value="<c:out value='${authorInfo.authorName }'></c:out>" >
	                   				<span id="warn_authorName">작가 이름을 입력 해주세요.</span>
	                   			</div>
	                   		</div>
	                   		<div class="form_section">
	                   			<div class="form_section_title">
	                   				<label>소속 국가</label>
	                   			</div>
	                   			<div class="form_section_content">
	                   				<select name="nationId" >
	                   					<option value="none" disabled="disabled">=== 선택 ===</option>
	                   					<option value="01" <c:out value=" ${authorInfo.nationId eq '01' ?'selected':''}"/>>국내</option>
	                   					<option value="02" <c:out value=" ${authorInfo.nationId eq '02' ?'selected':''}"/>>국외</option>
	                   				</select>
	                   			</div>
	                   		</div>
	                   		<div class="form_section">
	                   			<div class="form_section_title">
	                   				<label>작가소개</label>
	                   			</div>
	                   			<div class="form_section_content">
	                   				<textarea name="authorIntro" ><c:out value='${authorInfo.authorIntro }'/></textarea>
	                   				<span id="warn_authorIntro">작가 소개를 입력 해주세요.</span>
	                   			</div>
	                   		</div>
	                   		<div class="form_section">
	                   			<div class="form_section_title">
	                   				<label>등록 날짜</label>
	                   			</div>
	                   			<div class="form_section_content">
	                   				<input class="input_block" type="text" readonly="readonly" value="<fmt:formatDate value="${authorInfo.regDate}" pattern="yyyy-MM-dd"/>">
	                   			</div>
	                   		</div>
	                   		<div class="form_section">
	                   			<div class="form_section_title">
	                   				<label>수정 날짜</label>
	                   			</div>
	                   			<div class="form_section_content">
	                   				<input class="input_block" type="text" readonly="readonly" value="<fmt:formatDate value="${authorInfo.updateDate}" pattern="yyyy-MM-dd"/>">
	                   			</div>
	                   		</div>
	                 		<div class="btn_section">
	                   			<button id="cancelBtn" class="btn">취소</button>
		                    	<button id="modifyBtn" class="btn modify_btn">수 정</button>
		                    </div> 
	                    </form>
                    </div>                    
                </div>
                
                <form id="moveForm" method="get">
                	<input type="hidden" name="authorId" value='<c:out value="${authorInfo.authorId }"/>'>
                	<input type="hidden" name="pageNum" value='<c:out value="${cri.pageNum }"/>'>
                	<input type="hidden" name="amount" value='<c:out value="${cri.amount }"/>' >
                	<input type="hidden" name="keyword" value='<c:out value="${cri.keyword }"/>'>
                </form>
				<%@include file="../includes/admin/footer.jsp" %>


</body>
</html>

authorModify.css

@charset "UTF-8";
*{
	margin: 0;
	padding:0;
}
a{
	text-decoration: none;
}
a:link {color: black;}
a:visited {color: black;}
a:active {color: black;}
a:hover {color: black;}
ul{
    list-style: none;
}
/* 화면 전체 렙 */
.wrapper{
	width: 100%;
}
/* content 랩 */
.wrap{
	width : 1080px;
	margin: auto;
}
/* 홈페이지 기능 네비 */ 
.top_gnb_area{
	width: 100%;
    height: 50px;
    background-color: #f0f0f1;
    position:relative;
}
.top_gnb_area .list{
	position: absolute;
    top: 0px;
    right: 0;
    
}
.top_gnb_area .list li{
	list-style: none;	
    float : left;
    padding: 13px 15px 0 10px;
    font-weight: 900;
    cursor: pointer;
}

/* 관리제 페이지 상단 현페이지 정보 */
.admin_top_wrap{
    height:110px;
    line-height: 110px;
    background-color: #5080bd;
    margin-bottom: 15px;
}
.admin_top_wrap>span{
    margin-left: 30px;
    display:inline-block;
    color: white;
    font-size: 50px;
    font-weight: bolder;
}
/* 관리자 wrap(네비+컨텐츠) */
.admin_wrap{
    
    
}

/* 관리자페이지 네비 영역 */
.admin_navi_wrap{
    width: 20%;
    height: 300px;
    float:left;
    height: 100%;
}
.admin_navi_wrap li{
    display: block;
    height: 80px;
    line-height: 80px;
    text-align: center;
}
.admin_navi_wrap li a{
    display: block;
    height: 100%;
    width: 95%;
    margin: 0 auto;
    cursor: pointer;
    font-size: 30px;
    font-weight: bolder;
}
 
.admin_list_04{
    background-color: #c8c8c8;
} 



/* 관리자페이지 컨텐츠 영역 */
.admin_content_wrap{
    width: 80%;
    float:left;
    min-height:700px;
}
/* 관리자 컨텐츠 제목 영역 */
.admin_content_subject{	
    font-size: 40px;
    font-weight: bolder;
    padding-left: 15px;
    background-color: #6AAFE6;
    height: 80px;
    line-height: 80px;
    color: white;	
}
/* 관리자 컨텐츠 메인 영역 */
.form_section{
	width: 95%;
    margin-left: 2%;
    margin-top: 20px;
    border: 1px solid #dbdde2;
    background-color: #efefef;	
}
.form_section_title{
	padding: 20px 35px;	
}
.form_section_title label{
	display: block;
    font-size: 20px;
    font-weight: 800;
}
.form_section_content{
	padding: 20px 35px;
    border-top: 1px solid #dbdde2;	
}
.form_section_content input{
	width: 98%;
    height: 25px;
    font-size: 20px;
    padding: 5px 1%;
}
.form_section_content textarea{
    width: 98%;
    height: 170px;
    font-size: 20px;	
}
.form_section_content select{
	width: 98%;
    height: 35px;
    font-size: 20px;
    text-align-last: center;
}
.input_block{
	background-color:#f9f9f9;	
}

/* 입력란 공란 경고 태그 */
.form_section_content span{	
	display: none;
    padding-top: 10px;
    text-align: center;
    color: #e05757;
    font-weight: 300;    
}



/* 버튼 영역 */
.btn_section{
	text-align: center;
	margin: 80px 0;
}
.btn{
    min-width: 180px;
    padding: 4px 30px;
    font-size: 25px;
    font-weight: 600;
    line-height: 40px;
}
.modify_btn{
	background-color: #b8d3e8;
	margin-left:15px;
}




/* footer navai 영역 */
.footer_nav{
	width:100%;
	height:50px;
}
.footer_nav_container{
	width: 100%;
	height: 100%;
	background-color:#8EC0E4;
}
.footer_nav_container>ul{
	font-weight : bold;
	float:left;
	list-style:none;
	position:relative;
	padding-top:10px;
	line-height: 27px;
	font-family: dotum;
	margin-left: 10px;
}
.footer_nav_container>ul>li{
	display:inline;
	width: 45px;
	height: 19px;
	padding: 10px 9px 0 10px;
}
.footer_nav_container>ul>span{
	margin: 0 4px;
}
/* footer 영역 */
.footer{
	width:100%;
	height:130px;
	background-color:#D4DFE6;
	padding-bottom : 50px;
}
.footer_container{
	width: 100%;
	height: 100%;
	margin: auto;
}
.footer_left>img {
	width: 150%;
    height: 130px;
    margin-left: -20px;
    margin-top: -12px;
}
.footer_left{
	float :left;
	width: 170px;
	margin-left: 20px;
	margin-top : 30px;
	
}
.footer_right{
	float :left;
	width: 680px;
	margin-left: 70px;
	margin-top : 30px;
}



/* float 속성 해제 */
.clearfix{
	clear: both;
}

js코드 추가
작성한 두개의 버튼이 동작하도록 페이지 하단에 <script>태그를 작성하여 태그 내부에 아래의 코드를 추가하였습니다.

작가 정보 수정 버튼의 경우는 먼저 nameCk와 introCk변수를 선언하여 기본적으로 false값으로 초기화를 합니다. 그리고 작가 이름, 작가 소개 <input>태그가 공란이 아닌지 if문을 통해 체크하여 공란일 경우 Ck값을 false를 대입 및 <span>태그 노출시키고 공란이 아닐 경우 Ck값을 true로 대입 및 <span>태그를 숨깁니다. 마지막 최종적으로 Ck값이 모드 true일 때 작가 정보 데이터가 담긴 <form>이 서버에 전송되도록 하였습니다.

<script>

let moveForm = $("#moveForm");
let modifyForm = $("#modifyForm");

/* 작가 상세 페이지 이동 버튼 */
$("#cancelBtn").on("click", function(e){
	
	e.preventDefault();
			
	moveForm.attr("action", "/admin/authorDetail")
	moveForm.submit();
	
});

/* 작가 수정 버튼 작동 및 유효성 검사 */
$("#modifyBtn").on("click", function(e){

	let authorName = $(".form_section_content input[name='authorName']").val();
	let authorIntro = $(".form_section_content textarea").val();		

	let	nameCk = false;
	let introCk = false;		
	
	e.preventDefault();
	
	if(!authorName){
		$("#warn_authorName").css("display", "block");
	} else {
		$("#warn_authorName").css("display", "none");
		nameCk = true;
	}
	if(!authorIntro){
		$("#warn_authorIntro").css("display", "block");
	} else {
		$("#warn_authorIntro").css("display", "none");
		introCk = true;
	}

	
	if(nameCk && introCk ){
		modifyForm.submit();	
	} else {
		return false;
	}
	
	
});

</script>

3. Mapper, Service 메서드

1) AuthorMapper.java 인터페이스

작가 정보 수정 쿼리를 실행할 메서드를 선언하였습니다. 수정될 데이터를 전달 받기 위해서 파라미터로 AuthorVO를 부여하였습니다. 반환타입을 int로 하게되면 수정에 성공했을 때 1을 반환, 수정에 실패했을 때 0을 반환합니다.

    /* 작가 정보 수정 */
    public int authorModify(AuthorVO author);

2) AuthorMapper.xml

인터페이스에서 선언한 메서드가 실행할 쿼리를 작성합니다. authorId를 조건문으로하여 authorName, nationId, authorIntro데이터를 수정하는 쿼리문을 작성합니다.

더불어 updateDate가 현재의 시간으로 수정되도록 하였습니다.

    <!-- 작가 정보 수정 -->
    <update id="authorModify">
    	update test_author set authorName=#{authorName}, nationId=#{nationId}, authorIntro=#{authorIntro}, updatedate=now() where authorId = #{authorId}
    </update>

3) AuthorService.java 인터페이스

작가 정보 수정 쿼리를 실행하는 Mapper메서드를 호출하는 메서드를 선언합니다.

	/* 작가 정보 수정 */
	public int authorModify(AuthorVO author) throws Exception;

4) AuthorServiceImpl.java

인터페이스에서 선언한 메서드를 오버라이딩하여 구현부를 작성합니다. 메서드가 int형을 반환해야하기 때문에 return에서 mapper메서드를 호출합니다.

	/* 작가 정보 수정 */
	@Override
	public int authorModify(AuthorVO author) throws Exception {
		
		log.info("(service)authorModify..........." + author);
		
		return authorMapper.authorModify(author);
	}

4. Controller 작업(AdminController.java)

작가 정보 수정 요청을 처리할 URL매핑 메서드를 작성합니다.

  • 뷰에서 전달받은 데이터를 전달받기위해 AuthorVO를 파라미터로 부여하였습니다. 추가로 작가 정보 수정 후 '작가 관리 페이지(authorManage.jsp)'로 이동할 때 수정 성공여부를 알리기 위해 데이터를 전송하기 위해서 RedirectAttributes를 파라미터로 부여하였습니다.
  • service의 authorModify()메서드를 호출하여 반환 받은 결과값을 int타입인 result변수에 저장하였습니다.
  • 수정 성공 결과인 result변수 값을 addFlashAttribute()를 활용하여 "modify_result"속성명에 저장합니다.
  • 리다이렉트 방식으로 '작가 관리 페이지(authorManage.jsp)'로 이동할 수 있도록 return값을 작성하였습니다.
	/* 작가 정보 수정 */
	@PostMapping("/authorModify")
	public String authorModify(AuthorVO author, RedirectAttributes rttr) throws Exception {
		
		logger.info("authorModifyPOST........." + author);
		
		int result = authorService.authorModify(author);
		
		rttr.addFlashAttribute("modify_result", result);
		
		return "redirect:/admin/authorManage";
	}

5. 결과창 구현(authorManage.jsp)

서버로부터 전달받은 "modify_result"속성에 저장된 값에 따라 출력되는 결과 창을 구현합니다.
$(document).ready(function(){}) 메서드 내부에 아래의 코드를 추가합니다.

	let mresult = '<c:out value="${modify_result}"/>';
	
	checkmResult(mresult);
	
	function checkmResult(mresult){
		
		if(mresult === '1'){
			alert("작가 정보 수정을 완료하였습니다.");
		} else if(mresult === '0') {
			alert("작가 정부 수정을 하지 못하였습니다.")	
		}
		
	}

6. 테스트

- 수정 테스트


profile
개인이 공부한걸 작성하는 블로그입니다..

0개의 댓글