반응형

저번에 포스팅 했던 회원가입 및 로그인 검증은 우선 끝낫다. 

이제 저번에 만들었던 게시판을 한번 만들어 보고자 한다! 

 

사용 기술 Tools
Java 11 jdk STS3
Oracle 18g SQLDev

 

 

 

1. SQL 테이블 생성 😎 

 

 -- 게시판 테이블 생성
CREATE TABLE mvc_board (
    board_no NUMBER PRIMARY KEY,
    title VARCHAR2(100) NOT NULL,
    content VARCHAR2(300) NOT NULL,
    writer VARCHAR2(50) NOT NULL,
    reg_date DATE DEFAULT sysdate,
    view_cnt NUMBER DEFAULT 0
);

-- board_no에 대한 시퀀스 설정
CREATE SEQUENCE board_seq
    START WITH 1
    INCREMENT BY 1
    MAXVALUE 1000
    NOCYCLE
    NOCACHE;

우선 게시판을 만들 수있는 뼈대 즉 테이블 부터 생성해준다! 

 

 


2. BoardVO 생성 🤪

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class BoardVO {
	
	private int boardNo;
	private String title;
	private String content;
	private String writer;
	private Timestamp regDate;
	private int viewCnt;
	
	//new 마크 부착 여부 논리타입 필드
	private boolean newMark;
	

}

 

우선 Getter or Setter를 좀 더 쉽게 하기 위해 lombok을 사용하였다. 


3.  HTML 제작

 

	<div class="container">
		<div class="row">
			<div class="col-lg-2">
			</div>
			<div class="col-lg-8">
				<div class="panel-body">
				<h2 class="page-header"><span style="color: #643691;">Spring</span> 자유 게시판
					<span id="count-per-page" style="float: right;">
	                     <input class="btn btn-cpp" type="button" value="10">  
	                     <input class="btn btn-cpp" type="button" value="20">   
	                     <input class="btn btn-cpp" type="button" value="30">
                     </span>
					
				</h2>
					<table class="table table-bordered table-hover">
						<thead>
							<tr style="background-color: #643691; margin-top: 0; height: 40px; color: white; border: 0px solid #f78f24; opacity: 0.8">
								<th>#번호</th>
								<th>작성자</th>
								<th>제목</th>
								<th>작성일</th>
								<th>조회수</th>
							</tr>
						</thead>

						<!-- 게시물이 들어갈 공간 -->
						<c:forEach var="b" items="${articles}">
							<tr style="color: #643691;">
								<td>${b.boardNo}</td>
								<td>${b.writer}</td>

								<td><a style="margin-top: 0; height: 40px; color: orange;"
								 href="<c:url value="/board/content/${b.boardNo}${pc.makeUri(pc.paging.page)}"/>">
										${b.title} 
									</a>
									&nbsp;
									<c:if test="${b.newMark}">
										<img alt="newmark" src="C:\Users\mls00\OneDrive\바탕 화면\SpringWebMvcProject\src\main\webapp\resources\img\icon_new.gif">
									</c:if>
								</td>

								<td> <fmt:formatDate pattern="yyyy-MM-dd hh:mm:ss" value="${b.regDate}"/></td>
								<td>${b.viewCnt}</td>
							</tr>
						</c:forEach>
						
						
					</table>
					
					<!-- 페이징 처리 부분  -->
						<ul class="pagination justify-content-center">
					<c:if test="${pc.prev}">
                       	<li class="page-item">
							<a class="page-link" href="/board/list/?${pc.makeUri(pc.beginPage-1)}"
							style="background-color: #643691; margin-top: 0; height: 40px; color: white; border: 0px solid #f78f24; opacity: 0.8">이전</a>
						</li></c:if>
				
						<c:forEach var="num" begin="${pc.beginPage}" end="${pc.endPage}" >
							<li class="page-item">
						   <a href="/board/list${pc.makeUri(num)}" 
						   class="page-link  ${pc.paging.page == num ? 'page-active': '' }" style="margin-top: 0; height: 40px; color: pink; border: 1px solid #643691;">${num}</a>
						</li>
					   </c:forEach>
					
					 <c:if test="${pc.next}">
					     <li class="page-item">
					      <a class="page-link" href='<c:url value='/board/list${pc.makeUri(pc.endPage+1)}}'/>' 
					      style="background-color: #643691; margin-top: 0; height: 40px; color: white; border: 0px solid #f78f24; opacity: 0.8">다음</a>
					    </li>
				    </ul></c:if>
					
					<!-- 페이징 처리 끝 -->
					</div>
				</div>
			</div>
					<!-- 검색 버튼 -->
					<div class="row">
						<div class="col-sm-2"></div>
	                    <div class="form-group col-sm-2">
	                        <select id="condition" class="form-control" name="condition">                            	
	                            <option value="title" ${param.condition == 'title' ? 'selected' : '' }>제목</option>
	                            <option value="content"${param.condition == 'content' ? 'selected' : '' }>내용</option>
	                            <option value="writer"${param.condition == 'writer' ? 'selected' : '' }>작성자</option>
	                            <option value="titleContent"${param.condition == 'titleContent' ? 'selected' : '' }>제목+내용</option>
	                        </select>
	                    </div>
	                    <div class="form-group col-sm-4">
	                        <div class="input-group">
	                            <input type="text" class="form-control" name="keyword" id="keywordInput" placeholder="검색어" value="${param.keyword}">
	                            <span class="input-group-btn">
	                                <input type="button" value="검색" class="btn btn-cpp btn-flat" id="searchBtn">                                       
	                            </span>
	                        </div>
	                    </div>
	                    <div class="col-sm-2">
							<a href="<c:url value ="/board/write"/>" class="btn btn-cpp float-right">글쓰기</a>
						</div>
						<div class="col-sm-2"></div>
					</div>
		
	</div>

 

기본 뼈대의 Html이다 CSS는 BOOTSTRAP을 사용하였다. 😎😎😎

 


4. 본격적인 Spring 시작!😁

 

4-1 Controller 제작

 

 

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

   @GetMapping("/list")
   public String list(Model model) {
      System.out.println("/board/list: GET");
      model.addAttribute("articles", service.getArticleList());
      
      return "board/list";
   	}
   }

 

 

4-2 인터페이스 제작

package com.spring.mvc.board.service;

import java.util.List;

import com.spring.mvc.board.commons.SearchVO;
import com.spring.mvc.board.commons.pageVO;
import com.spring.mvc.board.model.BoardVO;

public interface IBoardService {

	//게시글 등록 기능
	void insert(BoardVO article);

	//게시글 전체 목록 기능
	List<BoardVO> getArticleList(SearchVO search);

	//게시글 상세 조회 기능
	BoardVO getArticle(int boardNo);

	//게시글 수정 기능
	void update(BoardVO article);

	//게시글 삭제 기능
	void delete(int boardNo);

	//게시물 수 조회 기능 
	int countArticles(SearchVO search);
	
	//날자 한글로 변경
	
}

 

IboardService를 만든다. 기능은 단순하게 세팅해준다.

 

그 다음은 IBoardMapper를 생성해준다.

 

package com.spring.mvc.board.repository;

import java.util.List;
import java.util.Map;

import org.apache.ibatis.annotations.Param;

import com.spring.mvc.board.commons.SearchVO;
import com.spring.mvc.board.commons.pageVO;
import com.spring.mvc.board.model.BoardVO;

public interface IBoardMapper {

	//게시글 등록 기능
	void insert(BoardVO article);
	
	//검색 결과와 페이지 정보까지 가지고 있는 하나의 객체를 매개값으로 받는 방식
	List<BoardVO> getArticleList(SearchVO search);
	//게시글 상세 조회 기능
	BoardVO getArticle(int boardNo);
	
	//게시글 수정 기능
	void update(BoardVO article);
	
	//게시글 삭제 기능
	void delete(int boardNo);
	
	//게시물 수 조회 기능
	int countArticles(SearchVO search);


	
	
}

 여기서 주의 할 점!

 

 MYBatis로 db연동을 진행할 떄 파라미터 값이 2개 이상이라면 
 1. @param으로 작성하는법

 2. map으로 포장해서 보내는법 

 3. 객체하나를 매개값으로 보내는법 들을 적절하게 상황에 맞게 선택하면 됨

 

 

주로 Map을 이용한 방법을 많이 쓴다. 

 

 


5. Service 제작 👏

package com.spring.mvc.board.service;

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

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.spring.mvc.board.commons.SearchVO;
import com.spring.mvc.board.commons.pageVO;
import com.spring.mvc.board.model.BoardVO;
import com.spring.mvc.board.repository.IBoardMapper;

@Service
public class BoardService implements IBoardService {
	
	@Autowired
	private IBoardMapper mapper;

	@Override
	public void insert(BoardVO article) {
		mapper.insert(article);
	}


	@Override
	public List<BoardVO> getArticleList(SearchVO search) {
		//mapper에게 전달할 맵 데이터를 생성
//		Map<String, Object> datas = new HashMap<>();
//		datas.put("paging", paging);
//		datas.put("keyword", keyword);
//		datas.put("condition", condition);
		
		List<BoardVO> list = mapper.getArticleList(search);
		for(BoardVO article : list) {
			long now = System.currentTimeMillis();
			long regTime = article.getRegDate().getTime();
			if(now - regTime < 60 * 60*24 *1000) {
				article.setNewMark(true);
			}
		}
		return list;
	}

	@Override
	public BoardVO getArticle(int boardNo) {
		return mapper.getArticle(boardNo);
	}

	@Override
	public void update(BoardVO article) {
		mapper.update(article);
	}

	@Override
	public void delete(int boardNo) {
		mapper.delete(boardNo);
	}
	
	@Override
	public int countArticles(SearchVO search){
		return mapper.countArticles(search);
	}
	
}

 

IServiceBoard를 Add하여 생성해준다.

 

 

 


6. Mapper 제작🤞

 

Mapper 를 제작해준다. 

이때 꿀팁

<mybatis-spring:scan base-package="com.spring.mvc.board.repository"/>
<mybatis-spring:scan base-package="com.spring.mvc.user.repository"/>

Context-root.xml 파일일에 Mybatis.xml파일을 bean으로 등록하기 위한 스캔 설정을 해줍니다. 

<interceptors>
		<interceptor>
			<!-- <mapping path="/board/**"/>  -->	
			<mapping path="/board/write"/>
			<mapping path="/board/content/**"/> <!-- **은 글번호  -->
			<beans:bean class="com.spring.mvc.board.commons.intercertor.BoardInterceptor" />
		</interceptor>

이때 servlet-config.xml에서 이렇게 설정을 해주면 별도로 xml 파일을 만들때 빈등록을 안해줘도 됩니다. 

👏👏👏👏즉 위 지정된 경로만 지정해주면 된다! 👏👏👏👏

 

위에 지정한 대로 파일을 이렇게 설정 하였다!

	<select id="getArticleList" resultMap="BoardMap">

		SELECT * FROM mvc_board
		
		ORDER BY board_no DESC
		

	</select>

리스트를 불러올 수 있도록 Select 값을 넣어준다!

	<insert id="insert">
		INSERT INTO mvc_board
		(board_no, title, content, writer)
		VALUES(board_seq.NEXTVAL,#{title},#{content},#{writer})
	</insert>

그리고 현재 insert 관련하여 컨트롤러나 이런부분을 만들지 않았다 하지만 게시물이 보이는

리스트를 만들려면 insert를 하여 볼 데이터가 필요했다. 

sqldev로 해도 되지만 plsql하기 귀찮아 Junit으로 테스트를 한다. 

 


7. Junit Test

 

package com.spring.mvc.board;

import java.util.List;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.spring.mvc.board.model.BoardVO;
import com.spring.mvc.board.repository.IBoardMapper;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"file:src/main/webapp/WEB-INF/spring/mvc-config.xml"})
public class BoardMapperTest {

	@Autowired
	private IBoardMapper mapper;
	
	//게시글 등록 단위 테스트
	@Test
	public void insertTest() {
		for(int i=1; i<=300; i++) {
			BoardVO article = new BoardVO();
			article.setTitle("테스트 제목입니다." + i);
			article.setWriter("김테스트" + i);
			article.setContent("테스트 중이니까 조용히 하세요!" + i);
			mapper.insert(article);
		}
	}

 

우선 300개만 가볍게 넣어보자

 

데이터가 잘 들어갔다면 이제 화면에 뿌려주자!

 


8. 화면 작업

<c:forEach var="b" items="${articles}">
		<tr style="color: #643691;">
		<td>${b.boardNo}</td>
		<td>${b.writer}</td>

		<td><a style="margin-top: 0; height: 40px; color: orange;"
		href="<c:url value="/board/content/${b.boardNo}${pc.makeUri(pc.paging.page)}"/>">
		${b.title} 
		</a>
		&nbsp;
		<c:if test="${b.newMark}">
		<img alt="newmark" src="C:\Users\mls00\OneDrive\바탕 화면\SpringWebMvcProject\src\main\webapp\resources\img\icon_new.gif">
		</c:if>
		</td>

		<td> <fmt:formatDate pattern="yyyy-MM-dd hh:mm:ss" value="${b.regDate}"/></td>
		<td>${b.viewCnt}</td>
		</tr>
		</c:forEach>
						
						
		</table>

 

Jstl 을 이용하여 받아온 파라미터 값을 뿌려준다.

😎<c:forEach var="b" items="${articles}">😎

😎변수는 b로 하고 뿌려준다!😎


😎

9. 동작 확인🙏

 

 

테스트로 넣은 게시글이 잘 보이는걸 알 수 있다!

 

또 오류 나는 줄 알고 십년감수했다.☠️

 

 

 

주인장 Github 

 

https://github.com/MoonSeokHyun

반응형

+ Recent posts