보고잇냥 2022. 8. 7. 18:32

★ 결과

   ■ 게시판 자세히보기

   ■ 게시판 생성하기

   ■ 게시판 수정하기

   ■ 게시판 삭제하기

★ 사전설정

 - 개발환경: '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>

 

※ 제대로 넣는다면 아래와같이 됩니다.