본문 바로가기

JSP&JSTL 수업 정리

JSP/JSTL 3일차.

만들던 board 기능의 수정 / 삭제를 이어서 구현.

 

● board 폴더에 detail.jsp에 수정페이지로 이동하는 버튼과 삭제버튼을 만들고 modify.jsp 수정파일을 생성 modify.jsp는 업데이트 커밋버튼과 list로 이동하는 버튼을 구현.

● 만들어둔 컨트롤러의 detail 부분을 그대로 받아와서 수정페이지로 옮기고 수정페이지에서 업데이트를 거칠 예정이기에 

case detail 부분에 modify를 추가

case "detail": case "modify" :
			try {
				int bno = Integer.parseInt(request.getParameter("bno"));
				BoardVO bvo = bsv.getDetail(bno);
				log.info(">>>> detail bvo >> {}", bvo);
				
				request.setAttribute("bvo", bvo);
				destPage = "/board/"+path+".jsp";
				
			} catch (Exception e) {
				log.info("detail error");
				e.printStackTrace();
			}
			break;

 

modify가 case에 추가됐으므로 응답 jsp에 주소를 저장하는 destPage는 detail.jsp로 가는게아니라 path로 설정해서 modify일때도 이동 할 수 있도록 함.

● 업데이트를 하려면 내가 update 하려는 정보를 form으로 받아올 수 있어야하고 form으로 받아오려면 name이 있어야하기에 업데이트하는데 필요한 보드번호, 타이틀, 상세내용은 input으로 수정가능하게 만들어줌. 여기서 보드번호같은경우는 받아오기위해 name이 필요하지만 수정할것은 아니기에 input hidden을 이용하여 정보만 받아 올 수있도록함.

<input type="hidden" name="bno" value="${bvo.bno }">

 

 

● modify.jsp 를 다구현했으면 form에 action을 업데이트에 전송할 수 있게 해주고 컨트롤러 구현

case "update" :
			try {
				int bno = Integer.parseInt(request.getParameter("bno"));
				String title = request.getParameter("title");
				String content = request.getParameter("content");
				BoardVO bvo = new BoardVO(bno, title, content);
				int isOk = bsv.update(bvo);
				log.info(">>>> update >>> " + (isOk >0 ? "성공" : "실패"));
				// 컨트롤러 내부 케이스는 /brd/ 따로 적을 필요가 없음.
				destPage = "detail?bno="+bno;
				
			} catch (Exception e) {
				log.info("update error");
				e.printStackTrace();
			}
			break;

update를 하면 다시 수정한 상세페이지로 이동할건데 이동 시 컨트롤러의 case detail로 이동하는 것이니 같은 컨트롤러의 움직임에는 /brd/ 를 따로 적지않고 "deatil"만 있으면 되고, 내가 이동할 상세페이지의 번호 bno를 추가해줌.

● 서비스 > 다오 이어서 다 연결하고 mapper 에 실제 쿼리문 구현

@Override
	public int update(BoardVO bvo) {
		log.info(">>>> update DAO in !!");	
		int isOk = sql.update("BoardMapper.up",bvo);
		if(isOk > 0) {
			sql.commit();
		}		
		return isOk;
	}
  <update id="up" parameterType="domain.BoardVO">
  	update board set 
  	title = #{title}, 
  	content=#{content}, 
  	moddate = now()
  	where bno = #{bno} 
  </update>

수정 기능 끝.

 

● 삭제 기능은 보드번호 받아서 컨트롤러에 케이스 delete 구현해주고 서비스 다오 연결하고 mapper에 구문써주면 바로 끝

	case "delete" :
			try {
				int bno = Integer.parseInt(request.getParameter("bno"));
				int isOk = bsv.delete(bno);
				log.info(">>>> delete >>> " + (isOk >0 ? "성공" : "실패"));		
				destPage = "list";
			} catch (Exception e) {
				log.info(">>>> delete error" );
				e.printStackTrace();
			}
			break;
		}
@Override
	public int delete(int bno) {
		log.info(">>>> delete DAO in !!");	
		int isOk = sql.update("BoardMapper.delete",bno);
		if(isOk > 0) {
			sql.commit();
		}	
		return isOk;
	}
  <delete id="delete" parameterType="int">
  	delete from board where bno = #{bno}
  </delete>

 


detail 페이지 아래에 댓글기능 구현

댓글 작업 : 비동기 처리 ( AJAX )

- 동기 방식 : 페이지 자체가 변화하는 방식 ( 페이지의 내용을 새로 구성해서 전송 ) 

- 비동기 방식 : 정보만 변화하는 방식 ( 데이터만 전송하는 방식 )

 

- Js => json 원래 가지고 있는 값

- Java 에서 Json을 객체화 하기위한 라이브러리가 필요

- json-simple-1.1.1

 

댓글 테이블 구성 ( comment )

cno : 댓글 번호 pk ai 

bno : 어떤 게시글의 댓글인지 확인

content : 댓글 내용 varchar(2000)

writer : 작성자 

regdate : 등록일

 

create table comment(
cno int auto_increment,
bno int not null,
content varchar(2000) not null,
writer varchar(500) default "unknown",
regdate datetime default now(),
primary key(cno));


 

● CommentVO 부터 controller, service, dao , mapper 까지 일단 전부 생성.

 

- CommentVO는 DB구조와 동일하게 구현

 

- controller에서는  동기 통신이 아닌 비동기 통신 ( 데이터만 요청한 곳으로 보내는 방식 ) 이므로

ReqeustDispatcher / destPage가 필요 없음.

get ,post  전부 똑같이 서비스에서 처리하도록 설정하고 인코딩처리를 해줌, setContentType은 동기에서만.

 

- mapper를 읽기위해 mapper resource="mapper/commentMapper.xml" 를 mybatis에추가해줘야함

 

● detail.jsp에 댓글 추가하는 공간을 구현 페이지를 넘어가는 동기방식이아닌 비동기 방식으로 사용할 것이기 때문에 추가적인 jsp 파일을 생성 할 필요가없음.

댓글이 추가되면 어떤형식으로 추가될지 샘플을 만들어두고 샘플은 날릴예정.

 

	<!-- comment print line -->

	<div id="commentLine">
		<div>
			<div>cno, bno, writer, regdate</div>
			<div>
				<button>수정</button>
				<button>삭제</button>
				<br> <input type="text" value="content">
			</div>
		</div>
	</div>
	<script type="text/javascript">
		const bnoVal = `<c:out value="${bvo.bno }" />`; 
		console.log(bnoVal);
	</script>
	
	<script type="text/javascript" src="/resources/board_detail.js"></script>

 

  자바스크립트를 사용할 파일을 만들어주고 스크립트 코드안에 넣어서 연결 스크립트 끼리는 변수를 공유 할 수있으므로 사용할 값을 스크립트 코드를 하나 더 열어서 변수에 저장해서 넣어줘서 사용 할 수 있게함.

 

● 스크립트 안에 등록 버튼을 누르면 작성자와 댓글 내용의 값을 객체로 생성해서 서버로 controller에 전송 할 수 있도록 구현 

구현을 위해서 화면에서 데이터를 만들어서 post로 보내는 function이 필요함.  데이터를 보낼때는

데이터를 보낼때 method=post, headers(Content-Type), body 를 작성해서 전송
Content-Type : application/json; charset=utf-8 필요.

async function postCommentToserver(cmtData) {
	try {
		console.log(cmtData);
		const url = "/cmt/post";
		const config = {
			method: 'post',
			headers: {
				'Content-Type': 'application/json; charset=utf-8'
			},
			body: JSON.stringify(cmtData)
		}
		const resp = await fetch(url, config);
		const result = await resp.text(); // isOk 값을 text로 리턴 
		return result;
	} catch (error) {
		console.log(error);
	}
};
document.getElementById('cmtAddBtn').addEventListener('click', () => {
	let cmtText = document.getElementById('cmtText').value;
	let cmtWriter = document.getElementById('cmtWriter').value;

	if (cmtText == null || cmtText == '') {
		alert("댓글을 입력해주세요.");
		return false;
	}
	// 댓글 객체 생성

	let cmtData = {
		bno: bnoVal,
		writer: cmtWriter,
		content: cmtText
	}
	// 댓글을 비동기로 전송	
	postCommentToserver(cmtData).then(result => {
		console.log(result); // isOK
		if (result == '1') {
			alert("댓글등록 성공");
		} else {
			alert("댓글등록 실패")
		}
	})

 

  controller service에서 처리 

- js에서 보낸 데이터를 읽어들이는 작업

		// js('Object' -> controller(String) => CommentVO로 변환
				// {"bno :" , "writer :" , "content :" 
				StringBuffer sb = new StringBuffer();
				String line="";
				BufferedReader br = request.getReader(); // request의 body값을 전송
				while((line = br.readLine()) != null) {
					sb.append(line);
				}
				log.info(">>>> sb > {} " , sb.toString());
// CommentVO 객체로 생성
				JSONParser parser = new JSONParser();
				JSONObject jsonObj = (JSONObject)parser.parse(sb.toString());
				log.info(">>> jsonObj >> {}" , jsonObj);
				// key : value 형태로 jsonObj 구성
				int bno = Integer.parseInt(jsonObj.get("bno").toString());
				String writer = jsonObj.get("writer").toString();
				String content = jsonObj.get("content").toString();

 

- 읽어들인 데이터를 객체에 넣어서 생성

	CommentVO cvo = new CommentVO(bno, content, writer);
				
				int isOk = csv.post(cvo);
				log.info(" >>>> post > {}", (isOk >0 ? "성공" : "실패"));
				
				// 결과 데이터를 전송 => 화면으로 전송 (response 객체의 body에 기록)
				
				PrintWriter out = response.getWriter();
				out.print(isOk);

 

  service DAO mapper를 연결 Mapper 에 쿼리문 작성해서 구현.

	@Override
	public int post(CommentVO cvo) {
		log.info("comment dao post in");
		int isOk = sql.insert("CommentMapper.post",cvo);
		
		if(isOk > 0 ) {
			sql.commit();
		}
		
		return isOk;
	}
  <mapper namespace="CommentMapper">
  
  <insert id="post">
  	insert into comment(bno, writer, content)
  	values(#{bno},#{writer},#{content})
  </insert>

 

댓글 작성 기능 구현 완성.

 

● 댓글 추가를 완성했으니까 추가한 댓글들의 리스트를 출력해서 보여주는 기능을 위해  js에서 list를 가져오는 메서드 구현

async function getCommentListFromServer(bno){
	try{
		const resp = await fetch("/cmt/list?bno="+bno);
		const result = await resp.json(); // 댓글 리스트 [{...},{...}]
		return result; 
		
	} catch (error){
		console.log(error);
	}
};

 

● 버튼을 눌렀을때 출력이가능하도록 추가

	// 댓글 출력
	getCommentListFromServer(bnoVal).then(result => {
		console.log(result);
	})

 

● controller에서 case "list" 일 때 리스트를 보여줄 수 있도록 구현

try catch 안에 

	int bno = Integer.parseInt(request.getParameter("bno"));
				List<CommentVO> list = csv.getList(bno);
				log.info(">>> list > {} " , list);

 

 

bno를 받아와서 list를 가져올 수 있게하고 가져온 list들을 CommentVO 객체의 list에 넣어줌.

service 부터 dao , mapper 구현.

	@Override
	public List<CommentVO> getList(int bno) {
		log.info("comment dao list in");
		
		return sql.selectList("CommentMapper.list", bno);
	}
  <select id="list" resultType="domain.CommentVO">
  	select * from comment where bno = #{bno}
  	order by cno desc
  </select>

 

● 받아온 list를 json 형태로 변환하여 보내기

[{...},{...},{...}] 형태 : [] JSONArray

{...} : JSONObject

 

JSONArray jsonArray = new JSONArray();
JSONObject[] jsonObjArr = new JSONObject[list.size()];

 받아온 list의 사이즈 크기만큼 오브젝트 배열을 만들어주고

add해서 JSONArray에 넣어줄 예정

 

반복문으로 새로운 JSON오브젝트를 만들어서 안에 put 해서 list에서 가져온 정보를 넣고

오브젝트 리스트안에 넣어주고 넣어준 오브젝트 리스트를 JSON 배열에 add해준다.

 

	for (int i = 0; i < list.size(); i++) {
					// jsonObjArr[i] = new JSONObject();
					// jsonObjArr[i].put("cno", list.get(i));

					JSONObject json = new JSONObject();
					json.put("cno", list.get(i).getCno());
					json.put("bno", list.get(i).getBno());
					json.put("writer", list.get(i).getWriter());
					json.put("content", list.get(i).getContent());
					json.put("regdate", list.get(i).getRegdate());

					jsonObjArr[i] = json;

					jsonArray.add(jsonObjArr[i]);
				}

 

제이슨배열의 값을 String으로 변환하여 전송하고 출력해줌.

 '[{...}, {...}, {...}]' => jsonArray의 값을 String으로 변환하여 전송
String jsonData = jsonArray.toJSONString();
				
// print
PrintWriter out = response.getWriter();
out.print(jsonData);

 

이러면 컨트롤러 작성 끝. 

 

이제 자바스크립트 파일에 만들어둔 jsp파일의 샘플 형식에 맞게 출력메서드를 만들어주고 

function printList(bnoVal){
	getCommentListFromServer(bnoVal).then(result => {
			console.log(result);
			if(result.length > 0){				
			printCommentList(result);
			} else{
				let div = document.getElementById('commentLine');
				div.innerHTML = `<div>comment가 없습니다.</div>`;
			}
		});
}

 

	// 댓글을 비동기로 전송	
	postCommentToserver(cmtData).then(result => {
		console.log(result); // isOK
		if (result == '1') {
			alert("댓글등록 성공");
		} else {
			alert("댓글등록 실패")
		}
	})
	// 댓글 출력
	printList(bnoVal)

 

버튼 작동을 하게해주는 스크립트에 출력메서드를 넣어줌.

 

● 디테일 페이지가 열렸을 때도 댓글이 보여지게 해야하므로 detail.jsp 파일에도 스크립트로 출력메서드를 실행시켜줌.

	<!-- 댓글 리스트 호출 -->

	<script type="text/javascript">
		printList(bnoVal);
	</script>

 

이러면 댓글을 작성하고 리스트를 보여줄 수 있음.

 

댓글 수정 / 삭제는 다음.

'JSP&JSTL 수업 정리' 카테고리의 다른 글

JSP/JSTL 5일차.  (0) 2024.10.25
JSP/JSTL 4일차.  (0) 2024.10.24
JSP/JSTL 2일차.  (0) 2024.10.22
JSP/JSTL 1일차.  (0) 2024.10.21