https://tech.kakaopay.com/post/mock-test-code/

1. 빌드 새로하기

프로젝트 우클릭 -> build module ''

 

2. 캐시 삭제

상위 File 탭 -> Invalidate Cache ~ 클릭

 

3. .idea 파일 삭제
해당 프로젝트 루트에 숨겨진 파일로 `.idea` 파일이 존재한다.

해당 파일을 삭제하고, intellij를 다시 열면 새롭게 프로젝트를 불러온다.

1. CRUD URI

method uri 설명
GET /board/list/{page} 게시판 목록 조회
POST /board/write 게시판 글 등록
GET /board/detail/{id} 게시판 상세 보기
POST /board/detail/file 파일 다운로드
POST /board/update/{id} 게시판 글 수정
DELETE /board/delete/{id} 게시판 글 삭제
DELETE /board/delete/file/{save_file_name} 파일 삭제
POST /board/write/reply/{id} 댓글 등록
DELETE /board/delete/reply/{reply_id} 댓글 삭제

 

 

2. Controller 작성

restful하게 작성하였습니다.

 

2-1) 게시판 목록 조회

	/** 게시판 목록 조회 */
	@RequestMapping(value="/list/{page}", method=RequestMethod.GET)
	@ResponseBody
	public Map<String, Object> getBoardList(@PathVariable int page, HttpServletRequest request, HttpServletResponse response, PagingVO pagingVO) throws Exception {
		Util util = new Util();

		Paging pageMaker = new Paging();
		pagingVO.setPage(page);

		pageMaker.setPagingVO(pagingVO);
		pageMaker.setTotalCount(boardService.getBoardCount());
		
		List<Map<String,Object>> board = boardService.getBoardList(pagingVO);
		
		Map<String, Object> data = new HashMap<String, Object>();
		data.put("board", board);
		data.put("total_count", pageMaker.getTotalCount());
		data.put("prev", pageMaker.isPrev());
		data.put("next", pageMaker.isNext());
		data.put("start_page", pageMaker.getStartPage());
		data.put("end_page", pageMaker.getEndPage());
		data.put("page", pagingVO.getPage());
		
		Map<String, Object> output = new HashMap<String, Object>();
		
		output = util.successTrue("getBoardList success!", data);
	
		return output;
	}

16번 라인 : 게시판 목록에 보여줄 데이터들(게시글 제목, 작성자, 작성일, 조회수)

17번 라인 : 총 게시물 수

18번-22번 라인 : 페이징 처리를 위한 번호

 

결과보기

페이지당 게시물 수를 10개로 했기 때문에 board 리스트에 데이터가 10개가 들어가 있습니다.

더보기
{
    "data": {
        "next": true,
        "end_page": 5,
        "start_page": 1,
        "total_count": 60,
        "prev": false,
        "page": 1,
        "board": [
            {
                "reg_date": "2020-01-15 12:38:01",
                "del_flag": "N",
                "hit": 10,
                "mod_date": "2020-01-15 17:59:30",
                "id": 60,
                "writer": "writer_60",
                "title": "title_60",
                "content": "content_60"
            },
            {
                "reg_date": "2020-01-15 12:38:01",
                "del_flag": "N",
                "hit": 0,
                "mod_date": "2020-01-15 12:38:01",
                "id": 59,
                "writer": "writer_59",
                "title": "title_59",
                "content": "content_59"
            },
            {
                "reg_date": "2020-01-15 12:38:01",
                "del_flag": "N",
                "hit": 0,
                "mod_date": "2020-01-15 12:38:01",
                "id": 58,
                "writer": "writer_58",
                "title": "title_58",
                "content": "content_58"
            },
            {
                "reg_date": "2020-01-15 12:38:01",
                "del_flag": "N",
                "hit": 0,
                "mod_date": "2020-01-15 12:38:01",
                "id": 57,
                "writer": "writer_57",
                "title": "title_57",
                "content": "content_57"
            },
            {
                "reg_date": "2020-01-15 12:38:01",
                "del_flag": "N",
                "hit": 0,
                "mod_date": "2020-01-15 12:38:01",
                "id": 56,
                "writer": "writer_56",
                "title": "title_56",
                "content": "content_56"
            },
            {
                "reg_date": "2020-01-15 12:38:01",
                "del_flag": "N",
                "hit": 0,
                "mod_date": "2020-01-15 12:38:01",
                "id": 55,
                "writer": "writer_55",
                "title": "title_55",
                "content": "content_55"
            },
            {
                "reg_date": "2020-01-15 12:38:01",
                "del_flag": "N",
                "hit": 0,
                "mod_date": "2020-01-15 12:38:01",
                "id": 54,
                "writer": "writer_54",
                "title": "title_54",
                "content": "content_54"
            },
            {
                "reg_date": "2020-01-15 12:38:01",
                "del_flag": "N",
                "hit": 0,
                "mod_date": "2020-01-15 12:38:01",
                "id": 53,
                "writer": "writer_53",
                "title": "title_53",
                "content": "content_53"
            },
            {
                "reg_date": "2020-01-15 12:38:01",
                "del_flag": "N",
                "hit": 0,
                "mod_date": "2020-01-15 12:38:01",
                "id": 52,
                "writer": "writer_52",
                "title": "title_52",
                "content": "content_52"
            },
            {
                "reg_date": "2020-01-15 12:38:01",
                "del_flag": "N",
                "hit": 0,
                "mod_date": "2020-01-15 12:38:01",
                "id": 51,
                "writer": "writer_51",
                "title": "title_51",
                "content": "content_51"
            }
        ]
    },
    "success": true,
    "message": "getBoardList success!",
    "error": null
}

 

2-2) 게시판 글 등록

	/** 게시판 등록 */
	@RequestMapping(value="/write", method=RequestMethod.POST)
	@ResponseBody
	public void insertBoard(MultipartHttpServletRequest request
			, @RequestParam String title
			, @RequestParam String writer
			, @RequestParam String content) throws Exception {
		
		BoardVO boardVO = new BoardVO();
		
		boardVO.setTitle(title);
		boardVO.setWriter(writer);
		boardVO.setContent(content);
		
		boardService.insertBoard(boardVO);
		
		Upload upload = new Upload();
		upload.uploadFile(boardService, request);
	}

게시글의 제목, 작성자, 내용, 그리고 첨부파일을 받아 게시판 글을 등록합니다.

(파일 첨부는 따로 포스팅하겠습니다.)

 

2-3) 게시판 글 상세보기

	/** 게시판 상세 */
	@RequestMapping(value="/detail/{id}", method=RequestMethod.GET)
	@ResponseBody
	public Map<String, Object> boardDetail(@PathVariable("id") int id, ReplyVO replyVO) throws Exception {
		Util util = new Util();
		
		BoardVO boardVO = new BoardVO();
		boardVO.setId(id);
		
	    Map<String, Object> detail = boardService.getBoardDetail(boardVO);
	    List<Map<String,Object>> file = boardService.getFileList(boardVO);
	    List<Map<String,Object>> reply = replyService.getReplyList(boardVO);

	    Map<String, Object> data = new HashMap<String, Object>();
	    
	    data.put("detail", detail);
	    data.put("file", file);
		data.put("reply", reply);
		
		Map<String, Object> output = new HashMap<String, Object>();
		
		output = util.successTrue("getBoardList success!", data);
	    
	    return output;
	}

결과보기

더보기
{
    "data": {
        "file": [
            {
                "save_file_name": "1579060044553_게시판테이블.txt",
                "reg_date": 1579060044000,
                "del_flag": "N",
                "extension": ".txt",
                "board_id": 60,
                "mod_date": 1579060044000,
                "id": 1,
                "org_file_name": "게시판테이블.txt",
                "file_size": 1465
            }
        ],
        "detail": {
            "reg_date": "2020-01-15 12:38:01",
            "del_flag": "N",
            "hit": 12,
            "mod_date": "2020-01-20 15:28:42",
            "id": 60,
            "writer": "writer_60",
            "title": "title_60",
            "content": "content_60"
        },
        "reply": [
            {
                "reg_date": "2020-01-15 12:47:49",
                "reply_id": 1,
                "reply_writer": "writer_01",
                "board_id": 60,
                "reply_content": "content_01"
            },
            {
                "reg_date": "2020-01-15 12:47:59",
                "reply_id": 2,
                "reply_writer": "writer_02",
                "board_id": 60,
                "reply_content": "content_02"
            },
            {
                "reg_date": "2020-01-15 12:48:50",
                "reply_id": 3,
                "reply_writer": "writer_03",
                "board_id": 60,
                "reply_content": "content_03"
            }
        ]
    },
    "success": true,
    "message": "getBoardList success!",
    "error": null
}

 

2-4) 게시판 글 수정

	/** 게시판 수정 */
	@RequestMapping(value="/update/{id}", method=RequestMethod.POST)
	@ResponseBody
	public void boardUpdatePost(@PathVariable("id") int id
			, @RequestParam String title
			, @RequestParam String writer
			, @RequestParam String content
			, MultipartHttpServletRequest request) throws Exception {
		
		BoardVO boardVO = new BoardVO();
		
		boardVO.setId(id);
		boardVO.setTitle(title);
		boardVO.setWriter(writer);
		boardVO.setContent(content);
		
		boardService.updateBoard(boardVO);
		
		Upload upload = new Upload();
		upload.uploadFile(boardService, request);
	}

처음에 수정 메소드를 PUT으로 작성하였지만 @RequestParam 과 PUT메소드에 문제가 생겨 POST메소드로 변경했습니다.

참고자료 -> 

 

2-5) 게시판 글 삭제

	/** 게시판 삭제 */
	@RequestMapping(value="/delete/{id}", method=RequestMethod.DELETE)
	@ResponseBody
	public Map<String, Object> boardDelete(@PathVariable int id) throws Exception {
		Util util = new Util();
		
        BoardVO boardVO = new BoardVO();
        boardVO.setId(id);
		boardService.deleteBoard(boardVO);
		
		Map<String, Object> output = new HashMap<String, Object>();
		
		output = util.successTrue("boardDelete success!", null);
		return output;
	}

 

 

3. Service 작성

DB 연동 이외의 부분 처리

	@Inject
	BoardDAO boardDAO;
	
	@Override
	public void insertBoard(BoardVO boardVO) throws Exception {
	    boardDAO.insertBoard(boardVO);
	}

	@Override
	public List<Map<String, Object>> getBoardList(PagingVO pagingVO) throws Exception {
		return boardDAO.getBoardList(pagingVO);
	}

	@Override
	public Map<String, Object> getBoardDetail(BoardVO boardVO) throws Exception {
		boardDAO.updateHit(boardVO);
		return boardDAO.getBoardDetail(boardVO);
		
	}

	@Override
	public void updateBoard(BoardVO boardVO) throws Exception {
		boardDAO.updateBoard(boardVO);
	}

	@Override
	public void deleteBoard(BoardVO boardVO) throws Exception {
		boardDAO.deleteBoard(boardVO);
	}
	
	@Override
	public int getBoardCount() throws Exception {
		return boardDAO.getBoardCount();
	}
	
	@Override
	public int getBoardId() throws Exception {
		return boardDAO.getBoardId();
	}

 

 

4. DAO 작성

	@Inject
	private SqlSession sqlSession;
	
	private static String namespace = "com.seongim.mvc_board.mapper.BoardMapper";

	@Override
	public void insertBoard(BoardVO boardVO) throws Exception {
		sqlSession.insert(namespace + ".insertBoard", boardVO);
	}

	@Override
	public List<Map<String, Object>> getBoardList(PagingVO pagingVO) throws Exception {
		return sqlSession.selectList(namespace + ".getBoardList", pagingVO);
	}

	@Override
	public Map<String, Object> getBoardDetail(BoardVO boardVO) throws Exception {
		return sqlSession.selectOne(namespace + ".getBoardDetail", boardVO);
	}

	@Override
	public void updateBoard(BoardVO boardVO) throws Exception {
		sqlSession.update(namespace + ".updateBoard", boardVO);
	}

	@Override
	public void deleteBoard(BoardVO boardVO) throws Exception {
		sqlSession.update(namespace + ".deleteBoard", boardVO);
	}
	
	@Override
	public void updateHit(BoardVO boardVO) throws Exception {
		sqlSession.update(namespace + ".updateHit", boardVO);
	}
	
	@Override
	public int getBoardCount() throws Exception {
		return sqlSession.selectOne(namespace + ".getBoardCount");
	}
	
	@Override
	public int getBoardId() throws Exception {
		return sqlSession.selectOne(namespace + ".getBoardId");
	}

 

 

5. Mapper 작성

<mapper namespace="com.seongim.mvc_board.mapper.BoardMapper">

<insert id="insertBoard" parameterType="BoardVO">
	INSERT INTO BOARD (
		title,
		content,
		writer
	) VALUES (
		#{title},
		#{content},
		#{writer}
	)
</insert>

<select id="getBoardList" resultType="hashmap">
	 	SELECT
	 		id,
	 		title,
	 		content,
	 		writer,
	 		hit,
	 		CAST(DATE_FORMAT(reg_date, '%Y-%m-%d %H:%i:%s') AS CHAR(19) ) AS reg_date,
	 		CAST(DATE_FORMAT(mod_date, '%Y-%m-%d %H:%i:%s') AS CHAR(19) ) AS mod_date,
	 		del_flag
	 	FROM
	 		board
	 	WHERE
	 		del_flag = 'N'
	 	ORDER BY id DESC
	 	LIMIT #{pageStart}, #{perPageNum}
</select>

<select id="getBoardDetail" parameterType="BoardVO" resultType="hashmap">
	<![CDATA[
	 	SELECT
	 		id,
	 		title,
	 		content,
	 		writer,
	 		hit,
	 		CAST(DATE_FORMAT(reg_date, '%Y-%m-%d %H:%i:%s') AS CHAR(19) ) AS reg_date,
	 		CAST(DATE_FORMAT(mod_date, '%Y-%m-%d %H:%i:%s') AS CHAR(19) ) AS mod_date,
	 		del_flag
	 	FROM 
	 		board
	 	WHERE 
	 		del_flag = "N"
	 		AND
	 		id = #{id}
	 ]]>
</select>

<update id="updateBoard" parameterType="BoardVO">
	UPDATE 
 		BOARD
 	SET
 		title = #{title},
 		content = #{content},
 		writer = #{writer}		
 	WHERE 
 		id = #{id}
</update>

<update id="deleteBoard" parameterType="BoardVO">
	UPDATE 
 		BOARD
 	SET
 		del_flag = "Y"		
 	WHERE 
 		id = #{id}
</update>

<update id="updateHit" parameterType="BoardVO">
	UPDATE 
 		board
 	SET
 		hit = hit + 1		
 	WHERE 
 		id = #{id}
</update>

<select id="getBoardCount" resultType="Integer">
	<![CDATA[
		SELECT
			count(*)
		FROM
			BOARD
		WHERE
			del_flag = 'N'
	]]>
</select>

<select id="getBoardId" resultType="Integer">
	<![CDATA[
		SELECT
			count(*)
		FROM
			BOARD
	]]>
</select>
</mapper>

 

 

6. 페이지 View 만들기

jquery를 사용해 ajax 통신이 가능하도록 작성하였습니다.

 

6-1) 게시판 목록 페이지

GET방식으로 2-1의 게시판 목록 데이터를 json형태의 data로 받아왔습니다.

더보기
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>게시판 목록</title>

<link rel="stylesheet" type="text/css" href="/css/commom/common.css"/>

<script type="text/javascript" src="http://code.jquery.com/jquery-3.4.1.js"></script>
<script>

	$(document).ready(function() {
		getBoardList();
	});
	
	function getBoardList() {
		var page = getUrlVars().page;
		if(!page) {
			page=1;
		}
		$.ajax({
			type : "GET",
			url : "/board/list/"+page,
			dataType : "json",
			contentType : "application/json",
			success : function(data) {
				
				var str = "";
				
				var total_count = data.data.total_count;
				var page = data.data.page;
				var prev = data.data.prev;
				var next = data.data.next;
				var start_page = data.data.start_page;
				var end_page = data.data.end_page;		
				var board = data.data.board;
						
				var idx = total_count - (page - 1) * 10;
				
				$("#total_count").html(total_count);

           		if(total_count > 0) {
					for(var i = 0; i < board.length; i++) {
						var id = board[i].id;
						var title = board[i].title;
						var hit = board[i].hit;
						var writer = board[i].writer;
						var reg_date = board[i].reg_date;
						
						str += "<tr>";
						str += "<td>" + idx + "</td>";
						str += "<td><a href='boardDetail.jsp?id=" + id + "'>" + title + "</a></td>";
						str += "<td>" + hit + "</td>";
						str += "<td>" + writer + "</td>";
						str += "<td>" + reg_date + "</td>";
						str += "</tr>";
						
						idx -= 1;
					}
           		} else {
           			str += "<tr>";
    				str += "<td colspan='5'> 등록된 글이 존재하지 않습니다. </td>";
    				str += "</tr>";
           		} //if~else
           			
           		$("#tbody").html(str);
           		
           		str = "";
           		
           		str += "<ul style='display:inline;'>";
           		
           		if(prev) {
           			str += "<li style='display:inline;'>";
           			str += "<a href='boardList.jsp?page=" + (start_page - 1) + "'><i>이전</i></a>";
           			str += "</li>";
           		}
           		
           		for(var i = start_page; i <= end_page; i++) {
           			//page = i;
           			str += "<li style='display:inline;'>";
           			str += "<a href='boardList.jsp?page=" + i + "'><i>" + i + "</i></a>";
           			str += "</li>";
           			
           		}
           		
           		if(next && end_page > 0) {
           			str += "<li style='display:inline;'>";
           			str += "<a href='boardList.jsp?page=" + (end_page + 1) + "'><i>다음</i></a>";
           			str += "</li>";
           		}
           		
           		$("#div_page").html(str);
			},
			error : function(err) {
				alert("ERROR : " + err);
			}
		});
		
	}
	
	function getUrlVars() {
	    var vars = [], hash;
	    var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
	    for(var i = 0; i < hashes.length; i++) {
	        hash = hashes[i].split('=');
	        vars.push(hash[0]);
	        vars[hash[0]] = hash[1];
	    }
	    return vars;
	}
	
</script>
</head>
<body>
<div id="wrap">
	<div id="container">
		<div class="inner">
			<h1>게시판 목록</h1>
			<form id="boardForm">
				<input type="hidden" id="current_page" name="current_page" value="1" />
				
				<div>
					<span>전체 게시글 수 : <b><span id="total_count"></span></b>개</span>
				</div>
				
				<table width="100%" border="1">
					<colgroup>
						<col width="10%" />
						<col width="25%" />
						<col width="10%" />
						<col width="15%" />
						<col width="20%" />
					</colgroup>
					<thead>
						<tr>
							<th>글번호</th>
							<th>제목</th>
							<th>조회수</th>
							<th>작성자</th>
							<th>작성일</th>
						</tr>
					</thead>
					<tbody id="tbody" style="text-align:center;">
						
					</tbody>
				</table>
			</form>
			<br>
			<div style="float:right;">
				<button type="button" onclick="location.href='boardWrite.jsp'">작성</button>
			</div>
			<br>
			<div id="div_page" style="float:center; width:20%; margin:0 auto;">
			</div>
		</div>
	</div>
</div>
</body>
</html>

 

6-2) 게시판 글 작성 페이지

formData로 title, writer, content, 그리고 files를 받아오고

POST방식으로 Controller를 호출하며 formData를 전송합니다.

46번 라인 : 성공 시 게시판 목록 페이지로 이동합니다.

더보기
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>게시판 목록</title>

<link rel="stylesheet" type="text/css" href="/css/commom/common.css"/>

<script type="text/javascript" src="http://code.jquery.com/jquery-3.4.1.js"></script>
<script>

	function postBoard() {
		
		if($("#title").val()) {
			var title = $("#title").val();
		} else {
			alert("제목을 입력해주세요!");
			return;
		}
		
		if($("#writer").val()) {
			var writer = $("#writer").val();
		} else {
			alert("작성자를 입력해주세요!");
			return;
		}
		
		if($("#content").val()) {
			var content = $("#content").val();
		} else {
			alert("내용을 입력해주세요!");
			return;
		}
		
		var formData = new FormData(document.getElementById("postForm"));
		
		$.ajax({
			type : "POST",
			url : "/board/write",
			enctype : "multipart/form-data",
			processData : false,
			contentType : false,
			data : formData,
			success : function() {
				alert("게시글이 등록되었습니다.");
				location.href="boardList.jsp";
			},
			error : function(err) {
				alert("ERROR : " + err);
			}
		});
	
	}
    
</script>

</head>
<body>
<div id="wrap">
	<div id="container">
		<div class="inner">
			<h1>게시판 등록</h1>
			<form method="post" name="postForm" id="postForm" enctype="multipart/form-data">
				<input type="hidden" name="id" value="1" />
				<table width="100%" border="1">
					<colgroup>
						<col width="40%" />
						<col width="60%" />
					</colgroup>
					<tbody id="tbody" style="text-align:center;">
						<tr>
							<td>제목</td>
							<td><input type="text" name="title" id="title" placeholder="제목을 입력하세요"></td>
						</tr>
						<tr>
							<td>작성자</td>
							<td><input type="text" name="writer" id="writer" placeholder="이름을 입력하세요"></td>
						</tr>
						<tr>
							<td>내용</td>
							<td><textarea type="text" name="content" id="content" rows="10"></textarea></td>
						</tr>
						<tr>
							<td colspan="2">
								다중 파일 추가<input type="file" name="files" id="files" multiple="multiple">
							</td>
						</tr>
					</tbody>
				</table>
				<div style="float:right;">
					<input type="button" onclick="postBoard();" value="등록하기">
	        		<button type="button" onclick="location.href='boardList.jsp'">목록으로</button>
				</div>
			</form>
		</div>
	
	</div>

</div>
</body>
</html>

 

6-3) 게시판 글 상세보기 페이지

더보기
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>게시판 상세</title>

<script type="text/javascript" src="http://code.jquery.com/jquery-3.4.1.js"></script>
<script>

	$(document).ready(function() {
		getBoardDetail();
	});

	function getBoardDetail() {
		var id = getUrlVars().id;
		$.ajax({
			type : "GET",
			url : "/board/detail/" + id,
			dataType : "json",
			contentType : "application/json",
			success : function(data) {
				
				var detail = data.data.detail;
				var file = data.data.file;
				var reply = data.data.reply;
				
				$("#title").html(detail.title);
				$("#hit").html(detail.hit);
				$("#writer").html(detail.writer);
				$("#reg_date").html(detail.reg_date);
				$("#content").html(detail.content);
				
				$("#update_href").prop("href", "boardUpdate.jsp?id=" + detail.id);
				
				str = "";
				
				if(file.length > 0) {
					
					for(var i = 0; i < file.length; i++) {
						var save_file_name = file[i].save_file_name;
						var org_file_name = file[i].org_file_name;
						
						str += "<form id='downForm' method='post' action='/board/detail/file'>";
						str += "<input type='hidden' name='saveFileName' value='" + save_file_name + "'>";
						str += "<input type='hidden' name='originFileName' value='" + org_file_name + "'>";
						str += "<input type='submit' id='click' value='" + save_file_name + "'>";
						str += "<br>"
						str += "</form>";

					}
					
				} else {
					str = "<p>업로드 파일이 없습니다.</p>";
				}
				
				$("#file").html(str);
				
				str ="";
				if(reply.length > 0) {
					for(var i = 0; i < reply.length; i++) {
						var reply_id = reply[i].reply_id;
						var reply_writer = reply[i].reply_writer;
						var reply_content = reply[i].reply_content;
						var reg_date = reply[i].reg_date;
			
						str += "<tr>";
						str += "<td>" + reply_writer + "</td>";
						str += "<td>" + reply_content + "</td>";
						str += "<td>" + reg_date + "</td>";
						str += "<form id='replyDelForm'> method='post'>";
						str += "<td><input type='hidden' name='reply_id' value='" + reply_id + "'>";
						str += "<button type='button' onclick='deleteReply(" + reply_id + ")';)>X</button></td>";
						str += "</form>";
						str += "</tr>";
					} //for
				} else {
					str += "<tr><td colspan='4'>댓글이 없습니다.</td></tr>";
				} //if~else
				
				$("#reply").html(str);
				
			},
			error : function(err) {
				alert("ERROR : " + err);
			}
		});
	}
	
	function getUrlVars() {
	    var vars = [], hash;
	    var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
	    for(var i = 0; i < hashes.length; i++) {
	        hash = hashes[i].split('=');
	        vars.push(hash[0]);
	        vars[hash[0]] = hash[1];
	    }
	    return vars;
	}
	
	function deleteBoard() {
		var id = getUrlVars().id;
		$.ajax({
			type : "DELETE",
			url : "/board/delete/" + id,
			dataType : "json",
			contentType : "application/json",
			success : function(data) {
				console.log("삭제완료");
				alert("게시글이 삭제되었습니다");
				location.href="boardList.jsp";
			},
			error : function(err) {
				alert("ERROR : " + err);
			}

		});
	}
	
	function postReply() {
		var formData = new FormData(document.getElementById("replyForm"));
		console.log(formData.has('updateBoard'));
		var id = getUrlVars().id;
		
		$.ajax({
			type : "POST",
			url : "/board/write/reply/" + id,
			data : formData,
			dataType : "json",
			contentType: false,
			processData: false,
			success : function(data) {
				alert("댓글이 등록되었습니다");
				location.href="boardDetail.jsp?id=" + id;
			},
			error : function(err) {
				alert("ERROR : " + err);
			}
		});
	}
	
	//댓글 삭제
	function deleteReply(reply_id) {
		var id = getUrlVars().id;
		$.ajax({
			type : "DELETE",
			url : "/board/delete/reply/" + reply_id,
			dataType : "json",
			contentType: false,
			processData: false,
			success : function(data) {
				alert("댓글이 삭제되었습니다");
				location.href="boardDetail.jsp?id=" + id;
			},
			error : function (request, status, error){
				alert("code:" + request.status +"\n" + "message:" + request.responseText + "\n" + "error:" + error);
			}

		});
	}
	
	//파일 다운로드
	function downloadFile() {

		var formData = new FormData(document.getElementById("downForm"));
		console.log(formData.has('saveFileName'));
		var id = getUrlVars().id;
		var xhr = new XMLHttpRequest();
		
		$.ajax({
			type : "POST",
			url : "/board/detail/file",
			data : formData,
			processData: false,
            contentType: false,
			success : function() {
			},
			error : function (request, status, error){
				alert("code:" + request.status +"\n" + "message:" + request.responseText + "\n" + "error:" + error);
			}
		});
		
		
	}

</script>
</head>
<body>
<div id="wrap">
	<div id="container">
		<div class="inner">	
			<h2>게시글 상세</h2>		
				<table width="100%" border="1">
				    <colgroup>
				        <col width="15%">
				        <col width="35%">
				        <col width="15%">
				        <col width="*">
				    </colgroup>
				    <tbody id="tbody" style="text-align:center;">
				    	<tr>
				    		<td>제목</td>
							<td id="title"></td>
							<td>조회수</td>
							<td id="hit"></td>
						</tr>
						<tr>
							<td>작성자</td>
							<td id="writer"></td>
							<td>등록일</td>
							<td id="reg_date"></td>
						</tr>
						<tr>
							<td>내용</td>
							<td colspan='3' id="content" style='height:500px;'></td>
						</tr>
						<tr>
							<td colspan="2">
								<p>파일 다운로드</p>
							</td>
							<td colspan="2" id="file">
								
							</td>
						</tr>
				    </tbody>
				</table>	
	
			<br>
			<div style="float:right;">
				<button type="button" onclick="location.href='boardList.jsp'">목록</button>
				<a id="update_href" href = ""><button type="button">수정</button></a>
				<button type="button" onclick="deleteBoard();">삭제</button>
			</div>
			<br>
			<br>
			<div style="width:100%;">
				<form id="replyForm" name="replyForm" method="post" enctype="multipart/form-data">
			      	<div>작성자 : <input type="text" name="reply_writer" id="reply_writer" placehoder="작성자명"></div>
					<div>내&nbsp;&nbsp;&nbsp;용 : <textArea name ="reply_content" id="reply_content" cols="60" rows="5"></textArea></div>	
					<div>
						<input type="button" onclick="postReply();" value="등록">
						<input type="button" value="취소">
					</div>
				</form>
			</div>
		    <table width="100%" border="1">
		    	<colgroup>
					<col width="20%">
				    <col width="50%">
				    <col width="20%">
				    <col width="*">
				</colgroup>
				<thead>
					<tr>
						<th>작성자</th>
						<th>댓글내용</th>
						<th>등록일</th>
						<th>삭제</th>
					</tr>
				</thead>
		    	<tbody id="reply" style="text-align:center;">
		    	</tbody>
		    </table>
		</div>
	</div>
</div>
</body>
</html>

 

6-4) 게시판 글 수정 페이지

게시판 글 작성 페이지를 일부 변형하여 작성했습니다.

더보기
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>게시판 수정</title>

<script type="text/javascript" src="http://code.jquery.com/jquery-3.4.1.js"></script>
<script>
	$(document).ready(function() {
		getBoardDetail();
	});
	
	function getBoardDetail() {
		var id = getUrlVars().id;
		$.ajax({
		type : "GET",
		url : "/board/detail/" + id,
		dataType : "json",
		contentType : "application/json",
		success : function(data) {
			var detail = data.data.detail;
			var file = data.data.file;
			
			$("#title").val(detail.title);
			$("#update_writer").val(detail.writer);
			$("#update_content").html(detail.content);
			
			var str = "";
			if(file.length > 0) {
				for(var i = 0; i < file.length; i++) {
					var save_file_name = file[i].save_file_name;
					var extension = file[i].extension;
			
					str += "<input type='hidden' name='extension' id='extension' value='" + extension + "'>";
					str += "<input type='button' value='" + save_file_name + "' ";
					str += "onclick='deleteFile(" + "\"" + save_file_name + "\", " + "\"" + extension + "\"" + ");' name='saveFileName'>";
					str += "<br>";
					console.log("file : " + save_file_name);
					console.log("file : " + extension);
				}
			}
			
			str += "<input type='file' name='files' multiple='multiple'>";
			
			$("#file").html(str);
		},
		error : function(err) {
			alert("ERROR : " + err);
		}
		});

	}
	
	//파일 삭제
	function deleteFile(save_file_name, extension) {
		var save_file_name = save_file_name;	
		var id = getUrlVars().id;
		$.ajax({
			type : "DELETE",
			url : "/board/delete/file/" + save_file_name,
			enctype : "multipart/form-data",
			processData : false,
			contentType : false,
			success : function() {
				alert("파일이 삭제되었습니다");
				location.href="boardUpdate.jsp?id=" + id;
			},
			error : function(err) {
				alert("ERROR : " + err);
			}
		});
	}
	
	function getUrlVars() {
	    var vars = [], hash;
	    var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
	    for(var i = 0; i < hashes.length; i++) {
	        hash = hashes[i].split('=');
	        vars.push(hash[0]);
	        vars[hash[0]] = hash[1];
	    }
	    return vars;
	}
	
	//게시글 수정
	function updateBoard() {
		
		if($("#title").val()) {
			var title = $("#title").val();
		} else {
			alert("제목을 입력해주세요!");
			return;
		}
		
		if($("#update_writer").val()) {
			var writer = $("#update_writer").val();
		} else {
			alert("작성자를 입력해주세요!");
			return;
		}
		
		if($("#update_content").val()) {
			var content = $("#update_content").val();
		} else {
			alert("내용을 입력해주세요!");
			return;
		}
		
		var formData = new FormData(document.getElementById("updateForm"));
		
		//console.log(formData.has('content')); // true);
		var id = getUrlVars().id;
		
		$.ajax({	
			type : "POST",
			url : "/board/update/" + id,
			enctype : "multipart/form-data",
			processData : false,
			contentType : false,
			data : formData,
			success : function() {
				alert("게시글이 수정되었습니다.");
				location.href="boardList.jsp";
			},
			error : function (request, status, error){
				alert("code:" + request.status +"\n" + "message:" + request.responseText + "\n" + "error:" + error);
			}

		});
	
	}

	
</script>
</head>
<body>

<div id="wrap">
	<div id="container">
		<div class="inner">
			<h1>게시판 수정</h1>
			<form  method="post" name="updateForm" id="updateForm" enctype="multipart/form-data">
				<table width="100%" border="1">
					<colgroup>
						<col width="40%" />
						<col width="60%" />
					</colgroup>
					<tbody id="tbody" style="text-align:center;">
						<tr>
							<td>제목</td>
							<td><input type="text" name="title" id="title" value=""></td>
						</tr>
						<tr>
							<td>작성자</td>
							<td><input type="text" name="writer" id="update_writer" value=""></td>
						</tr>
						<tr>
							<td>내용</td>
							<td><textarea type="text" name="content" id="update_content" rows="10"></textarea></td>
						</tr>
						<tr>
							<td>
								<p>파일</p>
							</td>
							<td id="file">
								
							</td>
						</tr>		
					</tbody>
				</table>
				<div style="float:right;">
					<input type="button" onclick="updateBoard();" value="수정하기">
	        		<button type="button" onclick="location.href='boardList.jsp'">뒤로가기</button>
				</div>
			</form>
		</div>
	</div>
</div>
</body>
</html>

 

1. MVC란?

MVC란 Model View Controller(모델 뷰 컨트롤러)의 약자로 애플리케이션을 세 가지의 역할로 구분한 소프트웨어 디자인 패턴, 개발 방법론이다.

 

Model : 애플리케이션의 데이터들을 의미하며, 사용자들에게 보이는 것에 대해 신경 쓰지 않으며 순수 public 함수로 이루어진다. 

View : 화면을 보여주는 역할로 모델의 데이터를 전달받아서 사용자에게 보여준다.

Controller : 화면의 처리 기능과 Model과 View를 연결시켜주는 역할을 한다.

 

사용자가 Controller를 조작하면 Controller는 Model을 통해 데이터를 가져오고 그 데이터를 바탕으로 View를 제어해 사용자에게 전달된다.

 

 

<출처 - https://commons.wikimedia.org/wiki/File:MVC-Process.svg>

 

2. Spring MVC 프로젝트

1) 프로젝트 구조

 

  • JAVA 파일 : JAVA로 작성된 Controller, Service, DAO 파일들이 위치해있다.

  • webapp : 웹 관련 디렉토리. html, css, js, jsp 파일과 웹 애플리케이션 구동에 필요한 xml 설정 파일들이 위치해있다.

  • spring : spring 설정 파일들이 위치해있다. (spring 컨테이너 생성 위함)

  • views : jsp 파일들이 위치해있다.

  • web.xml : 웹 설정 파일

  • pom.xml : Maven 설정 파일, Maven은 프로젝트 관리 도구로 필요한 라이브러리를 pom.xml에 정의하면 자동으로 라이브러리가 다운받아진다.

 

2) 프로젝트 구성 요소

구성요소 역할
DispatcherServlet Client의 요청을 전달 받아 요청에 맞는 handler로 요청을 보내고 Controller가 return한 결과값을 View에 전달하여 알맞은 응답을 생성한다.
HandlerMapping Client의 요청 url과 Controller를 매핑시킨다.
Controller Client의 요청을 처리한 뒤, 결과를 DispatcherServlet에 전달한다.
ModelAndView Controller가 처리한 결과 정보와 View 정보가 담겨있다.
ViewResolver Controller가 처리한 결과를 생성할 View를 결정한다.
View Controller의 처리 결과 화면을 설정한다.

 

3. Spring MVC 처리 과정

1) 일반적인 Spring MVC

<출처 - https://grokonez.com/spring-framework/spring-mvc-rest-difference-between-controller-and-restcontroller>

  • 클라이언트(Client)가 서버(Server)에 어떤 요청(Request)을 하면 Spring의 DispatcherServlet 클래스가 요청을 가로챈다. (web.xml에서 서블릿 매핑)

  • DispatcherServlet은 HandlerMapping정보를 참조하여 해당 요청을 처리하기 위한 Controller를 찾는다. (servlet-context.xml에서 @Controller 등록)

  • HandlerMappring에 매핑된 Controller가 존재하면 @RequestMapping을 통해 요청을 처리할 메서드로 이동한다.

  • Controller는 해당 요청을 처리할  Service를 받아 비즈니스 로직을 Service에 위임한다.

  • Service는 요청에 필요한 작업을 수행하고, 요청에 대해 DB에 접근이 필요하다면 DAO에 처리를 위임한다.

  • DAO는 mybatis 설정 등을 이용하여 SQL 쿼리를 날려 DB의 정보를 받아 Service에 다시 돌려준다.

  • Service는 모든 로직을 끝내고 결과를 Controller에게 넘긴다.

  • 결과를 받은 Controller는 반환해야 될 View 정보를 Model 객체에 담아 DispatcherServlet에게 전달한다.

  • DispatcherServlet은 ViewResolver에게 전달받은 View 정보를 전달한다.

  • ViewResolver는 응답할 View에 대한 JSP를 찾아 DispatcherServlet에게 전달한다.

  • DispatcherServlet은 응답할 View에게 Render를 지시하고 View는 응답 로직을 처리한다.

  • DispatcherServlet은 클라이언트에게 Rendering 된 View를 응답한다.

 

2) Restful Spring MVC

<출처 - https://grokonez.com/spring-framework/spring-mvc-rest-difference-between-controller-and-restcontroller>

  • 일반적인 Spring MVC 패턴과는 달리 Response를 Controller가 직접 처리한다.
  • HTTP Request에 의해 Controller가 호출되고 Service가 로직을 수행하고 결과를 Controller에 전달하는 과정은 위의 과정과 동일하다.
  • Controller는 return 값을 xml 또는 json 형태로 반환한다.
  • 요청에 대한 결과는 DispatcherServlet을 거치는 것이 아니라, Request가 왔던 곳으로 바로 Response 된다.

 

 

 

틀린 부분 있으면 댓글로 말씀해주세요. 수정하겠습니다!

 

 

1. 디렉토리 구조

MVC_Board 프로젝트는 Business 부분, WebTest 프로젝트는 Client 부분으로 나누어서 작성하였습니다.

 

참고 -> https://imsseong.tistory.com/4

 

[SPRING] MVC 패턴의 이해

1. MVC란? MVC란 Model View Controller(모델 뷰 컨트롤러)의 약자로 애플리케이션을 세 가지의 역할로 구분한 소프트웨어 디자인 패턴, 개발 방법론이다. Model : 애플리케이션의 데이터들을 의미하며, 사용자들..

imsseong.tistory.com

 

2. 설정파일

1) pom.xml

   - 버전 수정

   - jdbc

   - mysql

   - mybatis

   - jsckson

 

더보기
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.seongim</groupId>
	<artifactId>mvc_board</artifactId>
	<name>MVC_Board</name>
	<packaging>war</packaging>
	<version>1.0.0-BUILD-SNAPSHOT</version>
	<properties>
		<java-version>1.8</java-version>
		<org.springframework-version>5.2.2.RELEASE</org.springframework-version>
		<org.aspectj-version>1.6.10</org.aspectj-version>
		<org.slf4j-version>1.7.25</org.slf4j-version>
	</properties>
	<dependencies>
		<!-- Spring -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${org.springframework-version}</version>
			<exclusions>
				<!-- Exclude Commons Logging in favor of SLF4j -->
				<exclusion>
					<groupId>commons-logging</groupId>
					<artifactId>commons-logging</artifactId>
				 </exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>
				
		<!-- AspectJ -->
		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjrt</artifactId>
			<version>${org.aspectj-version}</version>
		</dependency>	
		
		<!-- Logging -->
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>${org.slf4j-version}</version>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>jcl-over-slf4j</artifactId>
			<version>${org.slf4j-version}</version>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-log4j12</artifactId>
			<version>${org.slf4j-version}</version>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.16</version>
			<exclusions>
				<exclusion>
					<groupId>javax.mail</groupId>
					<artifactId>mail</artifactId>
				</exclusion>
				<exclusion>
					<groupId>javax.jms</groupId>
					<artifactId>jms</artifactId>
				</exclusion>
				<exclusion>
					<groupId>com.sun.jdmk</groupId>
					<artifactId>jmxtools</artifactId>
				</exclusion>
				<exclusion>
					<groupId>com.sun.jmx</groupId>
					<artifactId>jmxri</artifactId>
				</exclusion>
			</exclusions>
			<scope>runtime</scope>
		</dependency>

		<!-- @Inject -->
		<dependency>
			<groupId>javax.inject</groupId>
			<artifactId>javax.inject</artifactId>
			<version>1</version>
		</dependency>
				
		<!-- Servlet -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>servlet-api</artifactId>
			<version>2.5</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>javax.servlet.jsp</groupId>
			<artifactId>jsp-api</artifactId>
			<version>2.1</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>
	
		<!-- Test -->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.7</version>
			<scope>test</scope>
		</dependency>
		
		<!-- JDBC -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-jdbc</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>

		<!-- mybatis -->
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis</artifactId>
			<version>3.5.3</version>
		</dependency>
		
		<!-- mybatis-spring -->
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis-spring</artifactId>
			<version>2.0.2</version>
		</dependency>
		
		<!-- jackson -->
		<dependency>
		    <groupId>com.fasterxml.jackson.core</groupId>
		    <artifactId>jackson-databind</artifactId>
		    <version>2.9.5</version>
		</dependency>
		<dependency>
		    <groupId>com.fasterxml.jackson.core</groupId>
		    <artifactId>jackson-annotations</artifactId>
		    <version>2.9.5</version>
		</dependency>
		<dependency>
		    <groupId>com.fasterxml.jackson.core</groupId>
		    <artifactId>jackson-core</artifactId>
		    <version>2.9.5</version>
		</dependency> 	
		
		<dependency>
		    <groupId>commons-fileupload</groupId>
		    <artifactId>commons-fileupload</artifactId>
		    <version>1.2.1</version>
		</dependency>  
		
		<dependency>
		    <groupId>commons-io</groupId>
		    <artifactId>commons-io</artifactId>
		    <version>1.4</version>
		</dependency>
	</dependencies>
    <build>
        <plugins>
            <plugin>
                <artifactId>maven-eclipse-plugin</artifactId>
                <version>2.9</version>
                <configuration>
                    <additionalProjectnatures>
                        <projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
                    </additionalProjectnatures>
                    <additionalBuildcommands>
                        <buildcommand>org.springframework.ide.eclipse.core.springbuilder</buildcommand>
                    </additionalBuildcommands>
                    <downloadSources>true</downloadSources>
                    <downloadJavadocs>true</downloadJavadocs>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.5.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <compilerArgument>-Xlint:all</compilerArgument>
                    <showWarnings>true</showWarnings>
                    <showDeprecation>true</showDeprecation>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>1.2.1</version>
                <configuration>
                    <mainClass>org.test.int1.Main</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

 

2) web.xml

   - Character Encoding Filter 삽입

 

더보기
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 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_2_5.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>
	
	<!-- 인코딩 -->
	<filter>
		<filter-name>CharacterEncodingFilter</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>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

</web-app>

 

3) root-context.xml

   - jdbc연동

   - mybatis설정

   - 파일 업로드를 위한 multipartResolver 설정과 업로드 디렉토리 설정

 

더보기
<?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 -->
	
	<!-- MySQL dataSource -->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/> 
        <property name="url" value="jdbc:mysql://localhost:3306/boardDB?useUnicode=true&amp;characterEncoding=utf8"/> 
        <property name="username" value="root"/> 
        <property name="password" value="1234"/>
    </bean>        
    
    <!-- MyBatis -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="configLocation" value="classpath:mybatis-config.xml"></property>
        <property name="dataSource" ref="dataSource"></property>
        <property name="mapperLocations" value="classpath:mapper/**/*.xml"></property>
    </bean> 
       
    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate" destroy-method="clearCache">
    	<constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"></constructor-arg>
    </bean>
    
    <!-- MultipartResolver 설정 -->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="maxUploadSize" value="100000000" />
        <property name="maxInMemorySize" value="100000000" />
    </bean>
    
    <!-- 파일 업로드 디렉토리 설정 -->
    <bean id="uploadPath" class="java.lang.String">
        <constructor-arg value="C:\Tomcat\webapps\upload"/>
    </bean>

		
</beans>

 

4) mybatis-config.xml

   - src/main/resources에 별도로 mybatis-config.xml을 추가했습니다.

   - 패키지명이 길어지면 경로를 작성하는데 어려움이 있어 typeAliases를 패키지 단위로 등록해주었습니다.

      typeAliases : 자바 타입에 대한 짧은 이름. 오직 XML 설정에서만 사용되며, 타이핑을 줄이기 위해 존재

 

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

<configuration>

	<typeAliases>
		<package name = "com.seongim.mvc_board.domain" />
	</typeAliases>
	
</configuration>

+ Recent posts