저번에 포스팅 했던 회원가입 및 로그인 검증은 우선 끝낫다.
이제 저번에 만들었던 게시판을 한번 만들어 보고자 한다!
사용 기술 | 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>
<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으로 작성하는법
3. 객체하나를 매개값으로 보내는법 들을 적절하게 상황에 맞게 선택하면 됨
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>
<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
'Spring > 학원에서 배운거정리 끄적' 카테고리의 다른 글
(Spring /Java) 스프링 파일 업로드 구현 (2) | 2022.02.20 |
---|---|
(Spring /Java)이메일 인증 구현하기😎 (4) | 2022.02.17 |
Spring스프링(Spring) 회원가입 진행(3-1) ajax 문제해결 404 error (0) | 2022.02.14 |
Spring(4) 로그인 처리 및 로그인 검증 세션작업(1)😁 (0) | 2022.02.14 |
스프링(Spring) 회원가입 진행(3) (0) | 2022.02.11 |