관리 메뉴

거니의 velog

231120_SPRING 1 (4) 본문

대덕인재개발원_웹기반 애플리케이션

231120_SPRING 1 (4)

Unlimited00 2023. 11. 20. 08:28
7. 책 삭제 만들기

	7-1. 책 삭제 기능 쿼리 생성
		- 책 삭제 기능 쿼리 작성
		- <delete id="deleteBook" parameterType="hashMap"></delete>
		
	7-2. 책 삭제 기능 DAO 메소드 작성
		- public int delete(Map<String, Object> map)
		
	7-3. 책 삭제 기능 service 인터페이스 메소드 생성
		- public boolean removeBook(Map <String, Object> map)
		
	7-4. 책 삭제 기능 service 클래스 메소드 생성
		- public boolean removeBook(Map <String, Object> map)
		
	7-5. 책 삭제 기능 컨트롤러 메소드 작성
		- public ModelAndView removeBook(Map <String, Object> map)
		
	7-6. 책 삭제 기능 확인하기
		- 책 삭제 기능 > 책 목록
		
8. 책 목록 만들기

	8-1. 책 목록 기능 쿼리 생성
		- 책 목록 기능 쿼리 작성
		- <select id="selectBookList" parameterType="hashMap" resultType="hashMap"></select>
		
	8-2. 책 목록 기능 DAO 메소드 생성
		- List<Map<String, Object>> selectBookList(Map<String, Object> map)
		
	8-3. 책 목록 service 인터페이스 메소드 생성
		- List<Map<String, Object>> selectBookList(Map<String, Object> map)
		
	8-4. 책 목록 service 클래스 메소드 작성
		- List<Map<String, Object>> selectBookList(Map<String, Object> map)
		
	8-5. 책 목록 기능 컨트롤러 메소드 생성
		- public ModelAndView list(@RequestParam Map<String, Object> map)
		
	8-6. 책 목록 화면 뷰 생성
		- views/book/list.jsp
		
	8-7. 책 목록 기능 확인하기
    
9. 책 검색 만들기

	9-1. 책 검색 기능 쿼리 생성
		- <select id="selectBookList" parameterType="hashMap" resultType="hashMap"></select>
		> 기존 목록 데이터 조회 시, 사용했던 쿼리 내에 동적 쿼리 추가(mybatis 조건절 부여)
		
	9-2. 책 검색 기능 목록 컨트롤러 메소드 수정
	
	9-3. 책 검색 화면 뷰 수정
		- views/book/list.jsp 수정
		
	9-4. 책 검색 기능 확인하기

[BoardRetreiveController.java]

package kr.or.ddit.board.web;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@RequestMapping("/board")
public class BoardRetreiveController {

	@RequestMapping(value = "/list.do", method = RequestMethod.GET)
	public String boardList() {
		return "board/list";
	}
	
}

[list.jsp]

<%@ page contentType="text/html; charset=utf-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>

<head>
    <link href="${pageContext.request.contextPath }/resources/css/bootstrap.min.css" rel="stylesheet">
    <link rel="stylesheet" href="${pageContext.request.contextPath }/resources/css/headers.css">
    <script src="${pageContext.request.contextPath}/resources/plugins/jquery/jquery.min.js"></script>
    <title>메인화면</title>
</head>
<style>
    .bi {
        vertical-align: -.125em;
        fill: currentColor;
    }
</style>

<body>
    <svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
        <symbol id="bootstrap" viewBox="0 0 118 94">
            <title>Bootstrap</title>
            <path fill-rule="evenodd" clip-rule="evenodd" d="M24.509 0c-6.733 0-11.715 5.893-11.492 12.284.214 6.14-.064 14.092-2.066 20.577C8.943 39.365 5.547 43.485 0 44.014v5.972c5.547.529 8.943 4.649 10.951 11.153 2.002 6.485 2.28 14.437 2.066 20.577C12.794 88.106 17.776 94 24.51 94H93.5c6.733 0 11.714-5.893 11.491-12.284-.214-6.14.064-14.092 2.066-20.577 2.009-6.504 5.396-10.624 10.943-11.153v-5.972c-5.547-.529-8.934-4.649-10.943-11.153-2.002-6.484-2.28-14.437-2.066-20.577C105.214 5.894 100.233 0 93.5 0H24.508zM80 57.863C80 66.663 73.436 72 62.543 72H44a2 2 0 01-2-2V24a2 2 0 012-2h18.437c9.083 0 15.044 4.92 15.044 12.474 0 5.302-4.01 10.049-9.119 10.88v.277C75.317 46.394 80 51.21 80 57.863zM60.521 28.34H49.948v14.934h8.905c6.884 0 10.68-2.772 10.68-7.727 0-4.643-3.264-7.207-9.012-7.207zM49.948 49.2v16.458H60.91c7.167 0 10.964-2.876 10.964-8.281 0-5.406-3.903-8.178-11.425-8.178H49.948z"></path>
        </symbol>
        <symbol id="home" viewBox="0 0 16 16">
            <path d="M8.354 1.146a.5.5 0 0 0-.708 0l-6 6A.5.5 0 0 0 1.5 7.5v7a.5.5 0 0 0 .5.5h4.5a.5.5 0 0 0 .5-.5v-4h2v4a.5.5 0 0 0 .5.5H14a.5.5 0 0 0 .5-.5v-7a.5.5 0 0 0-.146-.354L13 5.793V2.5a.5.5 0 0 0-.5-.5h-1a.5.5 0 0 0-.5.5v1.293L8.354 1.146zM2.5 14V7.707l5.5-5.5 5.5 5.5V14H10v-4a.5.5 0 0 0-.5-.5h-3a.5.5 0 0 0-.5.5v4H2.5z" />
        </symbol>
        <symbol id="grid" viewBox="0 0 16 16">
            <path d="M1 2.5A1.5 1.5 0 0 1 2.5 1h3A1.5 1.5 0 0 1 7 2.5v3A1.5 1.5 0 0 1 5.5 7h-3A1.5 1.5 0 0 1 1 5.5v-3zM2.5 2a.5.5 0 0 0-.5.5v3a.5.5 0 0 0 .5.5h3a.5.5 0 0 0 .5-.5v-3a.5.5 0 0 0-.5-.5h-3zm6.5.5A1.5 1.5 0 0 1 10.5 1h3A1.5 1.5 0 0 1 15 2.5v3A1.5 1.5 0 0 1 13.5 7h-3A1.5 1.5 0 0 1 9 5.5v-3zm1.5-.5a.5.5 0 0 0-.5.5v3a.5.5 0 0 0 .5.5h3a.5.5 0 0 0 .5-.5v-3a.5.5 0 0 0-.5-.5h-3zM1 10.5A1.5 1.5 0 0 1 2.5 9h3A1.5 1.5 0 0 1 7 10.5v3A1.5 1.5 0 0 1 5.5 15h-3A1.5 1.5 0 0 1 1 13.5v-3zm1.5-.5a.5.5 0 0 0-.5.5v3a.5.5 0 0 0 .5.5h3a.5.5 0 0 0 .5-.5v-3a.5.5 0 0 0-.5-.5h-3zm6.5.5A1.5 1.5 0 0 1 10.5 9h3a1.5 1.5 0 0 1 1.5 1.5v3a1.5 1.5 0 0 1-1.5 1.5h-3A1.5 1.5 0 0 1 9 13.5v-3zm1.5-.5a.5.5 0 0 0-.5.5v3a.5.5 0 0 0 .5.5h3a.5.5 0 0 0 .5-.5v-3a.5.5 0 0 0-.5-.5h-3z" />
        </symbol>
    </svg>
    <main>
        <header>
            <div class="px-3 py-2 text-bg-dark">
                <div class="container">
                    <div class="d-flex flex-wrap align-items-center justify-content-center justify-content-lg-start">
                        <a href="/" class="d-flex align-items-center my-2 my-lg-0 me-lg-auto text-white text-decoration-none">
                            <svg class="bi me-2" width="40" height="32" role="img" aria-label="Bootstrap">
                                <use xlink:href="#bootstrap" />
                            </svg>
                        </a>
                        <ul class="nav col-12 col-lg-auto my-2 justify-content-center my-md-0 text-small">
                            <li>
                                <a href="/main.do" class="nav-link text-white">
                                    <svg class="bi d-block mx-auto mb-1" width="24" height="24">
                                        <use xlink:href="#home" />
                                    </svg> Home
                                </a>
                            </li>
                            <li>
                                <a href="/board/list.do" class="nav-link text-white">
                                    <svg class="bi d-block mx-auto mb-1" width="24" height="24">
                                        <use xlink:href="#grid" />
                                    </svg> 일반게시판
                                </a>
                            </li>
                            <li>
                                <a href="/notice/list.do" class="nav-link text-white">
                                    <svg class="bi d-block mx-auto mb-1" width="24" height="24">
                                        <use xlink:href="#grid" />
                                    </svg> 공지사항게시판
                                </a>
                            </li>
                            <li>
                                <a href="/free/list.do" class="nav-link text-white">
                                    <svg class="bi d-block mx-auto mb-1" width="24" height="24">
                                        <use xlink:href="#grid" />
                                    </svg> 자유게시판
                                </a>
                            </li>
                        </ul>
                    </div>
                </div>
            </div>
        </header>

        <div class="position-relative overflow-hidden p-3 p-md-8 m-md-8 text-center bg-white">
            <div class="col-md-8 p-lg-8 mx-auto my-5">
                <h4 class="display-4 fw-normal">일반게시판</h4>
                <p class="lead fw-normal">일반게시판 CRUD를 작성해주세요.</p>
            </div>
            <div class="product-device shadow-sm d-none d-md-block"></div>
            <div class="product-device product-device-2 shadow-sm d-none d-md-block"></div>
        </div>

        <div class="container">
            <div class="row">
                <div class="col-md-12">
                    <div class="">
                        <div class="card-header">
                            <div class="card-tools">
                            </div>
                            <h3 class="card-title">일반게시판</h3>
                            <div align="right">
                                <span class="badge bg-dark-subtle border border-dark-subtle text-dark-emphasis rounded-pill">전체 0건</span>
                            </div>
                        </div>
                        <div class="card-body mt-3">
                            <div align="right">
                                <form class="input-group input-group-sm" method="post" id="searchForm" style="width: 440px;">
                                    <select class="form-control" name="searchType">
                                        <option value="title">제목</option>
                                        <option value="writer">작성자</option>
                                    </select>
                                    <input type="text" name="searchWord" class="form-control float-right" value="" placeholder="Search">
                                    <div class="input-group-append">
                                        <button type="submit" class="btn btn-default">
                                            <i class="fas fa-search"></i>검색
                                        </button>
                                    </div>
                                </form>
                            </div>
                            <div class="mt-2">
                                <table class="table">
                                    <thead class="table-dark">
                                        <tr>
                                            <th style="width: 6%">#</th>
                                            <th style="width: px">제목</th>
                                            <th style="width: 12%">작성자</th>
                                            <th style="width: 12%">작성일</th>
                                            <th style="width: 10%">조회수</th>
                                        </tr>
                                    </thead>
                                    <tbody>
                                        <tr>
                                            <td colspan="5">조회하신 게시글이 존재하지 않습니다.</td>
                                        </tr>
                                        <tr>
                                            <td></td>
                                            <td></td>
                                            <td></td>
                                            <td></td>
                                            <td></td>
                                        </tr>
                                    </tbody>
                                </table>
                            </div>
                            <div align="left">
                                <a href="/board/form.do" class="btn btn-primary">등록</a>
                            </div>
                        </div>
                        <div class="card-footer clearfix mt-4" id="pagingArea"></div>
                    </div>
                </div>
                <div class="col-md-12"><br /><br /><br /></div>
            </div>
        </div>
    </main>
</body>

</html>

- http://localhost/board/list.do


[BoardInsertController.java]

package kr.or.ddit.board.web;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@RequestMapping("/board")
public class BoardInsertController {

	@RequestMapping(value = "/form.do", method = RequestMethod.GET)
	public String boardForm() {
		return "board/form";
	}
	
}

[form.jsp]

<%@ page contentType="text/html; charset=utf-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page contentType="text/html; charset=utf-8"%>
<html>

<head>
    <link href="${pageContext.request.contextPath }/resources/css/bootstrap.min.css" rel="stylesheet">
    <link rel="stylesheet" href="${pageContext.request.contextPath }/resources/css/headers.css">
    <script src="${pageContext.request.contextPath}/resources/plugins/jquery/jquery.min.js"></script>
    <script type="text/javascript" src="${pageContext.request.contextPath }/resources/ckeditor/ckeditor.js"></script>
    <title>일반게시판 등록/수정</title>
</head>
<style>
    .bi {
        vertical-align: -.125em;
        fill: currentColor;
    }
</style>

<body>
    <svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
        <symbol id="bootstrap" viewBox="0 0 118 94">
            <title>Bootstrap</title>
            <path fill-rule="evenodd" clip-rule="evenodd" d="M24.509 0c-6.733 0-11.715 5.893-11.492 12.284.214 6.14-.064 14.092-2.066 20.577C8.943 39.365 5.547 43.485 0 44.014v5.972c5.547.529 8.943 4.649 10.951 11.153 2.002 6.485 2.28 14.437 2.066 20.577C12.794 88.106 17.776 94 24.51 94H93.5c6.733 0 11.714-5.893 11.491-12.284-.214-6.14.064-14.092 2.066-20.577 2.009-6.504 5.396-10.624 10.943-11.153v-5.972c-5.547-.529-8.934-4.649-10.943-11.153-2.002-6.484-2.28-14.437-2.066-20.577C105.214 5.894 100.233 0 93.5 0H24.508zM80 57.863C80 66.663 73.436 72 62.543 72H44a2 2 0 01-2-2V24a2 2 0 012-2h18.437c9.083 0 15.044 4.92 15.044 12.474 0 5.302-4.01 10.049-9.119 10.88v.277C75.317 46.394 80 51.21 80 57.863zM60.521 28.34H49.948v14.934h8.905c6.884 0 10.68-2.772 10.68-7.727 0-4.643-3.264-7.207-9.012-7.207zM49.948 49.2v16.458H60.91c7.167 0 10.964-2.876 10.964-8.281 0-5.406-3.903-8.178-11.425-8.178H49.948z"></path>
        </symbol>
        <symbol id="home" viewBox="0 0 16 16">
            <path d="M8.354 1.146a.5.5 0 0 0-.708 0l-6 6A.5.5 0 0 0 1.5 7.5v7a.5.5 0 0 0 .5.5h4.5a.5.5 0 0 0 .5-.5v-4h2v4a.5.5 0 0 0 .5.5H14a.5.5 0 0 0 .5-.5v-7a.5.5 0 0 0-.146-.354L13 5.793V2.5a.5.5 0 0 0-.5-.5h-1a.5.5 0 0 0-.5.5v1.293L8.354 1.146zM2.5 14V7.707l5.5-5.5 5.5 5.5V14H10v-4a.5.5 0 0 0-.5-.5h-3a.5.5 0 0 0-.5.5v4H2.5z" />
        </symbol>
        <symbol id="grid" viewBox="0 0 16 16">
            <path d="M1 2.5A1.5 1.5 0 0 1 2.5 1h3A1.5 1.5 0 0 1 7 2.5v3A1.5 1.5 0 0 1 5.5 7h-3A1.5 1.5 0 0 1 1 5.5v-3zM2.5 2a.5.5 0 0 0-.5.5v3a.5.5 0 0 0 .5.5h3a.5.5 0 0 0 .5-.5v-3a.5.5 0 0 0-.5-.5h-3zm6.5.5A1.5 1.5 0 0 1 10.5 1h3A1.5 1.5 0 0 1 15 2.5v3A1.5 1.5 0 0 1 13.5 7h-3A1.5 1.5 0 0 1 9 5.5v-3zm1.5-.5a.5.5 0 0 0-.5.5v3a.5.5 0 0 0 .5.5h3a.5.5 0 0 0 .5-.5v-3a.5.5 0 0 0-.5-.5h-3zM1 10.5A1.5 1.5 0 0 1 2.5 9h3A1.5 1.5 0 0 1 7 10.5v3A1.5 1.5 0 0 1 5.5 15h-3A1.5 1.5 0 0 1 1 13.5v-3zm1.5-.5a.5.5 0 0 0-.5.5v3a.5.5 0 0 0 .5.5h3a.5.5 0 0 0 .5-.5v-3a.5.5 0 0 0-.5-.5h-3zm6.5.5A1.5 1.5 0 0 1 10.5 9h3a1.5 1.5 0 0 1 1.5 1.5v3a1.5 1.5 0 0 1-1.5 1.5h-3A1.5 1.5 0 0 1 9 13.5v-3zm1.5-.5a.5.5 0 0 0-.5.5v3a.5.5 0 0 0 .5.5h3a.5.5 0 0 0 .5-.5v-3a.5.5 0 0 0-.5-.5h-3z" />
        </symbol>
    </svg>
    <main>
        <header>
            <div class="px-3 py-2 text-bg-dark">
                <div class="container">
                    <div class="d-flex flex-wrap align-items-center justify-content-center justify-content-lg-start">
                        <a href="/" class="d-flex align-items-center my-2 my-lg-0 me-lg-auto text-white text-decoration-none">
                            <svg class="bi me-2" width="40" height="32" role="img" aria-label="Bootstrap">
                                <use xlink:href="#bootstrap" />
                            </svg>
                        </a>
                        <ul class="nav col-12 col-lg-auto my-2 justify-content-center my-md-0 text-small">
                            <li>
                                <a href="/main.do" class="nav-link text-white">
                                    <svg class="bi d-block mx-auto mb-1" width="24" height="24">
                                        <use xlink:href="#home" />
                                    </svg> Home
                                </a>
                            </li>
                            <li>
                                <a href="/board/list.do" class="nav-link text-white">
                                    <svg class="bi d-block mx-auto mb-1" width="24" height="24">
                                        <use xlink:href="#grid" />
                                    </svg> 일반게시판
                                </a>
                            </li>
                            <li>
                                <a href="/notice/list.do" class="nav-link text-white">
                                    <svg class="bi d-block mx-auto mb-1" width="24" height="24">
                                        <use xlink:href="#grid" />
                                    </svg> 공지사항게시판
                                </a>
                            </li>
                            <li>
                                <a href="/free/list.do" class="nav-link text-white">
                                    <svg class="bi d-block mx-auto mb-1" width="24" height="24">
                                        <use xlink:href="#grid" />
                                    </svg> 자유게시판
                                </a>
                            </li>
                        </ul>
                    </div>
                </div>
            </div>
        </header>

        <div class="position-relative overflow-hidden p-3 p-md-8 m-md-8 text-center bg-white">
            <div class="col-md-8 p-lg-8 mx-auto my-5">
                <h4 class="display-4 fw-normal">일반게시판</h4>
                <p class="lead fw-normal">일반게시판 CRUD를 작성해주세요.</p>
            </div>
            <div class="product-device shadow-sm d-none d-md-block"></div>
            <div class="product-device product-device-2 shadow-sm d-none d-md-block"></div>
        </div>

        <div class="container">
            <div class="row">
                <div class="col-md-12">
                    <div class="">
                        <div class="card-body">
                            <form method="post" action="" id="boardForm" class="form-horizontal">
                                <div class="form-group row">
                                    <label class="col-sm-2 control-label">제목</label>
                                    <div class="col-sm-10">
                                        <input name="boTitle" type="text" class="form-control" value="" placeholder="subject">
                                    </div>
                                    <font color="red" style="font-size: 12px;"></font>
                                </div>
                                <div class="form-group row mt-4">
                                    <label class="col-sm-2 control-label">내용</label>
                                    <div class="col-sm-10">
                                        <textarea name="boContent" cols="50" rows="5" class="form-control" placeholder="content"></textarea>
                                    </div>
                                    <font color="red" style="font-size: 12px;"></font>
                                </div>
                                <div class="form-group row mt-4">
                                    <div class="col-sm-offset-2 col-sm-12 ">
                                        <input type="button" value="등록" class="btn btn-primary float-right" id="addBtn">
                                        <input type="button" value="취소" class="btn btn-danger float-right" id="cancelBtn">
                                        <input type="button" value="목록" class="btn btn-success float-right" id="listBtn">
                                    </div>
                                </div>
                            </form>
                        </div>
                    </div>
                </div>
                <div class="col-md-12"><br /><br /><br /></div>
            </div>
        </div>
    </main>
</body>

</html>

- http://localhost/board/form.do


[form.jsp]

<%@ page contentType="text/html; charset=utf-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page contentType="text/html; charset=utf-8"%>
<html>

<head>
    <link href="${pageContext.request.contextPath }/resources/css/bootstrap.min.css" rel="stylesheet">
    <link rel="stylesheet" href="${pageContext.request.contextPath }/resources/css/headers.css">
    <script src="${pageContext.request.contextPath}/resources/plugins/jquery/jquery.min.js"></script>
    <script type="text/javascript" src="${pageContext.request.contextPath }/resources/ckeditor/ckeditor.js"></script>
    <title>일반게시판 등록/수정</title>
</head>
<style>
    .bi {
        vertical-align: -.125em;
        fill: currentColor;
    }
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<body>
    <svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
        <symbol id="bootstrap" viewBox="0 0 118 94">
            <title>Bootstrap</title>
            <path fill-rule="evenodd" clip-rule="evenodd" d="M24.509 0c-6.733 0-11.715 5.893-11.492 12.284.214 6.14-.064 14.092-2.066 20.577C8.943 39.365 5.547 43.485 0 44.014v5.972c5.547.529 8.943 4.649 10.951 11.153 2.002 6.485 2.28 14.437 2.066 20.577C12.794 88.106 17.776 94 24.51 94H93.5c6.733 0 11.714-5.893 11.491-12.284-.214-6.14.064-14.092 2.066-20.577 2.009-6.504 5.396-10.624 10.943-11.153v-5.972c-5.547-.529-8.934-4.649-10.943-11.153-2.002-6.484-2.28-14.437-2.066-20.577C105.214 5.894 100.233 0 93.5 0H24.508zM80 57.863C80 66.663 73.436 72 62.543 72H44a2 2 0 01-2-2V24a2 2 0 012-2h18.437c9.083 0 15.044 4.92 15.044 12.474 0 5.302-4.01 10.049-9.119 10.88v.277C75.317 46.394 80 51.21 80 57.863zM60.521 28.34H49.948v14.934h8.905c6.884 0 10.68-2.772 10.68-7.727 0-4.643-3.264-7.207-9.012-7.207zM49.948 49.2v16.458H60.91c7.167 0 10.964-2.876 10.964-8.281 0-5.406-3.903-8.178-11.425-8.178H49.948z"></path>
        </symbol>
        <symbol id="home" viewBox="0 0 16 16">
            <path d="M8.354 1.146a.5.5 0 0 0-.708 0l-6 6A.5.5 0 0 0 1.5 7.5v7a.5.5 0 0 0 .5.5h4.5a.5.5 0 0 0 .5-.5v-4h2v4a.5.5 0 0 0 .5.5H14a.5.5 0 0 0 .5-.5v-7a.5.5 0 0 0-.146-.354L13 5.793V2.5a.5.5 0 0 0-.5-.5h-1a.5.5 0 0 0-.5.5v1.293L8.354 1.146zM2.5 14V7.707l5.5-5.5 5.5 5.5V14H10v-4a.5.5 0 0 0-.5-.5h-3a.5.5 0 0 0-.5.5v4H2.5z" />
        </symbol>
        <symbol id="grid" viewBox="0 0 16 16">
            <path d="M1 2.5A1.5 1.5 0 0 1 2.5 1h3A1.5 1.5 0 0 1 7 2.5v3A1.5 1.5 0 0 1 5.5 7h-3A1.5 1.5 0 0 1 1 5.5v-3zM2.5 2a.5.5 0 0 0-.5.5v3a.5.5 0 0 0 .5.5h3a.5.5 0 0 0 .5-.5v-3a.5.5 0 0 0-.5-.5h-3zm6.5.5A1.5 1.5 0 0 1 10.5 1h3A1.5 1.5 0 0 1 15 2.5v3A1.5 1.5 0 0 1 13.5 7h-3A1.5 1.5 0 0 1 9 5.5v-3zm1.5-.5a.5.5 0 0 0-.5.5v3a.5.5 0 0 0 .5.5h3a.5.5 0 0 0 .5-.5v-3a.5.5 0 0 0-.5-.5h-3zM1 10.5A1.5 1.5 0 0 1 2.5 9h3A1.5 1.5 0 0 1 7 10.5v3A1.5 1.5 0 0 1 5.5 15h-3A1.5 1.5 0 0 1 1 13.5v-3zm1.5-.5a.5.5 0 0 0-.5.5v3a.5.5 0 0 0 .5.5h3a.5.5 0 0 0 .5-.5v-3a.5.5 0 0 0-.5-.5h-3zm6.5.5A1.5 1.5 0 0 1 10.5 9h3a1.5 1.5 0 0 1 1.5 1.5v3a1.5 1.5 0 0 1-1.5 1.5h-3A1.5 1.5 0 0 1 9 13.5v-3zm1.5-.5a.5.5 0 0 0-.5.5v3a.5.5 0 0 0 .5.5h3a.5.5 0 0 0 .5-.5v-3a.5.5 0 0 0-.5-.5h-3z" />
        </symbol>
    </svg>
    <main>
        <header>
            <div class="px-3 py-2 text-bg-dark">
                <div class="container">
                    <div class="d-flex flex-wrap align-items-center justify-content-center justify-content-lg-start">
                        <a href="/" class="d-flex align-items-center my-2 my-lg-0 me-lg-auto text-white text-decoration-none">
                            <svg class="bi me-2" width="40" height="32" role="img" aria-label="Bootstrap">
                                <use xlink:href="#bootstrap" />
                            </svg>
                        </a>
                        <ul class="nav col-12 col-lg-auto my-2 justify-content-center my-md-0 text-small">
                            <li>
                                <a href="/main.do" class="nav-link text-white">
                                    <svg class="bi d-block mx-auto mb-1" width="24" height="24">
                                        <use xlink:href="#home" />
                                    </svg> Home
                                </a>
                            </li>
                            <li>
                                <a href="/board/list.do" class="nav-link text-white">
                                    <svg class="bi d-block mx-auto mb-1" width="24" height="24">
                                        <use xlink:href="#grid" />
                                    </svg> 일반게시판
                                </a>
                            </li>
                            <li>
                                <a href="/notice/list.do" class="nav-link text-white">
                                    <svg class="bi d-block mx-auto mb-1" width="24" height="24">
                                        <use xlink:href="#grid" />
                                    </svg> 공지사항게시판
                                </a>
                            </li>
                            <li>
                                <a href="/free/list.do" class="nav-link text-white">
                                    <svg class="bi d-block mx-auto mb-1" width="24" height="24">
                                        <use xlink:href="#grid" />
                                    </svg> 자유게시판
                                </a>
                            </li>
                        </ul>
                    </div>
                </div>
            </div>
        </header>

        <div class="position-relative overflow-hidden p-3 p-md-8 m-md-8 text-center bg-white">
            <div class="col-md-8 p-lg-8 mx-auto my-5">
                <h4 class="display-4 fw-normal">일반게시판</h4>
                <p class="lead fw-normal">일반게시판 CRUD를 작성해주세요.</p>
            </div>
            <div class="product-device shadow-sm d-none d-md-block"></div>
            <div class="product-device product-device-2 shadow-sm d-none d-md-block"></div>
        </div>

        <div class="container">
            <div class="row">
                <div class="col-md-12">
                    <div class="">
                        <div class="card-body">
                            <form method="post" action="insert.do" id="boardForm" name="boardForm" class="form-horizontal">
                                <div class="form-group row">
                                    <label class="col-sm-2 control-label">제목</label>
                                    <div class="col-sm-10">
                                        <input id="boTitle" name="boTitle" type="text" class="form-control" value="" placeholder="subject">
                                    </div>
                                    <font color="red" style="font-size: 12px;"></font>
                                </div>
                                <div class="form-group row mt-4">
                                    <label class="col-sm-2 control-label">내용</label>
                                    <div class="col-sm-10">
                                        <textarea id="boContent" name="boContent" cols="50" rows="5" class="form-control" placeholder="content"></textarea>
                                    </div>
                                    <font color="red" style="font-size: 12px;"></font>
                                </div>
                                <div class="form-group row mt-4">
                                    <div class="col-sm-offset-2 col-sm-12 ">
                                        <input type="button" value="등록" class="btn btn-primary float-right" id="addBtn">
                                        <input type="button" value="취소" class="btn btn-danger float-right" id="cancelBtn">
                                        <input type="button" value="목록" class="btn btn-success float-right" id="listBtn">
                                    </div>
                                </div>
                            </form>
                        </div>
                    </div>
                </div>
                <div class="col-md-12"><br /><br /><br /></div>
            </div>
        </div>
    </main>
</body>
<script type="text/javascript">
	$(function(){
		var addBtn = $("#addBtn"); // 등록 버튼
		var cancelBtn = $("#cancelBtn"); // 취소 버튼
		var listBtn = $("#listBtn"); // 목록 버튼
		var boTitle = $("#boTitle");
		var boContent = $("#boContent");
		var boardForm = $("#boardForm"); // 등록 form
		
		// 등록 버튼 이벤트
		addBtn.on("click", function(){
			var title = boTitle.val(); // 제목 데이터
			var content = boContent.val(); // 내용 데이터
			
			// 제목을 입력하지 않았을 때 발생할 이벤트
			if(!title) {
				alert("제목을 입력해주세요!");
				boTitle.focus();
				return false;
			}
			
			// 내용을 입력하지 않았을 때 발생할 이벤트
			if(!content) {
				alert("내용을 입력해주세요!");
				boContent.focus();
				return false;
			}
			
			boardForm.submit();
		});
		
		// 취소 버튼 이벤트
		cancelBtn.on("click", function(){
			
		});
		
		// 목록 버튼 이벤트
		listBtn.on("click", function(){
			location.href = "/board/list.do";
		});
	});
</script>
</html>

[BoardVO.java]

package kr.or.ddit.vo;

public class BoardVO {

	private int boNo; // 일반 게시판 번호
	private String boTitle; // 일반 게시판 제목
	private String boWriter; // 일반 게시판 작성자
	private String boContent; // 일반 게시판 내용
	private String boDate; // 일반 게시판 작성일
	private int boHit; // 일반 게시판 조회수
	
	public BoardVO() {}
	public BoardVO(int boNo, String boTitle, String boWriter, String boContent, String boDate, int boHit) {
		this.boNo = boNo;
		this.boTitle = boTitle;
		this.boWriter = boWriter;
		this.boContent = boContent;
		this.boDate = boDate;
		this.boHit = boHit;
	}
	
	public int getBoNo() {
		return boNo;
	}
	public void setBoNo(int boNo) {
		this.boNo = boNo;
	}
	public String getBoTitle() {
		return boTitle;
	}
	public void setBoTitle(String boTitle) {
		this.boTitle = boTitle;
	}
	public String getBoWriter() {
		return boWriter;
	}
	public void setBoWriter(String boWriter) {
		this.boWriter = boWriter;
	}
	public String getBoContent() {
		return boContent;
	}
	public void setBoContent(String boContent) {
		this.boContent = boContent;
	}
	public String getBoDate() {
		return boDate;
	}
	public void setBoDate(String boDate) {
		this.boDate = boDate;
	}
	public int getBoHit() {
		return boHit;
	}
	public void setBoHit(int boHit) {
		this.boHit = boHit;
	}
	
	@Override
	public String toString() {
		return "BoardVO [boNo=" + boNo + ", boTitle=" + boTitle + ", boWriter=" + boWriter + ", boContent=" + boContent
				+ ", boDate=" + boDate + ", boHit=" + boHit + "]";
	}
	
}

[pom.xml]

		<!--  
			apache commons
			데이터 StringUtils를 이용할 때 사용하며,
			데이터를 null, 공백체크할 때 사용한다.
		-->
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-lang3</artifactId>
			<version>3.6</version>
		</dependency>
	
		<!-- Test -->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.7</version>
			<scope>test</scope>
		</dependency>        
	</dependencies>

[BoardInsertController.java]

package kr.or.ddit.board.web;

import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import kr.or.ddit.vo.BoardVO;

@Controller
@RequestMapping("/board")
public class BoardInsertController {

	@RequestMapping(value = "/form.do", method = RequestMethod.GET)
	public String boardForm() {
		return "board/form";
	}
	
	@RequestMapping(value = "/insert.do", method = RequestMethod.POST)
	public String boardInsert(BoardVO boardVO) {
		String goPage = ""; // 페이지 정보를 담을 변수
		
		// 클라이언트에서 넘어온 제목, 내용에 대한 데이터가 공백 또는 null로 들어오진 않는다.
		// 하지만, 데이터가 혹시나 검증되지 않고 서버로 넘어올 시 에러가 발생할 확률이 가장 높기 때문에
		// 서버에서도 데이터에 대한 입력값 검증에 대한 필터를 걸어준다.
		// 클라이언트에서 1번 거르고, 서버에서 한 번 더 거른다.
		
		Map<String, String> errors = new HashMap<String, String>();
		//if(boardVO.getBoTitle().equals("") && boardVO.getBoTitle() == null) {
		if(StringUtils.isBlank(boardVO.getBoTitle())) {
			errors.put("boTitle", "제목을 입력해 주세요!");
		}
		
		if(StringUtils.isBlank(boardVO.getBoContent())) {
			errors.put("boContent", "내용을 입력해 주세요!");
		}
	}
	
}

[ServiceResult.java]

package kr.or.ddit;

public enum ServiceResult {

	OK, FAILED, EXIST, NOTEXIST
	
}

[IBoardService.java]

package kr.or.ddit.board.service;

import kr.or.ddit.ServiceResult;
import kr.or.ddit.vo.BoardVO;

public interface IBoardService {

	public ServiceResult insertBoard(BoardVO boardVO);
	
}

[BoardServiceImpl.java]

package kr.or.ddit.board.service;

import javax.inject.Inject;

import org.springframework.stereotype.Service;

import kr.or.ddit.ServiceResult;
import kr.or.ddit.board.dao.IBoardDAO;
import kr.or.ddit.vo.BoardVO;

@Service
public class BoardServiceImpl implements IBoardService {

	@Inject
	private IBoardDAO boardDao;
	
	@Override
	public ServiceResult insertBoard(BoardVO boardVO) {
		ServiceResult result = null;
		int status = boardDao.insertBoard(boardVO);
		if(status > 0) { // 성공
			result = ServiceResult.OK;
		}else { // 실패
			result = ServiceResult.FAILED;
		}
		return result;
	}

}

[IBoardDAO.java]

package kr.or.ddit.board.dao;

import kr.or.ddit.vo.BoardVO;

public interface IBoardDAO {

	public int insertBoard(BoardVO boardVO);
	
}

[pom.xml]

<!-- 데이터베이스 설정 -->
		
		<!--  
			mybatis는 xml로 쿼리를 작성하게 해주는 라이브러리
			쿼리를 문자열로 코딩하지 않고 xml을 사용해서 관리하게 해준다.
		-->
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis</artifactId>
			<version>3.5.4</version>
		</dependency>
		
		<!--  
			mybatis-spring은 스프링과 mybatis를 연동하게 해주는 라이브러리
		-->
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis-spring</artifactId>
			<version>2.0.4</version>
		</dependency>
		
		<!--  
			jdbc는 자바에서 데이터베이스에 접속하기 위한 API
			spring-jdbc는 스프링에서 jdbc를 통해 데이터베이스와 연결할 수 있게 해준다.
		-->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-jdbc</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>
		
		<!--  
			dbcp2는 데이터베이스 커넥션 풀
			데이터베이스 서버와 웹 서버는 서로 다른 프로그램이고,
			실무에서는 전혀 다른 컴퓨터에 설치되어 있을 가능성이 높다.
			서로 다른 컴퓨터와 프로그램이 통신을 하기 위해서는 서로 연결을 맺는 과정이 필요
			미리 데이터베이스와 연동하기 위한 길을 만들어놓는 라이브러리
			요즘은 dbcp2보다 hikaricp를 자주 사용하기도 함
		-->
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-dbcp2</artifactId>
			<version>2.7.0</version>
		</dependency>
		
		<!--  
			로깅을 위한 라이브러리
			데이터베이스에 연동하는 쿼리를 콘솔이나 파일 로그로 볼 수 있게 해준다.
		-->
		<dependency>
			<groupId>org.bgee.log4jdbc-log4j2</groupId>
			<artifactId>log4jdbc-log4j2-jdbc4</artifactId>
			<version>1.16</version>
		</dependency>
		
		<!-- oracle 데이터베이스 연동 라이브러리 -->
		<dependency>
			<groupId>com.oracle.database.jdbc</groupId>
			<artifactId>ojdbc8</artifactId>
			<version>21.1.0.0</version>
		</dependency>
		
		<!-- 데이터베이스 설정 End -->

[root-context.xml]

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
	
	<!-- Root Context: defines shared resources visible to all other web components -->
	
	<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
		<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
		<property name="url" value="jdbc:oracle:thin:@localhost:1521:xe" />
		<property name="username" value="yse" />
		<property name="password" value="java" />
	</bean>
	
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<property name="mapperLocations" value="classpath:/sqlmap/**/*_SQL.xml" />
		<property name="configLocation" value="/WEB-INF/mybatisAlias/mybatisAlias.xml" />
	</bean>
	
	<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
		<constructor-arg index="0" ref="sqlSessionFactory" />
	</bean>
		
</beans>

https://mybatis.org/mybatis-3/getting-started.html

 

mybatis – MyBatis 3 | Getting started

It's very important to understand the various scopes and lifecycles classes we've discussed so far. Using them incorrectly can cause severe concurrency problems. Dependency Injection frameworks can create thread safe, transactional SqlSessions and mappers

mybatis.org

[blank_SQL.xml]

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="Blank"></mapper>

[mybatisAlias.xml]

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

	<settings>
		<setting name="mapUnderscoreToCamelCase" value="true" />
	</settings>
	
	<typeAliases>
		<typeAlias type="kr.or.ddit.vo.BoardVO" alias="boardVO" />
	</typeAliases>

</configuration>

[web.xml]

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1" xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_3_1.xsd">

	<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/spring/root-context.xml</param-value>
	</context-param>
	
	<!-- Creates the Spring Container shared by all Servlets and Filters -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

	<!-- Processes application requests -->
	<servlet>
		<servlet-name>appServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
		
	<servlet-mapping>
		<servlet-name>appServlet</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>
	
	<!--  
		브라우저에서 보내는 요청(request)과 응답(response)을 모두 UTF-8로 고정하기 위해 인코딩 필터를 설정한다.
	-->
	<filter>
		<filter-name>encordingFilter</filter-name>
		<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
		<init-param>
			<param-name>encoding</param-name>
			<param-value>UTF-8</param-value>
		</init-param>
		<init-param>
			<param-name>forceEncoding</param-name>
			<param-value>true</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>encordingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

</web-app>

[BoardDAOImpl.java]

package kr.or.ddit.board.dao;

import javax.inject.Inject;

import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.stereotype.Repository;

import kr.or.ddit.vo.BoardVO;

@Repository
public class BoardDAOImpl implements IBoardDAO {

	@Inject
	private SqlSessionTemplate sqlSession;
	
	@Override
	public int insertBoard(BoardVO boardVO) {
		return sqlSession.insert("Board.insertBoard", boardVO);
	}

}

[board_SQL.xml]

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="Board">

	<insert id="insertBoard" parameterType="boardVO" useGeneratedKeys="true">
		<selectKey keyProperty="boNo" resultType="int" order="BEFORE">
			select seq_board.nextval from dual
		</selectKey>
		insert into board(
			bono, botitle, bocontent, bowriter, bodate
		)values(
			#{boNo}, #{boTitle}, #{boContent}, #{boWriter}, sysdate
		)
	</insert>

</mapper>

-- SPRING 1
-- BOARD 테이블 생성
create table board(
    bono number not null,
    botitle varchar2(300) not null,
    bocontent varchar2(3000) not null,
    bowriter varchar2(150) not null,
    bodate date not null,
    bohit number(8) default 0 null,
    constraint pk_board primary key(bono)
);

-- BOARD 테이블 시퀀스 생성
CREATE SEQUENCE seq_board
INCREMENT by 1 
start with 1 
nocache;

commit;

select * from board;


[BoardInsertController.java]

package kr.or.ddit.board.web;

import java.util.HashMap;
import java.util.Map;

import javax.inject.Inject;

import org.apache.commons.lang3.StringUtils;
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 kr.or.ddit.ServiceResult;
import kr.or.ddit.board.service.IBoardService;
import kr.or.ddit.vo.BoardVO;

@Controller
@RequestMapping("/board")
public class BoardInsertController {
	
	@Inject
	private IBoardService boardService;

	@RequestMapping(value = "/form.do", method = RequestMethod.GET)
	public String boardForm() {
		return "board/form";
	}
	
	@RequestMapping(value = "/insert.do", method = RequestMethod.POST)
	public String boardInsert(BoardVO boardVO, Model model) {
		String goPage = ""; // 페이지 정보를 담을 변수
		
		// 클라이언트에서 넘어온 제목, 내용에 대한 데이터가 공백 또는 null로 들어오진 않는다.
		// 하지만, 데이터가 혹시나 검증되지 않고 서버로 넘어올 시 에러가 발생할 확률이 가장 높기 때문에
		// 서버에서도 데이터에 대한 입력값 검증에 대한 필터를 걸어준다.
		// 클라이언트에서 1번 거르고, 서버에서 한 번 더 거른다.
		
		Map<String, String> errors = new HashMap<String, String>();
		//if(boardVO.getBoTitle().equals("") && boardVO.getBoTitle() == null) {
		if(StringUtils.isBlank(boardVO.getBoTitle())) {
			errors.put("boTitle", "제목을 입력해 주세요!");
		}
		
		if(StringUtils.isBlank(boardVO.getBoContent())) {
			errors.put("boContent", "내용을 입력해 주세요!");
		}
		
		if(errors.size() > 0) { // 에러가 있음
			// 다시 클라이언트로 내가 입력했던 제목, 내용을 돌려준다.
			// 에러 정보도 전달
			// 이 때, 페이지는 어디로?
			model.addAttribute("boardVO", boardVO);
			model.addAttribute("errors", errors);
			goPage = "board/form"; // 포워딩
		}else { // 에러가 없는 정상적인 데이터가 입력되었다
			boardVO.setBoWriter("a001");
			ServiceResult result = boardService.insertBoard(boardVO);
			if(result.equals(ServiceResult.OK)) {
				goPage = "redirect:/board/detail.do?boNo=" + boardVO.getBoNo();
			}else {
				model.addAttribute("boardVO", boardVO);
				model.addAttribute("message", "서버 에러, 다시 시도해주세요!");
				goPage = "board/form"; // 포워딩
			}
		}
		
		return goPage;
	}
	
}

[form.jsp]

                            <form method="post" action="insert.do" id="boardForm" name="boardForm" class="form-horizontal">
                                <div class="form-group row">
                                    <label class="col-sm-2 control-label">제목</label>
                                    <div class="col-sm-10">
                                        <input id="boTitle" name="boTitle" type="text" class="form-control" value="${boardVO.boTitle }" placeholder="subject">
                                    </div>
                                    <font color="red" style="font-size: 12px;">${errors.boTitle }</font>
                                </div>
                                <div class="form-group row mt-4">
                                    <label class="col-sm-2 control-label">내용</label>
                                    <div class="col-sm-10">
                                        <textarea id="boContent" name="boContent" cols="50" rows="5" class="form-control" placeholder="content">${boardVO.boContent }</textarea>
                                    </div>
                                    <font color="red" style="font-size: 12px;">${errors.boContent }</font>
                                </div>
                                <div class="form-group row mt-4">
                                    <div class="col-sm-offset-2 col-sm-12 ">
                                        <input type="button" value="등록" class="btn btn-primary float-right" id="addBtn">
                                        <input type="button" value="취소" class="btn btn-danger float-right" id="cancelBtn">
                                        <input type="button" value="목록" class="btn btn-success float-right" id="listBtn">
                                    </div>
                                </div>
                            </form>

- http://localhost/board/form.do

- http://localhost/board/detail.do?boNo=1


[BoardRetreiveController.java]

package kr.or.ddit.board.web;

import javax.inject.Inject;

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 kr.or.ddit.board.service.IBoardService;
import kr.or.ddit.vo.BoardVO;

@Controller
@RequestMapping("/board")
public class BoardRetreiveController {

	@Inject
	private IBoardService boardService;
	
	@RequestMapping(value = "/list.do", method = RequestMethod.GET)
	public String boardList() {
		return "board/list";
	}
	
	@RequestMapping(value = "detail.do", method = RequestMethod.GET)
	public String boardDetail(int boNo, Model model) {
		BoardVO boardVO = boardService.selectBoard(boNo);
		model.addAttribute("board", boardVO);
		return "board/view";
	}
	
}

[IBoardService.java]

package kr.or.ddit.board.service;

import kr.or.ddit.ServiceResult;
import kr.or.ddit.vo.BoardVO;

public interface IBoardService {

	public ServiceResult insertBoard(BoardVO boardVO);
	public BoardVO selectBoard(int boNo);
	
}

[BoardServiceImpl.java]

package kr.or.ddit.board.service;

import javax.inject.Inject;

import org.springframework.stereotype.Service;

import kr.or.ddit.ServiceResult;
import kr.or.ddit.board.dao.IBoardDAO;
import kr.or.ddit.vo.BoardVO;

@Service
public class BoardServiceImpl implements IBoardService {

	@Inject
	private IBoardDAO boardDao;
	
	@Override
	public ServiceResult insertBoard(BoardVO boardVO) {
		ServiceResult result = null;
		int status = boardDao.insertBoard(boardVO);
		if(status > 0) { // 성공
			result = ServiceResult.OK;
		}else { // 실패
			result = ServiceResult.FAILED;
		}
		return result;
	}
	
	@Override
	public BoardVO selectBoard(int boNo) {
		// 조회수 증가
		boardDao.incrementHit(boNo);
		return boardDao.selectBoard(boNo);
	}

}

[IBoardDAO.java]

package kr.or.ddit.board.dao;

import kr.or.ddit.vo.BoardVO;

public interface IBoardDAO {

	public int insertBoard(BoardVO boardVO);
	public BoardVO selectBoard(int boNo);
	public void incrementHit(int boNo);
	
}

[BoardDAOImpl.java]

package kr.or.ddit.board.dao;

import javax.inject.Inject;

import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.stereotype.Repository;

import kr.or.ddit.vo.BoardVO;

@Repository
public class BoardDAOImpl implements IBoardDAO {

	@Inject
	private SqlSessionTemplate sqlSession;
	
	@Override
	public int insertBoard(BoardVO boardVO) {
		return sqlSession.insert("Board.insertBoard", boardVO);
	}
	
	@Override
	public BoardVO selectBoard(int boNo) {
		return sqlSession.selectOne("Board.selectBoard", boNo);
	}
	
	@Override
	public void incrementHit(int boNo) {
		sqlSession.update("Board.incrementHit", boNo);
	}

}

[board_SQL.xml]

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="Board">

	<insert id="insertBoard" parameterType="boardVO" useGeneratedKeys="true">
		<selectKey keyProperty="boNo" resultType="int" order="BEFORE">
			select seq_board.nextval from dual
		</selectKey>
		insert into board(
			bono, botitle, bocontent, bowriter, bodate
		)values(
			#{boNo}, #{boTitle}, #{boContent}, #{boWriter}, sysdate
		)
	</insert>
	
	<update id="incrementHit" parameterType="int">
		update board 
		set 
			bohit = bohit + 1 
		where bono = #{boNo}
	</update>
	
	<select id="selectBoard" parameterType="int" resultType="boardVO">
		select 
			bono, botitle, bocontent, bowriter, bodate, bohit
		from board 
		where bono = #{boNo}
	</select>

</mapper>

[view.jsp]

<%@ page contentType="text/html; charset=utf-8"%>
<html>
<head>
<link href="${pageContext.request.contextPath }/resources/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="${pageContext.request.contextPath }/resources/css/headers.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<title>일반게시판 등록/수정</title>
</head>
<style>
.bi {
	vertical-align: -.125em;
	fill: currentColor;
}
</style>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
  <symbol id="bootstrap" viewBox="0 0 118 94">
    <title>Bootstrap</title>
    <path fill-rule="evenodd" clip-rule="evenodd" d="M24.509 0c-6.733 0-11.715 5.893-11.492 12.284.214 6.14-.064 14.092-2.066 20.577C8.943 39.365 5.547 43.485 0 44.014v5.972c5.547.529 8.943 4.649 10.951 11.153 2.002 6.485 2.28 14.437 2.066 20.577C12.794 88.106 17.776 94 24.51 94H93.5c6.733 0 11.714-5.893 11.491-12.284-.214-6.14.064-14.092 2.066-20.577 2.009-6.504 5.396-10.624 10.943-11.153v-5.972c-5.547-.529-8.934-4.649-10.943-11.153-2.002-6.484-2.28-14.437-2.066-20.577C105.214 5.894 100.233 0 93.5 0H24.508zM80 57.863C80 66.663 73.436 72 62.543 72H44a2 2 0 01-2-2V24a2 2 0 012-2h18.437c9.083 0 15.044 4.92 15.044 12.474 0 5.302-4.01 10.049-9.119 10.88v.277C75.317 46.394 80 51.21 80 57.863zM60.521 28.34H49.948v14.934h8.905c6.884 0 10.68-2.772 10.68-7.727 0-4.643-3.264-7.207-9.012-7.207zM49.948 49.2v16.458H60.91c7.167 0 10.964-2.876 10.964-8.281 0-5.406-3.903-8.178-11.425-8.178H49.948z"></path>
  </symbol>
  <symbol id="home" viewBox="0 0 16 16">
    <path d="M8.354 1.146a.5.5 0 0 0-.708 0l-6 6A.5.5 0 0 0 1.5 7.5v7a.5.5 0 0 0 .5.5h4.5a.5.5 0 0 0 .5-.5v-4h2v4a.5.5 0 0 0 .5.5H14a.5.5 0 0 0 .5-.5v-7a.5.5 0 0 0-.146-.354L13 5.793V2.5a.5.5 0 0 0-.5-.5h-1a.5.5 0 0 0-.5.5v1.293L8.354 1.146zM2.5 14V7.707l5.5-5.5 5.5 5.5V14H10v-4a.5.5 0 0 0-.5-.5h-3a.5.5 0 0 0-.5.5v4H2.5z"/>
  </symbol>
  <symbol id="grid" viewBox="0 0 16 16">
    <path d="M1 2.5A1.5 1.5 0 0 1 2.5 1h3A1.5 1.5 0 0 1 7 2.5v3A1.5 1.5 0 0 1 5.5 7h-3A1.5 1.5 0 0 1 1 5.5v-3zM2.5 2a.5.5 0 0 0-.5.5v3a.5.5 0 0 0 .5.5h3a.5.5 0 0 0 .5-.5v-3a.5.5 0 0 0-.5-.5h-3zm6.5.5A1.5 1.5 0 0 1 10.5 1h3A1.5 1.5 0 0 1 15 2.5v3A1.5 1.5 0 0 1 13.5 7h-3A1.5 1.5 0 0 1 9 5.5v-3zm1.5-.5a.5.5 0 0 0-.5.5v3a.5.5 0 0 0 .5.5h3a.5.5 0 0 0 .5-.5v-3a.5.5 0 0 0-.5-.5h-3zM1 10.5A1.5 1.5 0 0 1 2.5 9h3A1.5 1.5 0 0 1 7 10.5v3A1.5 1.5 0 0 1 5.5 15h-3A1.5 1.5 0 0 1 1 13.5v-3zm1.5-.5a.5.5 0 0 0-.5.5v3a.5.5 0 0 0 .5.5h3a.5.5 0 0 0 .5-.5v-3a.5.5 0 0 0-.5-.5h-3zm6.5.5A1.5 1.5 0 0 1 10.5 9h3a1.5 1.5 0 0 1 1.5 1.5v3a1.5 1.5 0 0 1-1.5 1.5h-3A1.5 1.5 0 0 1 9 13.5v-3zm1.5-.5a.5.5 0 0 0-.5.5v3a.5.5 0 0 0 .5.5h3a.5.5 0 0 0 .5-.5v-3a.5.5 0 0 0-.5-.5h-3z"/>
  </symbol>
</svg>
<main>
	<header>
		<div class="px-3 py-2 text-bg-dark">
			<div class="container">
				<div class="d-flex flex-wrap align-items-center justify-content-center justify-content-lg-start">
					<a href="/" class="d-flex align-items-center my-2 my-lg-0 me-lg-auto text-white text-decoration-none">
						<svg class="bi me-2" width="40" height="32" role="img" aria-label="Bootstrap">
							<use xlink:href="#bootstrap" />
						</svg>
					</a>
					<ul class="nav col-12 col-lg-auto my-2 justify-content-center my-md-0 text-small">
						<li>
							<a href="/main.do" class="nav-link text-white"> 
								<svg class="bi d-block mx-auto mb-1" width="24" height="24">
									<use xlink:href="#home" />
								</svg> Home
							</a>
						</li>
						<li>
							<a href="/board/list.do" class="nav-link text-white"> 
								<svg class="bi d-block mx-auto mb-1" width="24" height="24">
									<use xlink:href="#grid" />
								</svg> 일반게시판
							</a>
						</li>
						<li>
							<a href="/notice/list.do" class="nav-link text-white"> 
								<svg class="bi d-block mx-auto mb-1" width="24" height="24">
									<use xlink:href="#grid" />
								</svg> 공지사항게시판
							</a>
						</li>
						<li>
							<a href="/free/list.do" class="nav-link text-white"> 
								<svg class="bi d-block mx-auto mb-1" width="24" height="24">
									<use xlink:href="#grid" />
								</svg> 자유게시판
							</a>
						</li>
					</ul>
				</div>
			</div>
		</div>
	</header>

	<div class="position-relative overflow-hidden p-3 p-md-8 m-md-8 text-center bg-white">
		<div class="col-md-8 p-lg-8 mx-auto my-5">
			<h4 class="display-4 fw-normal">일반게시판</h4>
			<p class="lead fw-normal">일반게시판 CRUD를 작성해주세요.</p>
		</div>
		<div class="product-device shadow-sm d-none d-md-block"></div>
		<div
			class="product-device product-device-2 shadow-sm d-none d-md-block"></div>
	</div>

	<div class="container">
		<div class="row">
			<div class="col-md-12">
				<div class="">
					<div class="card-header">
						<h3 class="card-title">${board.boTitle }</h3>
						<div class="card-tools mt-1">
							${board.boWriter } ${board.boDate } ${board.boHit }
						</div>
					</div>
					<div class="card-body">
						<div class="form-group row mt-1">
							<div class="col-sm-12">${board.boContent }</div>
						</div>
					</div>
					<div class="card-footer">
						<button type="button" class="btn btn-primary" id="listBtn">목록</button>
						<button type="button" class="btn btn-info" id="modifyBtn">수정</button>
						<button type="button" class="btn btn-danger" id="delBtn">삭제</button>
					</div>
					<form action="/board/update.do" method="get" id="boardForm" name="boardForm">
						<input type="hidden" name="boNo" value="${board.boNo }" />
					</form>
				</div>
			</div>
			<div class="col-md-12"><br/><br/><br/></div>
		</div>
	</div>
</main>
</body>
<script type="text/javascript">
	$(function(){
		var boardForm = $("#boardForm");
		var listBtn = $("#listBtn");
		var modifyBtn = $("#modifyBtn");
		var delBtn = $("#delBtn");
		
		// 목록 버튼 이벤트
		listBtn.on("click", function(){
			location.href = "/board/list.do"
		});
		
		// 수정 버튼 이벤트
		modifyBtn.on("click", function(){
			boardForm.submit();
		});
		
		// 삭제 버튼 이벤트
		delBtn.on("click", function(){
			if(confirm("정말로 삭제하시겠습니까?")){
				boardForm.attr("action", "/board/delete.do");
				boardForm.attr("method", "post");
				boardForm.submit();
			}
		});
	});
</script>
</html>

- http://localhost/board/detail.do?boNo=2

조회수도 잘 증가하고 있다


ckeditor4

[form.jsp]

<%@ page contentType="text/html; charset=utf-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page contentType="text/html; charset=utf-8"%>
<html>

<head>
    <link href="${pageContext.request.contextPath }/resources/css/bootstrap.min.css" rel="stylesheet">
    <link rel="stylesheet" href="${pageContext.request.contextPath }/resources/css/headers.css">
	<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
    <script type="text/javascript" src="${pageContext.request.contextPath }/resources/ckeditor/ckeditor.js"></script>
    <title>일반게시판 등록/수정</title>
</head>
<style>
    .bi {
        vertical-align: -.125em;
        fill: currentColor;
    }
</style>
<body>
    <svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
        <symbol id="bootstrap" viewBox="0 0 118 94">
            <title>Bootstrap</title>
            <path fill-rule="evenodd" clip-rule="evenodd" d="M24.509 0c-6.733 0-11.715 5.893-11.492 12.284.214 6.14-.064 14.092-2.066 20.577C8.943 39.365 5.547 43.485 0 44.014v5.972c5.547.529 8.943 4.649 10.951 11.153 2.002 6.485 2.28 14.437 2.066 20.577C12.794 88.106 17.776 94 24.51 94H93.5c6.733 0 11.714-5.893 11.491-12.284-.214-6.14.064-14.092 2.066-20.577 2.009-6.504 5.396-10.624 10.943-11.153v-5.972c-5.547-.529-8.934-4.649-10.943-11.153-2.002-6.484-2.28-14.437-2.066-20.577C105.214 5.894 100.233 0 93.5 0H24.508zM80 57.863C80 66.663 73.436 72 62.543 72H44a2 2 0 01-2-2V24a2 2 0 012-2h18.437c9.083 0 15.044 4.92 15.044 12.474 0 5.302-4.01 10.049-9.119 10.88v.277C75.317 46.394 80 51.21 80 57.863zM60.521 28.34H49.948v14.934h8.905c6.884 0 10.68-2.772 10.68-7.727 0-4.643-3.264-7.207-9.012-7.207zM49.948 49.2v16.458H60.91c7.167 0 10.964-2.876 10.964-8.281 0-5.406-3.903-8.178-11.425-8.178H49.948z"></path>
        </symbol>
        <symbol id="home" viewBox="0 0 16 16">
            <path d="M8.354 1.146a.5.5 0 0 0-.708 0l-6 6A.5.5 0 0 0 1.5 7.5v7a.5.5 0 0 0 .5.5h4.5a.5.5 0 0 0 .5-.5v-4h2v4a.5.5 0 0 0 .5.5H14a.5.5 0 0 0 .5-.5v-7a.5.5 0 0 0-.146-.354L13 5.793V2.5a.5.5 0 0 0-.5-.5h-1a.5.5 0 0 0-.5.5v1.293L8.354 1.146zM2.5 14V7.707l5.5-5.5 5.5 5.5V14H10v-4a.5.5 0 0 0-.5-.5h-3a.5.5 0 0 0-.5.5v4H2.5z" />
        </symbol>
        <symbol id="grid" viewBox="0 0 16 16">
            <path d="M1 2.5A1.5 1.5 0 0 1 2.5 1h3A1.5 1.5 0 0 1 7 2.5v3A1.5 1.5 0 0 1 5.5 7h-3A1.5 1.5 0 0 1 1 5.5v-3zM2.5 2a.5.5 0 0 0-.5.5v3a.5.5 0 0 0 .5.5h3a.5.5 0 0 0 .5-.5v-3a.5.5 0 0 0-.5-.5h-3zm6.5.5A1.5 1.5 0 0 1 10.5 1h3A1.5 1.5 0 0 1 15 2.5v3A1.5 1.5 0 0 1 13.5 7h-3A1.5 1.5 0 0 1 9 5.5v-3zm1.5-.5a.5.5 0 0 0-.5.5v3a.5.5 0 0 0 .5.5h3a.5.5 0 0 0 .5-.5v-3a.5.5 0 0 0-.5-.5h-3zM1 10.5A1.5 1.5 0 0 1 2.5 9h3A1.5 1.5 0 0 1 7 10.5v3A1.5 1.5 0 0 1 5.5 15h-3A1.5 1.5 0 0 1 1 13.5v-3zm1.5-.5a.5.5 0 0 0-.5.5v3a.5.5 0 0 0 .5.5h3a.5.5 0 0 0 .5-.5v-3a.5.5 0 0 0-.5-.5h-3zm6.5.5A1.5 1.5 0 0 1 10.5 9h3a1.5 1.5 0 0 1 1.5 1.5v3a1.5 1.5 0 0 1-1.5 1.5h-3A1.5 1.5 0 0 1 9 13.5v-3zm1.5-.5a.5.5 0 0 0-.5.5v3a.5.5 0 0 0 .5.5h3a.5.5 0 0 0 .5-.5v-3a.5.5 0 0 0-.5-.5h-3z" />
        </symbol>
    </svg>
    <main>
        <header>
            <div class="px-3 py-2 text-bg-dark">
                <div class="container">
                    <div class="d-flex flex-wrap align-items-center justify-content-center justify-content-lg-start">
                        <a href="/" class="d-flex align-items-center my-2 my-lg-0 me-lg-auto text-white text-decoration-none">
                            <svg class="bi me-2" width="40" height="32" role="img" aria-label="Bootstrap">
                                <use xlink:href="#bootstrap" />
                            </svg>
                        </a>
                        <ul class="nav col-12 col-lg-auto my-2 justify-content-center my-md-0 text-small">
                            <li>
                                <a href="/main.do" class="nav-link text-white">
                                    <svg class="bi d-block mx-auto mb-1" width="24" height="24">
                                        <use xlink:href="#home" />
                                    </svg> Home
                                </a>
                            </li>
                            <li>
                                <a href="/board/list.do" class="nav-link text-white">
                                    <svg class="bi d-block mx-auto mb-1" width="24" height="24">
                                        <use xlink:href="#grid" />
                                    </svg> 일반게시판
                                </a>
                            </li>
                            <li>
                                <a href="/notice/list.do" class="nav-link text-white">
                                    <svg class="bi d-block mx-auto mb-1" width="24" height="24">
                                        <use xlink:href="#grid" />
                                    </svg> 공지사항게시판
                                </a>
                            </li>
                            <li>
                                <a href="/free/list.do" class="nav-link text-white">
                                    <svg class="bi d-block mx-auto mb-1" width="24" height="24">
                                        <use xlink:href="#grid" />
                                    </svg> 자유게시판
                                </a>
                            </li>
                        </ul>
                    </div>
                </div>
            </div>
        </header>

        <div class="position-relative overflow-hidden p-3 p-md-8 m-md-8 text-center bg-white">
            <div class="col-md-8 p-lg-8 mx-auto my-5">
                <h4 class="display-4 fw-normal">일반게시판</h4>
                <p class="lead fw-normal">일반게시판 CRUD를 작성해주세요.</p>
            </div>
            <div class="product-device shadow-sm d-none d-md-block"></div>
            <div class="product-device product-device-2 shadow-sm d-none d-md-block"></div>
        </div>

        <div class="container">
            <div class="row">
                <div class="col-md-12">
                    <div class="">
                        <div class="card-body">
                            <form method="post" action="insert.do" id="boardForm" name="boardForm" class="form-horizontal">
                                <div class="form-group row">
                                    <label class="col-sm-2 control-label">제목</label>
                                    <div class="col-sm-10">
                                        <input id="boTitle" name="boTitle" type="text" class="form-control" value="${boardVO.boTitle }" placeholder="subject">
                                    </div>
                                    <font color="red" style="font-size: 12px;">${errors.boTitle }</font>
                                </div>
                                <div class="form-group row mt-4">
                                    <label class="col-sm-2 control-label">내용</label>
                                    <div class="col-sm-10">
                                        <textarea id="boContent" name="boContent" cols="50" rows="5" class="form-control" placeholder="content">${boardVO.boContent }</textarea>
                                    </div>
                                    <font color="red" style="font-size: 12px;">${errors.boContent }</font>
                                </div>
                                <div class="form-group row mt-4">
                                    <div class="col-sm-offset-2 col-sm-12 ">
                                        <input type="button" value="등록" class="btn btn-primary float-right" id="addBtn">
                                        <input type="button" value="취소" class="btn btn-danger float-right" id="cancelBtn">
                                        <input type="button" value="목록" class="btn btn-success float-right" id="listBtn">
                                    </div>
                                </div>
                            </form>
                        </div>
                    </div>
                </div>
                <div class="col-md-12"><br /><br /><br /></div>
            </div>
        </div>
    </main>
</body>
<script type="text/javascript">
	$(function(){
		CKEDITOR.replace("boContent"); // CKEDITOR를 textarea에 등록
		
		var addBtn = $("#addBtn"); // 등록 버튼
		var cancelBtn = $("#cancelBtn"); // 취소 버튼
		var listBtn = $("#listBtn"); // 목록 버튼
		var boTitle = $("#boTitle");
		var boContent = $("#boContent");
		var boardForm = $("#boardForm"); // 등록 form
		
		// 등록 버튼 이벤트
		addBtn.on("click", function(){
			var title = boTitle.val(); // 제목 데이터
			
			// 일반적인 데이터를 가져올 때 사용하는 방법(textarea 사용시)
			//var content = boContent.val(); // 내용 데이터
			
			// CKEDITOR를 사용해서 데이터를 가져와야 할 때 사용하는 방법(editor 사용 시)
			var content = CKEDITOR.instances.boContent.getData(); // 내용 데이터
			
			// 제목을 입력하지 않았을 때 발생할 이벤트
			if(!title) {
				alert("제목을 입력해주세요!");
				boTitle.focus();
				return false;
			}
			
			// 내용을 입력하지 않았을 때 발생할 이벤트
			if(!content) {
				alert("내용을 입력해주세요!");
				boContent.focus();
				return false;
			}
			
			boardForm.submit();
		});
		
		// 취소 버튼 이벤트
		cancelBtn.on("click", function(){
			
		});
		
		// 목록 버튼 이벤트
		listBtn.on("click", function(){
			location.href = "/board/list.do";
		});
	});
</script>
</html>

- http://localhost/board/form.do

- http://localhost/board/detail.do?boNo=3


[pom.xml]

		<!--  
			자바빈 클래스(VO)의 getter/setter 메소드, toString 자동처리
			log.info()의 메소드로 sysout 대신 로그를 console에 출력할 수 있게 해준다.
		-->
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<version>1.18.22</version>
		</dependency>
	
		<!-- Test -->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.7</version>
			<scope>test</scope>
		</dependency>        
	</dependencies>

오른쪽 마우스 클릭 > Run as > Java Application 돌리면 나옴

[BoardVO.java]

package kr.or.ddit.vo;

import lombok.Data;

@Data
public class BoardVO {

	private int boNo; // 일반 게시판 번호
	private String boTitle; // 일반 게시판 제목
	private String boWriter; // 일반 게시판 작성자
	private String boContent; // 일반 게시판 내용
	private String boDate; // 일반 게시판 작성일
	private int boHit; // 일반 게시판 조회수
	
}

- 멤버 필드에 노란색 밑줄이 있으면 getter, setter를 임시로 설정해 주어야 한다. 적용되는 데 시간이 걸림


'대덕인재개발원_웹기반 애플리케이션' 카테고리의 다른 글

231121_SPRING 1 (5-2) - 자유게시판 과제  (1) 2023.11.21
231121_SPRING 1 (5-1)  (1) 2023.11.21
231117_SPRING 1 (3)  (0) 2023.11.17
231116_SPRING 1 (2)  (0) 2023.11.16
231115_SPRING 1 (1)  (0) 2023.11.15