Spring

230208 Spring myweb 기능구현-등록-목록-상세, 수정, 삭제

주영재 2023. 2. 8. 19:42

등록과 목록

 

 

등록

jsp에서는 form의 action-submit과 input태그의 name속성으로 값을 보냄.

 

 

Controller

//글등록
@RequestMapping(value="/registForm", method=RequestMethod.POST)
public String registForm(TripVO vo,RedirectAttributes ra) {
	int result = tripService.noticeRegist(vo);
	String msg=result==1?"문의사항이 정상 등록되었습니다.":"문의 등록에 실패했습니다.";
	ra.addFlashAttribute("msg", msg);
	return "redirect:/trip/notice_list";
}

-form형식의 action으로 넘어올 때, mapper(sql)에서는 insert태그 사용. 반환값은 성공실패 반환하므로 3항연산자와 RedirectAttributes, addFlashAttribute를 통해 1회성 메시지 보내기.

 

 

mapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  
  <mapper namespace="com.cordhistory.myweb.trip.service.TripMapper">
  	<insert id="noticeRegist" parameterType="TripVO">
  		insert into trip(tripdate, writer, title, content) values(#{tripdate}, #{writer}, #{title}, #{content})
  	</insert>

  </mapper>

 


목록

Controller

//목록
@RequestMapping("/notice_list")
public String notice_list(Model model) {
	/*
	 * service, mapper영역에 getList함수를 선언하고
	 * 등록번호 역순으로 데이터를 조회해서 가지고 나옵니다.
	 * model에 담아서
	 * 화면에서는 반복문으로 처리.
	 *  
	 */
	ArrayList<TripVO> list = tripService.getList();
	model.addAttribute("list",list);
	return "trip/notice_list";
}

 

 

mapper.xml

<select id="getList" resultType="TripVO" >
	select * from trip order by tno desc
</select>

 

 

list.jsp

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>    
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>  

<c:forEach var="colList" items="${list}" varStatus="num">
	<tr>
		<td>${num.count}</td>
		<td class="tit_notice"><a href="notice_view?tno=${colList.tno}">${colList.title}</a></td>
		<td>${colList.hit}</td>
		<td><fmt:formatDate value="${colList.regdate}" pattern="yyyy-MM-dd"/></td>
	</tr>
</c:forEach>

-로, 반복해서 화면 그리고, ${num.count}로 글번호 출력. tno는 pk다. 화면에서 보이지 않아야 함.

-formatDate 형식변환
-parseDate 형변환


상세

Controller

//상세페이지
@RequestMapping("/notice_view")
public String notice_view(@RequestParam("tno")int tno, Model model) {
	//클릭한 글 번호에 대한 내용을 조회
	TripVO vo = tripService.getContent(tno);
	model.addAttribute("vo",vo);
	
	//조회수-Cookie or 세션 이용해서 조회수 중복 방지
	tripService.hitUpdate(tno); //조회수 업데이트
	
	//이전글, 다음글
	ArrayList<TripVO> list = tripService.getPrevNext(tno);
	model.addAttribute("list", list);
	
	return "trip/notice_view";
}

 

-@RequestParam을 이용해서 필수로 받아오도록. list에서 상세페이지인 뷰페이지로 올 때 값이 없으면 상세페이지를 볼 수 없도록.

 

 

mapper.xml

상세페이지에선 db의 한 행만 필요하다.

<select id="getContent" resultType="TripVO">
	select * from trip where tno=#{tno}
</select>

 

조회수 업데이트

<update id="hitUpdate" parameterType="int">
	update trip set hit=hit+1 where tno=#{tno}
</update>

hit=hit+1에서 변화하는 값이 없다. 단순히 조회수에 1만 추가해주면 된다.

조회수 증가를 막으려면 컨트롤러에서 쿠키나 세션을 이용.

 

 

view.jsp에서

<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>

<ul class="bbsview_list">
	<li class="bbs_title">${vo.title}</li>
	<li class="bbs_hit">조회수 : ${vo.hit }</li>
	<li class="bbs_date">작성일 : <span><fmt:formatDate value="${vo.regdate}" pattern="yyyy-MM-dd" /></span></li>
	<li class="bbs_hit">작성자 : <span>${vo.writer }</span></li>
	<li class="bbs_content">
		<div class="editer_content">${vo.content }</div>
	</li>
</ul>

로, model에서 넘긴 값을 그린다.

 

 

조회수 업데이트 쿠키로 제한하기

//상세페이지
	@RequestMapping("/notice_view")
	public String notice_view(@RequestParam("tno")int tno, Model model,HttpServletResponse response, HttpServletRequest request) {
		
		//조회수-Cookie or 세션 이용해서 조회수 중복 방지
		Cookie[] cookies=request.getCookies();
		int countCookie=0;
			for(Cookie c : cookies) {
				if(c.getName().equals(Integer.toString(tno))) {
					countCookie++;
				}
			}
			if(countCookie==0) {
				Cookie cookie = new Cookie(Integer.toString(tno),Integer.toString(tno));
				cookie.setMaxAge(30);
				response.addCookie(cookie);
				tripService.hitUpdate(tno); //조회수 업데이트
			}
		
        
			//클릭한 글 번호에 대한 내용을 조회
			TripVO vo = tripService.getContent(tno);
			model.addAttribute("vo",vo);

		//이전글, 다음글
		ArrayList<TripVO> list = tripService.getPrevNext(tno);
		model.addAttribute("list", list);
		
		return "trip/notice_view";
	}

수정

view.jsp에서

<a href="notice_modify?tno=${vo.tno}" class="btn_bbs">글수정</a>

로 sql문에서 사용할 tno를 보낸다.

 

Controller

//수정화면
@RequestMapping("/notice_modify")
public String notice_modify(@RequestParam("tno")int tno,Model model) {
	TripVO vo = tripService.getContent(tno);
	model.addAttribute("vo",vo);
	return "trip/notice_modify";
}

으로, 글 수정의 a태그를 통해 받은 값으로 sql에서 한 행의 값들을 꺼냄. 마찬가지로 값이 없으면 수정하기 화면이 보이지 않아야 하니까 @RequestParam을 사용.

어차피 필요한 sql문은 상세페이지를 그리는 sql문과 같다. 

 

수정화면

modify.jsp에서

<form action="modifyForm" method="post" class="appForm">
	<fieldset>
		<legend>상담문의 수정양식</legend>
		<p class="info_pilsoo pilsoo_item">필수입력</p>
		<ul class="app_list">
			<li class="clear">
				<label for="email_lbl" class="tit_lbl pilsoo_item">등록일 (수정 일자)</label>
				<div class="app_content email_area">
					<!-- required, pattern속성을 사용할 떄는 form태그를 반드시 submit버튼으로 전송해야 동작됩니다. -->
					<input type="text" name="tripdate" value="${vo.tripdate }" id="datepicker_a" placeholder="날짜를 선택하세요" required="required" pattern="[0-9]{4}-[0-9]{2}-[0-9]{2}" >
				</div>
			</li>
			<li class="clear">
				<label for="email_lbl" class="tit_lbl pilsoo_item">작성자 (수정 불가)</label>
				<div class="app_content email_area">
					<input type="hidden" name="tno" value="${vo.tno }" />
					<input type="text" name="writer" value="${vo.writer }" readonly="readonly"/>
				</div>
			</li>
			<li class="clear">
				<label for="name_lbl" class="tit_lbl pilsoo_item">제목</label>
				<div class="app_content">
					<input type="text" name="title" class="w100p" id="name_lbl" placeholder="${vo.title }" required="required"/>
				</div>
			</li>
			<li class="clear">
				<label for="content_lbl" class="tit_lbl">문의내용</label>
				<div class="app_content">
					<textarea name="content" id="content_lbl" class="w100p" placeholder="${vo.content }"></textarea>
				</div>
			</li>
		</ul>
		<p class="btn_line">
			<input type="submit" class="btn_baseColor" value="글 수정">
			<input type="button" class="btn_baseColor" value="목록" onclick="location.href='notice_list'">
		</p>	
	</fieldset>
</form>

-수정 후 값을 넘기기 위해 form태그와 name, submit을 사용한다.

-action의 modifyForm은 controller에서

//수정하기
@RequestMapping(value="/modifyForm", method=RequestMethod.POST)
public String modifyForm(TripVO vo, RedirectAttributes ra) {
	
	//업데이트작업-화면에서는 tno가 필요하기 때문에 hidden태그를 이용해서 넘겨준다.		
	int result=tripService.noticeModify(vo);
	String msg=result==1?"문의사항이 수정되었습니다.":"수정에 실패했습니다.";
	ra.addFlashAttribute("msg",msg);
	return "redirect:/trip/notice_view?tno="+vo.getTno();
}

이다. 받은 값들을 통해 mapper.xml에서

<update id="noticeModify" parameterType="TripVO">
	update trip 
	set tripdate=#{tripdate},
	title=#{title},
	content=#{content}
	where tno=#{tno}
</update>

로 수정한다. update-set이므로 지정한것들만 수정되고, 나머지는 이전 내용 그대로이다.

 

-수정에서, 수정한 뒤 화면에 필요한 값을 넘겨야 하기 때문 hidden태그를 이용해서 넘겨준다. 

-수정해서 상세페이지로 갈 때, 상세페이지는 tno가 필요하다. return에 get방식으로 넘겨준다.

 

 

 

+)

만약 수정과 상세화면이 완전 동일하다면 컨트롤러에서 void형식으로

//수정, 상세 화면이 완전 동일하다면
	@RequestMapping({"notice_view", "notice_modify"}) //배열임
	public void notice_view(@RequestParam("tno")int tno, Model model) {
		TripVO vo = tripService.getContent(tno);
		model.addAttribute("vo",vo);
	}

가 가능하다.


삭제


삭제시, 삭제는 get방식으로 보내면 안된다. url을 쳐서 삭제해버릴 수 있기 때문!
JS로 제어.
+)<a href="javascript:;" ->자바스크립트 문법을 쓸 수 있다는 뜻

onclick="이벤트"를 넣고,
아래 script태그 안에서 함수 만들기.
단, a태그므로 바로 화면이 넘어가버린다. 따라서 a태그의 기본적인 기능을 삭제해야 한다.
이후 form으로 내용을 감싼다. hidden을 이용해서 삭제에 필요한 키값을 전달하고 js를 이용해서 form을 전송.

 

view.jsp에서

	<!-- bodytext_area -->
	<!-- 삭제시는 post로 동작하는데
	hidden이용해서 삭제에 필요한 키값을 전달해줍니다.
	js를 이용해서 form을 전송 -->
	<form action="deleteForm" method="post" name="actionForm">
	<input type="hidden" name="tno" value="${vo.tno }"/>
	<div class="bodytext_area box_inner">
		<ul class="bbsview_list">
			<li class="bbs_title">${vo.title}</li>
			<li class="bbs_hit">조회수 : ${vo.hit }</li>
			<li class="bbs_date">작성일 : <span><fmt:formatDate value="${vo.regdate}" pattern="yyyy-MM-dd" /></span></li>
			<li class="bbs_hit">작성자 : <span>${vo.writer }</span></li>
			<li class="bbs_content">
				<div class="editer_content">${vo.content }</div>
			</li>
		</ul>
		<p class="btn_line txt_right">
			<a href="notice_modify?tno=${vo.tno}" class="btn_bbs">글수정</a>
			<a href="javascript:;" class="btn_bbs" onclick="noticeDelete()">글삭제</a>
			<a href="notice_list" class="btn_bbs">목록</a>
		</p>

로, 보낼 값들을 form태그로 감싼다. 

 

삭제 a태그 제어

<script>
	//a링크 고유이벤트 중지
	function noticeDelete(){
		event.preventDefault();
		
		if(confirm("삭제하시겠습니까?")){
			//폼형식으로 삭제 -document.form이름
			document.actionForm.submit();
		}
	}
	
</script>

a링크의 기본값을 event객체를 이용해 중지시키고, confirm을 이용해 확인을 누르면 

form태그라서 가능한 document.form이름.submit()함수로 이동.

 

Controller

	//글삭제
	@RequestMapping(value="/deleteForm", method=RequestMethod.POST)
	public String deleteForm(@RequestParam("tno")int tno, RedirectAttributes ra) {
		/*
		 * service, mapper에는 noticeDelete 메서드로 삭제를 진행
		 * 삭제 이후에는 list화면으로 이동해주면 됩니다.
		 */
		int result=tripService.noticeDelete(tno);
		String msg=result==1?"삭제되었습니다.":"삭제에 실패하였습니다.";
		ra.addFlashAttribute("msg", msg);
		return "redirect:/trip/notice_list";
	}

 

mapper.xml

<delete id="noticeDelete" parameterType="int">
 	delete from trip where tno=#{tno}
 </delete>