로그인과 회원가입, 중복체크까지 구현을 완료함.
이어서 게시판 목록 보이기 구현
1. 로그인을 성공하면 게시글 목록(bbslist.jsp)로 이동
2. 컨트롤러(BbsController.jsp)에서 bbslist.do를 취함
3. mapper(Bbs.xml)에서 sql문으로 select해서 BbsDto에 담아 돌려줌
4. 이 결과를 model의 속성 값으로 추가함
package mul.cam.a.dto;
import java.io.Serializable;
// BBS Bulletin Board System
public class BbsDto implements Serializable {
private int seq; // sequence 글번호
private String id; // 작성자
private int ref; // 답글용 그룹번호(글번호)
private int step; // 행번호
private int depth; // 깊이
private String title;
private String content;
private String wdate;
private int del;
private int readcount; // 조회수
public BbsDto() {
}
public BbsDto(String id, String title, String content) {
super();
this.id = id;
this.title = title;
this.content = content;
}
public BbsDto(int seq, String id, int ref, int step, int depth, String title, String content, String wdate, int del,
int readcount) {
super();
this.seq = seq;
this.id = id;
this.ref = ref;
this.step = step;
this.depth = depth;
this.title = title;
this.content = content;
this.wdate = wdate;
this.del = del;
this.readcount = readcount;
}
public int getSeq() {
return seq;
}
public void setSeq(int seq) {
this.seq = seq;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public int getRef() {
return ref;
}
public void setRef(int ref) {
this.ref = ref;
}
public int getStep() {
return step;
}
public void setStep(int step) {
this.step = step;
}
public int getDepth() {
return depth;
}
public void setDepth(int depth) {
this.depth = depth;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getWdate() {
return wdate;
}
public void setWdate(String wdate) {
this.wdate = wdate;
}
public int getDel() {
return del;
}
public void setDel(int del) {
this.del = del;
}
public int getReadcount() {
return readcount;
}
public void setReadcount(int readcount) {
this.readcount = readcount;
}
@Override
public String toString() {
return "BbsDto [seq=" + seq + ", id=" + id + ", ref=" + ref + ", step=" + step + ", depth=" + depth + ", title="
+ title + ", content=" + content + ", wdate=" + wdate + ", del=" + del + ", readcount=" + readcount
+ "]";
}
}
(앞서 jsp에서 썼던 bbslist사용)
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css">
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.3/dist/jquery.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.3/jquery.min.js"></script>
<script type="text/javascript" src="./jquery/jquery.twbsPagination.min.js"></script>
<style type="text/css">
.table th, .table td {
text-align: center;
vertical-align: middle!important;
}
</style>
</head>
<body bgcolor="#e9e9e9">
<h1>게시판</h1>
<hr>
<div align="center">
<table style="margin-left: auto; margin-right: auto; margin-top: 3px; margin-bottom: 3px">
<tr>
<td style="padding-left: 5px">
<select class="custom-select" id="choice" name="choice">
<option selected>검색</option>
<option value="title">제목</option>
<option value="content">내용</option>
<option value="writer">작성자</option>
</select>
</td>
<td style="padding-left: 5px" class="align-middle">
<input type="text" class="form-control" id="search" name="search" placeholder="검색어" value="<%=search %>">
<td style="padding-left: 5px">
<span>
<button type="button" class="btn btn-primary" onclick="searchBtn()">검색</button>
</span>
</td>
</tr>
</table>
<br>
<table class="table table-hover table-sm" style="width: 1000px">
<col width="70"><col width="600"><col width="100"><col width="150">
<thead>
<tr class="bg-primary" style="color: white;">
<th>번호</th><th>제목</th><th>조회수</th><th>작성자</th>
</tr>
</thead>
</table>
</script>
</body>
</html>
@Controller로 컨트롤러를 선언
@RequestMapping으로 경로 요청이 있을 경우 해당 컨르롤러 클래스를 매핑시켜 줌
package mul.cam.a.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.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import mul.cam.a.dto.BbsComment;
import mul.cam.a.dto.BbsDto;
import mul.cam.a.dto.BbsParam;
import mul.cam.a.service.BbsService;
@Controller
public class BbsController {
@Autowired
BbsService service;
@GetMapping(value="bbslist.do")
//들어오는 값 - param / 짐싸서 보내기 위한 - model
public String bbslist(BbsParam param, Model model) {
}
mapper에 해당 - sql문 작성
id
<?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="Bbs">
<!-- parameterType은 단 하나만 존재! -->
<!-- parameterType - 들어오는 값, resultType - 나가는 값 -->
<select id="bbslist" parameterType="mul.cam.a.dto.BbsParam"
resultType="mul.cam.a.dto.BbsDto">
select seq, id, ref, step, depth, title, content, wdate, del, readcount
from
(select row_number()over(order by ref desc, step asc) as rnum,
seq, id, ref, step, depth, title, content, wdate, del, readcount
from bbs
where 1=1
<if test="choice != null and choice != '' and search != null and search != '' ">
<if test="choice == 'title'">
and title like concat('%', #{search}, '%') and del=0
</if>
<if test="choice == 'content'">
and content like concat('%', #{search}, '%') and del=0
</if>
<if test="choice == 'writer'">
and id=#{search} and del=0
</if>
</if>
order by ref desc, step asc) a
where rnum between ${start} and ${end}
</select>
<!-- 글의 총 갯수 for paging -->
<select id="getAllBbs" parameterType="mul.cam.a.dto.BbsParam" resultType="java.lang.Integer">
select ifnull(count(*), 0)
from bbs
<if test="choice != null and choice != '' and search != null and search != '' ">
<if test="choice == 'title'">
where title like concat('%', #{search}, '%')
</if>
<if test="choice == 'content'">
where content like concat('%', #{search}, '%')
</if>
<if test="choice == 'writer'">
where id=#{search}
</if>
</if>
</select>
SpringMVC 패턴 구성
특정 도메인이 매핑되면 Controller가 해당 Service 호출
-> Service는 주입된 DAO의 리턴 값을 가지고 옴
-> DAO는 mapper의 쿼리의 결과값 반환
-> Controller는 Service의 결과값을 model에 담아 view로 보냄
-> view는 Controller로부터 받은 값을 출력
실제 비즈니스 로직을 처리하는 부분은 Service
DAO는 백엔드에서 서버-클라이언트 프로그램간 데이터를 주고받음
package mul.cam.a.dao;
import java.util.List;
import mul.cam.a.dto.BbsComment;
import mul.cam.a.dto.BbsDto;
import mul.cam.a.dto.BbsParam;
public interface BbsDao {
/* 글과 페이지 넘기기 */
List<BbsDto> bbslist(BbsParam bbs);
//모든 글의 갯수 allBbs
int getAllBbs(BbsParam bbs);
package mul.cam.a.dao.impl;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import mul.cam.a.dao.BbsDao;
import mul.cam.a.dto.BbsComment;
import mul.cam.a.dto.BbsDto;
import mul.cam.a.dto.BbsParam;
@Repository
public class BbsDaoImpl implements BbsDao {
@Autowired
SqlSession session;
String ns = "Bbs.";
@Override
public List<BbsDto> bbslist(BbsParam bbs) {
return session.selectList(ns + "bbslist", bbs);
}
@Override
public int getAllBbs(BbsParam bbs) {
return session.selectOne(ns + "getAllBbs", bbs);
}
package mul.cam.a.service;
import java.util.List;
import mul.cam.a.dto.BbsComment;
import mul.cam.a.dto.BbsDto;
import mul.cam.a.dto.BbsParam;
public interface BbsService {
List<BbsDto> bbslist(BbsParam bbs);
int getAllBbs(BbsParam bbs);
boolean writeBbs(BbsDto dto);
BbsDto getBbs(int seq);
package mul.cam.a.service.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import mul.cam.a.dao.BbsDao;
import mul.cam.a.dto.BbsComment;
import mul.cam.a.dto.BbsDto;
import mul.cam.a.dto.BbsParam;
import mul.cam.a.service.BbsService;
@Service
public class BbsServiceImpl implements BbsService {
@Autowired
BbsDao dao;
@Override
public List<BbsDto> bbslist(BbsParam bbs) {
return dao.bbslist(bbs);
}
@Override
public int getAllBbs(BbsParam bbs) {
return dao.getAllBbs(bbs);
}
@GetMapping(value="bbslist.do")
//들어오는 값 - param / 짐싸서 보내기 위한 - model
public String bbslist(BbsParam param, Model model) {
// 글의 시작과 끝
int pn = param.getPageNumber(); // 0 1 2 3 4
int start = 1 + (pn * 10); // 1 11
int end = (pn + 1) * 10; // 10 20
param.setStart(start);
param.setEnd(end);
List<BbsDto> list = service.bbslist(param);
//페이지 총 갯수
//총 길이값
int len = service.getAllBbs(param);
//게시글의 총 갯수가 아니라 페이지가 몇페이지인지 알고싶은거임
int pageBbs = len / 10; //25/10 -> 2 나머지 5는 3page로 넘어감 +1필요
if((len % 10)>0) {
pageBbs = pageBbs + 1;
}
if(param.getChoice() == null || param.getChoice().equals("")
|| param.getSearch() == null || param.getSearch().equals("")) {
param.setChoice("검색");
param.setSearch("");
}
//짐싸!
model.addAttribute("bbslist", list); // 게시판 리스트
model.addAttribute("pageBbs", pageBbs); // 총 페이지수
model.addAttribute("pageNumber", param.getPageNumber()); // 현재 페이지
model.addAttribute("choice", param.getChoice()); // 검색 카테고리
model.addAttribute("search", param.getSearch()); // 검색어
return "bbslist";
}
<%@page import="mul.cam.a.util.Utility"%>
<%@page import="mul.cam.a.dto.BbsDto"%>
<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css">
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.3/dist/jquery.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.3/jquery.min.js"></script>
<script type="text/javascript" src="./jquery/jquery.twbsPagination.min.js"></script>
<style type="text/css">
.table th, .table td {
text-align: center;
vertical-align: middle!important;
}
</style>
</head>
<body bgcolor="#e9e9e9">
<%
/*
String choice = request.getParameter("choice");
String search = request.getParameter("search");
if(choice == null){
choice = "";
}
if(search == null){
search = "";
}
*/
// BbsDao dao = BbsDao.getInstance();
// List<BbsDto> list = dao.getBbsList();
// List<BbsDto> list = dao.getBbsSearchList(choice, search);
List<BbsDto> list = (List<BbsDto>)request.getAttribute("bbslist");
int pageBbs = (Integer)request.getAttribute("pageBbs");
int pageNumber = (Integer)request.getAttribute("pageNumber");
String choice = (String)request.getAttribute("choice");
String search = (String)request.getAttribute("search");
%>
<h1>게시판</h1>
<hr>
<div align="center">
<table style="margin-left: auto; margin-right: auto; margin-top: 3px; margin-bottom: 3px">
<tr>
<td style="padding-left: 5px">
<select class="custom-select" id="choice" name="choice">
<option selected>검색</option>
<option value="title">제목</option>
<option value="content">내용</option>
<option value="writer">작성자</option>
</select>
</td>
<td style="padding-left: 5px" class="align-middle">
<input type="text" class="form-control" id="search" name="search" placeholder="검색어" value="<%=search %>">
<td style="padding-left: 5px">
<span>
<button type="button" class="btn btn-primary" onclick="searchBtn()">검색</button>
</span>
</td>
</tr>
</table>
<br>
<table class="table table-hover table-sm" style="width: 1000px">
<col width="70"><col width="600"><col width="100"><col width="150">
<thead>
<tr class="bg-primary" style="color: white;">
<th>번호</th><th>제목</th><th>조회수</th><th>작성자</th>
</tr>
</thead>
<tbody>
<%
if(list == null || list.size() == 0){
%>
<tr>
<td colspan="4">작성된 글이 없습니다</td>
</tr>
<%
}else{
for(int i = 0;i < list.size(); i++)
{
BbsDto dto = list.get(i);
%>
<tr>
<th><%=i + 1 + (pageNumber * 10) %></th>
<td style="text-align: left;">
<%
if(dto.getDel() == 0){
%>
<%=Utility.arrow(dto.getDepth()) %>
<a href="bbsdetail.do?seq=<%=dto.getSeq() %>">
<%=dto.getTitle() %>
</a>
<%
}else if(dto.getDel() == 1){
%>
<%=Utility.arrow(dto.getDepth()) %>
<font color="#ff0000">*** 이 글은 작성자에 의해서 삭제되었습니다 ***</font>
<%
}
%>
</td>
<td><%=dto.getReadcount() %></td>
<td><%=dto.getId() %></td>
</tr>
<%
}
}
%>
</tbody>
</table>
<br>
<%-- <%
for(int i = 0;i < pageBbs; i++){
if(pageNumber == i){ // 현재 페이지
%>
<span style="font-size: 15pt;color: #0000ff">
<%=i+1 %>
</span>
<%
}else{ // 그밖에 다른 페이지
%>
<a href="#none" title="<%=i+1 %>페이지" onclick="goPage(<%=i %>)"
style="font-size: 15pt; color: #000; text-decoration: none;">
[<%=i+1 %>]
</a>
<%
}
}
%> --%>
<div class="container">
<nav aria-label="Page navigation">
<ul class="pagination" id="pagination" style="justify-content:center"></ul>
</nav>
</div>
<br>
<a href="bbswrite.do">글쓰기</a>
</div>
<script type="text/javascript">
let search = "<%=search %>";
console.log("search = " + search);
if(search != ""){
let obj = document.getElementById("choice");
obj.value = "<%=choice %>";
obj.setAttribute("selected", "selected");
}
function searchBtn() {
let choice = document.getElementById('choice').value;
let search = document.getElementById('search').value;
/* if(choice == ""){
alert("카테고리를 선택해 주십시오");
return;
} */
/*
if(search.trim() == ""){
alert("검색어를 선택해 주십시오");
return;
} */
location.href = "bbslist.do?choice=" + choice + "&search=" + search;
}
//페이징
$('#pagination').twbsPagination({
startPage: <%=pageNumber+1 %>,
totalPages: <%=pageBbs %>,
visiblePages: 10,
first:'<span srid-hidden="true">«</span>',
prev:"이전",
next:"다음",
last:'<span srid-hidden="true">»</span>',
initiateStartPageClick:false, // onPageClick 자동실행되지 않도록
onPageClick: function (event, page) {
// alert(page);
let choice = document.getElementById('choice').value;
let search = document.getElementById('search').value;
location.href = "bbslist.do?choice=" + choice + "&search=" + search + "&pageNumber=" + (page-1);
}
});
</script>
</body>
</html>