230208 Spring myweb 기능구현-등록-목록-상세, 수정, 삭제
등록과 목록
등록
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>