게시판 다루기
★ 결과
■ 게시판 자세히보기
■ 게시판 생성하기
■ 게시판 수정하기
■ 게시판 삭제하기
★ 사전설정
- 개발환경: 'pom.xml' → spring framework 버전 - 5.3.19
2022.08.02 - [백엔드 보고/스프링 (Spring)] - 프로젝트 개발 기준
프로젝트 개발 기준
앞으로 올리는 보물들은 아래 기준으로 업데이트 할 예정입니다. 참고해주세용!! * Windows 10 Pro (64Bit 운영체제) * 전자정부 프레임워크 (링크: https://www.egovframe.go.kr/) - 표준프레임워크 개발자 교.
bogoitsaw.tistory.com
- My-SQL 셋팅: mysql 프로그램이 활성화되어있는 상태. (참고자료)
2022.08.04 - [백엔드 보고/My SQL (DB)] - My-SQL 셋팅
My-SQL 셋팅
처음 설치한다 가정하구, 접속하는것부터 시작해볼게용!~ ★ 사전설정 2022.08.02 - [백엔드 보고/스프링 (Spring)] - 프로젝트 개발 기준 프로젝트 개발 기준 앞으로 올리는 보물들은 아래 기준으로
bogoitsaw.tistory.com
- Spring과 DB연동 상태
◆ 셋팅되어있어야 하는 파일들 (아래 xml파일들은 'Spring과 DB연동' 포스팅 내용처럼 그대로 따라하시면됩니다.)
-> pom.xml , web.xml, root-context.xml, servlet-context.xml
◆ Controller, Domain, Mapper, Service 형태도 'Spring과 DB연동' 포스팅 그대로 따라해주세요. 내용만 바꿀겁니다.
2022.08.05 - [백엔드 보고/My SQL (DB)] - Spring과 DB 연동
Spring과 DB 연동
★ 결과 실제 서비스에서 많이 쓰는 쿼리문들로 구성해놓은 틀을 공개합니다! ^.^// My-sql과 연동 및 유지보수를 위해 'Hikari-CP', 'MyBatis', Lombok'을 이용하였습니다. ★ 사전설정 개발환경: 'pom.xml..
bogoitsaw.tistory.com
★ DB 생성
■ Database 명: test
■ 생성쿼리문
CREATE TABLE TestBoard
(
`b_seq` INT NOT NULL AUTO_INCREMENT COMMENT '게시판 번호',
`b_title` VARCHAR(150) NULL COMMENT '게시판 제목',
`b_writer` VARCHAR(150) NULL COMMENT '게시판 작성자',
`b_content` MEDIUMTEXT NULL COMMENT '게시판 내용',
`b_regdate` DATETIME NULL DEFAULT CURRENT_TIMESTAMP COMMENT '게시판 등록날짜',
`b_img` VARCHAR(200) NULL COMMENT '게시판 대표그림',
PRIMARY KEY (b_seq)
);
※ 참고로, b_regdate 오른쪽에 'DEFAULT CURRENT_TIMESTAMP'의미는 insert한 당시의 그 날짜와 시간을 넣어달라는 의미입니다. 그래서 b_regdate를 넣지않고 insert하게되면, insert한 그 순간의 날짜와 시간을 b_regdate컬럼의 데이터에 넣게 됩니다.
- b_img는 이 포스팅에서 다루지않지만, 나중에 넣어주려구, 미리 만들어두었습니다.
■ 테스트데이터 쿼리문
INSERT INTO TestBoard (b_title, b_writer, b_content, b_regdate, b_img) VALUES ('b_title 01', 'b_writer 01', 'b_content 01', NOW(), 'b_img 01');
INSERT INTO TestBoard (b_title, b_writer, b_content, b_regdate, b_img) VALUES ('b_title 02', 'b_writer 02', 'b_content 02', NOW(), 'b_img 02');
INSERT INTO TestBoard (b_title, b_writer, b_content, b_regdate, b_img) VALUES ('b_title 03', 'b_writer 03', 'b_content 03', NOW(), 'b_img 03');
INSERT INTO TestBoard (b_title, b_writer, b_content, b_regdate, b_img) VALUES ('b_title 04', 'b_writer 04', 'b_content 04', NOW(), 'b_img 04');
INSERT INTO TestBoard (b_title, b_writer, b_content, b_regdate, b_img) VALUES ('b_title 05', 'b_writer 05', 'b_content 05', NOW(), 'b_img 05');
INSERT INTO TestBoard (b_title, b_writer, b_content, b_regdate, b_img) VALUES ('b_title 06', 'b_writer 06', 'b_content 06', NOW(), 'b_img 06');
INSERT INTO TestBoard (b_title, b_writer, b_content, b_regdate, b_img) VALUES ('b_title 07', 'b_writer 07', 'b_content 07', NOW(), 'b_img 07');
INSERT INTO TestBoard (b_title, b_writer, b_content, b_regdate, b_img) VALUES ('b_title 08', 'b_writer 08', 'b_content 08', NOW(), 'b_img 08');
INSERT INTO TestBoard (b_title, b_writer, b_content, b_regdate, b_img) VALUES ('b_title 09', 'b_writer 09', 'b_content 09', NOW(), 'b_img 09');
INSERT INTO TestBoard (b_title, b_writer, b_content, b_regdate, b_img) VALUES ('b_title 10', 'b_writer 10', 'b_content 10', NOW(), 'b_img 10');
INSERT INTO TestBoard (b_title, b_writer, b_content, b_regdate, b_img) VALUES ('b_title 11', 'b_writer 11', 'b_content 11', NOW(), 'b_img 11');
INSERT INTO TestBoard (b_title, b_writer, b_content, b_regdate, b_img) VALUES ('b_title 12', 'b_writer 12', 'b_content 12', NOW(), 'b_img 12');
★ 틀
■ Domain / Testboard.java
package com.test.Domain;
import lombok.Data;
@Data
public class Testboard {
private int b_seq;
private String b_title;
private String b_writer;
private String b_content;
private String b_regdate;
private String b_img;
}
■ Mapper / TestMapper.java
package com.test.Mapper;
import java.util.List;
import com.test.Domain.Testboard;
public interface TestMapper {
/*boardTest*/
public List<Testboard> selectAllBoard();
public void insertBoard(Testboard tb);
public Testboard selectSeqBoard(int b_seq);
public void updateBoard(Testboard tb);
public void deleteBoard(int b_seq);
}
■ Mapper / TestMapper.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.test.Mapper.TestMapper">
<!-- boardTest부분 -->
<select id = "selectAllBoard" resultType = "com.test.Domain.Testboard">
SELECT * FROM testboard
</select>
<insert id = "insertBoard" parameterType = "com.test.Domain.Testboard">
INSERT INTO testboard (b_title, b_writer, b_content, b_img) VALUES(#{b_title},#{b_writer},#{b_content}, #{b_img})
</insert>
<select id = "selectSeqBoard" parameterType = "int" resultType = "com.test.Domain.Testboard">
SELECT * FROM testboard WHERE b_seq = #{b_seq}
</select>
<update id = "updateBoard" parameterType = "com.test.Domain.Testboard">
UPDATE testboard SET b_title = #{b_title}, b_content = #{b_content}, b_img = #{b_img} WHERE b_seq = #{b_seq}
</update>
<delete id = "deleteBoard" parameterType = "int">
DELETE FROM testboard WHERE b_seq = #{b_seq}
</delete>
</mapper>
■ Service / TestService.java
package com.test.Service;
import java.util.List;
import javax.inject.Inject;
import org.springframework.stereotype.Service;
import com.test.Domain.Testboard;
import com.test.Mapper.TestMapper;
@Service
public class TestService {
@Inject
private TestMapper mapper;
/*boardTest*/
public List<Testboard> selectAllBoard(){
return mapper.selectAllBoard();
}
public void insertBoard(Testboard tb) {
mapper.insertBoard(tb);
}
public Testboard selectSeqBoard(int b_seq) {
return mapper.selectSeqBoard(b_seq);
}
public void updateBoard(Testboard tb) {
mapper.updateBoard(tb);
}
public void deleteBoard(int b_seq) {
mapper.deleteBoard(b_seq);
}
}
■ Controller / HomeController.java
package com.test.Controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.test.Domain.Testboard;
import com.test.Service.TestService;
/**
* Handles requests for the application home page.
*/
@Controller
public class HomeController {
@Autowired
private TestService service;
@RequestMapping(value = {"/","/main","/home"}, method = RequestMethod.GET)
public String home(Model model) throws Exception {
List<Testboard> selectAllBoard = service.selectAllBoard();
model.addAttribute("test", selectAllBoard);
return "home";
}
@RequestMapping("/view")
public String view(int b_seq, Model model) {
Testboard tb = service.selectSeqBoard(b_seq);
model.addAttribute("test", tb);
return "view";
}
@RequestMapping("/write")
public String write() {
return "write";
}
@RequestMapping("/write.do")
public String writedo(Testboard tb) {
service.insertBoard(tb);
return "redirect:main";
}
@RequestMapping("/update")
public String update(int b_seq, Model model) {
Testboard tb = service.selectSeqBoard(b_seq);
model.addAttribute("test", tb);
return "update";
}
@RequestMapping("/update.do")
public String updatedo(Testboard tb) {
service.updateBoard(tb);
return "redirect:main";
}
@RequestMapping("/delete.do")
public String deletedo(int b_seq) {
service.deleteBoard(b_seq);
return "redirect:main";
}
}
■ views / home.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>게시판 리스트</title>
<!-- bootstrap 라이브러리 CDN 방식 등록 -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
<!-- css - 꾸미기 -->
<style type="text/css">
.dataRow:hover {
background: #eee;
cursor: pointer;
}
div.nav-align{
text-align: center;
}
</style>
<script type="text/javascript">
// jquery ( == $) - HTML의 로딩이 끝나면 동작
$(function(){
// 데이터 한 줄을 클릭하면 글번호, inc와 함께 글보기로 이동한다.
$(".dataRow").click(function(){
//alert("글보기 이동 클릭");
var b_seq = $(this).find(".b_seq").text();
// js : 페이지 이동 location.href = location
location = "view?b_seq=" + b_seq;
});
});
</script>
</head>
<body>
<div class="container">
<h1>게시판 리스트</h1>
<table class="table">
<tr>
<th>번호</th>
<th>제목</th>
<th>작성자</th>
</tr>
<c:if test="${empty test }">
<tr>
<td colspan="3">데이터가 존재하지 않습니다.</td>
</tr>
</c:if>
<c:if test="${!empty test }">
<c:forEach items="${requestScope.test }" var="vo">
<tr class="dataRow">
<td class="b_seq" >${pageScope.vo.b_seq }</td>
<td >${vo.b_title }</td>
<td >${vo.b_writer }</td>
</tr>
</c:forEach>
</c:if>
</table>
<a href = "write" class="btn btn-default">글쓰기</a>
</div>
</body>
</html>
■ views / update.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>게시판 글수정</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
<script type="text/javascript">
$(function () {
$(".cancelBackBtn").click(function () {
history.back();
});
});
</script>
</head>
<body>
<div class="container">
<h1>게시판 글수정 폼</h1>
<form action="update.do" method="post">
<div class="form-group">
<label for="b_seq">번호:</label>
<input name="b_seq" type="text" class="form-control" id="b_seq" value="${test.b_seq }" readonly="readonly">
</div>
<div class="form-group">
<label for="title">제목:</label>
<input name="b_title" type="text" class="form-control" id="title" maxlength="100"
required="required" value="${test.b_title }">
</div>
<div class="form-group">
<label for="content">내용:</label>
<textarea name="b_content" class="form-control" rows="5" id="content">${test.b_content }</textarea>
</div>
<div class="form-group">
<label for="writer">작성자:</label>
<input name="b_writer" type="text" class="form-control" id="writer" maxlength="20" value="${test.b_writer }" readonly="readonly">
</div>
<div class="form-group">
<label for="b_regdate">작성일:</label>
<input name="b_regdate" type="text" class="form-control" id="b_regdate" maxlength="20" value="${test.b_regdate }" readonly="readonly">
</div>
<button>수정</button>
<button type="button" class="cancelBackBtn">취소</button>
</form>
</div>
</body>
</html>
■ views / view.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>게시판 자세히보기</title>
<!-- BootStrap 라이브러리 등록 -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
<script type="text/javascript">
$(function(){
var imageExt = ["JPG", "JPEG", "GIF", "PNG", "BMP"];
$("#changeBtn").click(function(){
var fileName = $("#imageFile").val();
if(!fileName){
alert("바꿀 이미지를 반드시 선택하셔야 합니다.");
$("#imageFile").focus();
return false;
}
var ext = fileName.substring(fileName.lastIndexOf(".")+1).toUpperCase();
var checkExt = false; // 지원하지 않는 확장자를 기본으로 셋팅
for(i = 0; i < imageExt.length; i++){
if(ext == imageExt[i]){
checkExt = true; // 지원하는 확장자로 바꾼다.
break;
}
}
// 지원하지 않는 이미지 파일 선택경의 처리
if(!checkExt){
alert("지원하지 않는 이미지 파일입니다.");
$("#imageFile").focus();
return false;
}
$("#updateFileForm").submit();
});
// 삭제 버튼 이벤트 처리 - 위 아래 버튼이므로 id는 사용하지 않는다. class 사용.
$(".deleteBtn").click(function(){
return confirm("정말 삭제하시겠습니까?");
});
});
</script>
</head>
<body>
<div class="container">
<h1>게시판 자세히보기</h1>
<table class="table">
<tr>
<td colspan="5">
<a href="update?b_seq=${test.b_seq }" class="btn btn-default">수정</a>
<a href="delete.do?b_seq=${test.b_seq }" class="btn btn-default deleteBtn">삭제</a>
<a href="main" class="btn btn-default">홈</a>
</td>
</tr>
<tr>
<th style="width: 100px;">번호</th>
<td>${test.b_seq }</td>
</tr>
<tr>
<th>제목</th>
<td>${test.b_title }</td>
</tr>
<tr>
<th>내용</th>
<td>${test.b_content }</td>
</tr>
<tr>
<th>작성자</th>
<td>${test.b_writer }</td>
</tr>
<tr>
<th>작성일</th>
<td>
<fmt:parseDate value="${test.b_regdate}" var="dateFmt" pattern="yyyy-MM-dd HH:mm:ss"/>
<fmt:formatDate value="${dateFmt}" pattern="yyyy-MM-dd HH:mm:ss" />
</td>
</tr>
<tr>
<td colspan="5">
<a href="update?b_seq=${test.b_seq }" class="btn btn-default">수정</a>
<a href="delete.do?b_seq=${test.b_seq }" class="btn btn-default deleteBtn">삭제</a>
<a href="main" class="btn btn-default">홈</a>
</td>
</tr>
</table>
</div>
</body>
</html>
■ views / write.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>게시판 글쓰기</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
<script type="text/javascript">
$(function () {
$(".cancelBackBtn").click(function () {
history.back();
});
});
</script>
</head>
<body>
<div class="container">
<h1>게시판 글쓰기 폼</h1>
<form action="write.do" method="post">
<div class="form-group">
<label for="title">제목:</label>
<input name="b_title" type="text" class="form-control" id="title"maxlength="100">
</div>
<div class="form-group">
<label for="content">내용:</label>
<textarea name="b_content" class="form-control" rows="5"
id="content"></textarea>
</div>
<div class="form-group">
<label for="writer">작성자:</label>
<input name="b_writer" type="text" class="form-control" id="writer" maxlength="20">
</div>
<button>등록</button>
<button type="button" class="cancelBackBtn">취소</button>
</form>
</div>
</body>
</html>
※ 제대로 넣는다면 아래와같이 됩니다.