Spring

240304 스프링 프로젝트

코딩하는딩굴 2024. 3. 4. 10:16

관리자 페이지 만들기

Admin 의 Controller, Service, Repository 만들기

@Controller
@RequestMapping("/admin")
public class AdminController extends AbstractController{

  @Resource(name="adminService")
  private AdminService adminService;

  @GetMapping("/index")
  public String index() {
    return "admin/index";
  }
  
  @GetMapping("/boardList")
  public String boardList(@RequestParam(value = "page", required = false, defaultValue = "1") String no, Model model) {
    int totalRecordCount = adminService.totalRecordCount();
    int page = util.str2Int2(no);
    
    PaginationInfo paginationInfo = new PaginationInfo();
    paginationInfo.setCurrentPageNo(page); // 현재 페이지 번호
    paginationInfo.setRecordCountPerPage(15); // 한 페이지에 게시되는 게시글 건수
    paginationInfo.setPageSize(10); // 페이지 리스트 사이즈
    paginationInfo.setTotalRecordCount(totalRecordCount); // 총 페이지 수

    model.addAttribute("list", adminService.boardList(paginationInfo.getFirstRecordIndex()));
    model.addAttribute("paginationInfo", paginationInfo);
    model.addAttribute("page", page);

    return "admin/boardList";
  }

 

RequestMapping 을 넣으면 /admin 이 고정으로 들어간다고 함

GetMapping 에서 /admin/index 와 RequestMapping 에 /admin 을 넣고 /index 한 것과 같은 효과

 

@Service("adminService")
public class AdminService {
  
  @Autowired
  private AdminRepository adminRepository;
  
  public List<BoardDTO> boardList(int page) {
    return adminRepository.boardList(page);
  }
  
@Repository
public class AdminRepository {
  
  @Autowired
  private SqlSession sqlSession;
  
  public List<BoardDTO> boardList(int page) {
    return sqlSession.selectList("admin.boardList", page);
  }

  public int totalRecordCount() {
    return sqlSession.selectOne("admin.totalRecordCount");
  }

 

Mapper 설정

<mapper namespace="admin">
  <select id="boardList" parameterType="Integer" resultType="boardDTO">
    select board_no, board_title, mname, board_date, board_del 
    from board join member on board.mno = member.mno 
    order by board_no desc
    limit #{page}, 15
  </select>
	
  <select id="totalRecordCount" resultType="Integer">
    select count(*) from board
  </select>

 

BoardList.jsp 를 만들어서 글 전체 띄우기

<div class="tableDiv d-flex justify-content-center align-items-center">
  <table class="table text-center">
    <thead>
      <tr>
        <th class="">번호</th>
        <th class="">제목</th>
        <th class="">글쓴이</th>
        <th class="">작성일</th>
        <th class="">삭제여부</th>
      </tr>
    </thead>
    <tbody>
      <c:forEach items="${list }" var="list">
        <tr>
          <td>${list.board_no }</td>
          <td>${list.board_title }</td>
          <td>${list.mname }</td>
          <td>${list.board_date }</td>
          <td>
            <c:choose>
              <c:when test="${list.board_del eq 1}">
                <i class="fas fa-fw fa-regular fa-eye"></i>
              </c:when>
              <c:otherwise>
                <i class="fas fa-fw fa-regular fa-eye-slash"></i>
              </c:otherwise>
            </c:choose>
          </td>
        </tr>
      </c:forEach>
    </tbody>
  </table>
</div>

 

Comments 도 똑같이 진행

@GetMapping("/comments")
public String comments(@RequestParam(value = "page", required = false, defaultValue = "1") String no, Model model) {
  int totalRecordCount = adminService.totalCommentRecordCount();
  int page = util.str2Int2(no);
    
  PaginationInfo paginationInfo = new PaginationInfo();
  paginationInfo.setCurrentPageNo(page); // 현재 페이지 번호
  paginationInfo.setRecordCountPerPage(15); // 한 페이지에 게시되는 게시글 건수
  paginationInfo.setPageSize(10); // 페이지 리스트 사이즈
  paginationInfo.setTotalRecordCount(totalRecordCount); // 총 페이지 수

  model.addAttribute("list", adminService.commentList(paginationInfo.getFirstRecordIndex()));
  model.addAttribute("paginationInfo", paginationInfo);
  model.addAttribute("page", page);

  return "admin/comments";
}

// Service
public int totalCommentRecordCount() {
  return adminRepository.totalCommentRecordCount();
}

public List<CommentDTO> commentList(int firstRecordIndex) {
  return adminRepository.commentList(firstRecordIndex);
}

// Repository
public int totalCommentRecordCount() {
  return sqlSession.selectOne("admin.totalCommentRecordCount");
}

public List<CommentDTO> commentList(int page) {
  return sqlSession.selectList("admin.commentList", page);
}
<select id="totalCommentRecordCount" resultType="Integer">
  select count(*) from comment
</select>
  
<!-- DB 에 있는 데이터와 DTO 의 값 매핑시키기 -->
<resultMap type="commentDTO" id="commentDTOmap">
  <result column="cno" property="no" />
  <result column="ccomment" property="comment" />
</resultMap>
  
<select id="commentList" parameterType="Integer" resultMap="commentDTOmap">
  select cno, board_no, mname, ccomment, cdate, clike, cdel 
  from comment join member on comment.mno = member.mno 
  order by cno desc
  limit #{page}, 15
</select>

 

Select, Option 을 이용한 게시물 필터링

게시글 한번에 n개씩 보기 처리하기

<select name="boardCount" id="boardCount">
  <option value="10">10개씩 보기</option>
  <option value="15">15개씩 보기</option>
  <option value="20">20개씩 보기</option>
</select>

 

Select 태그 추가하기

 

값 바꿀 때마다 바꾸기

$(function() {
  $('#boardCount').change(function() {
    location.href = "./boardList?page=${page}&boardCount=" + $('#boardCount').val();
  });
});

 

Controller 에서 값 받기

@RequestParam(value = "boardCount", required = false, defaultValue = "10") String boardCount

int perPage = util.str2Int2(boardCount);

PaginationInfo paginationInfo = new PaginationInfo();
paginationInfo.setCurrentPageNo(page); // 현재 페이지 번호
paginationInfo.setRecordCountPerPage(perPage); // 한 페이지에 게시되는 게시글 건수
paginationInfo.setPageSize(10); // 페이지 리스트 사이즈
paginationInfo.setTotalRecordCount(totalRecordCount); // 총 페이지 수

SearchDTO dto = new SearchDTO();
dto.setPage(paginationInfo.getFirstRecordIndex());
dto.setPerPage(perPage);
    
model.addAttribute("list", adminService.boardList(dto));

 

쭉 넘겨서 mapper 에서 처리

<select id="boardList" parameterType="searchDTO" resultType="boardDTO">
  select board_no, board_title, mname, board_date, board_del 
  from board join member on board.mno = member.mno 
  order by board_no desc
  limit #{page}, #{perPage}
</select>

 

검색 결과 처리하기

Search 검색창 추가

<span class="input-group col-4">
  <input type="text" name="search" id="search" class="form-control"/>
  <button type="button" class="btn btn-outline-dark" id="searchBtn">검색</button>
</span>

 

Controller 에서 값 받기

@RequestParam(value = "search", required = false) String search

 

DTO 에 같이 넣어서 값 보내기, 검색 시 페이징 처리

글 작성자도 함께 처리하기

// 검색 한 내용으로 총 글 갯수 확인하기, Controller
int totalRecordCount = adminService.totalRecordCount(search);

// Service
public int totalRecordCount(String search) {
  return adminRepository.totalRecordCount(search);
}

// Repository
public int totalRecordCount(String search) {
  return sqlSession.selectOne("admin.totalRecordCount", search);
}
<select id="boardList" parameterType="searchDTO" resultType="boardDTO">
  select board_no, board_title, mname, board_date, board_del
  from board join member on board.mno = member.mno 
  <where>
    <if test="search != null">
      board_title like concat('%', #{search}, '%') 
      or board_content like concat('%', #{search}, '%') 
      or mname like concat('%', #{search}, '%') 
    </if>
  </where>
  order by board_no desc
  limit #{page}, #{perPage}
</select>

<select id="totalRecordCount" parameterType="String" resultType="Integer">
  select count(*) from board b join member m on b.mno = m.mno 
  <where>
    <if test="search != null">
      (b.board_title like concat('%', #{search}, '%')
      or b.board_content like concat('%', #{search}, '%')
      or m.mname like concat('%', #{search}, '%'))
    </if>
  </where>
</select>

 

글 검색 시 제목, 본문, 작성자, 제목 + 본문 검색 해보기

<div class="row justify-content-end">
  <span class="">
    <select name="boardCount" id="boardCount" class="form-control">
      <option value="10" <c:if test="${boardCount eq 10 }">selected</c:if>>10개씩 보기</option>
      <option value="15" <c:if test="${boardCount eq 15 }">selected</c:if>>15개씩 보기</option>
      <option value="20" <c:if test="${boardCount eq 20 }">selected</c:if>>20개씩 보기</option>
    </select>
  </span>
  <span class="input-group col-6">
    <select name="searchTitle" id="searchTitle" class="form-control col-3">
      <option value="1" <c:if test="${searchTitle eq 1 }">selected</c:if>>제목</option>
      <option value="2" <c:if test="${searchTitle eq 2 }">selected</c:if>>본문</option>
      <option value="3" <c:if test="${searchTitle eq 3 }">selected</c:if>>작성자</option>
      <option value="4" <c:if test="${searchTitle eq 4 }">selected</c:if>>제목+본문</option>
    </select>
    <input type="text" name="search" value="${search }" id="search" class="form-control"/>
    <button type="button" class="btn btn-outline-dark" id="searchBtn">검색</button>
  </span>
</div>

 

Controller 또또또 수정

@GetMapping("/boardList")
public String boardList(
      @RequestParam(value = "page", required = false, defaultValue = "1") String no, 
      @RequestParam(value = "boardCount", required = false, defaultValue = "10") String boardCount,
      @RequestParam(value = "search", required = false) String search,
      @RequestParam(value = "searchTitle", required = false, defaultValue = "1") String searchTitle,
      Model model) {
    
  int page = util.str2Int2(no);
  int perPage = util.str2Int2(boardCount);
  int sTitle = util.str2Int2(searchTitle);

  SearchDTO dto = new SearchDTO();
  dto.setPerPage(perPage);
  dto.setSearchTitle(sTitle);
  dto.setSearch(search);
    
  int totalRecordCount = adminService.totalRecordCount(dto);
    
  PaginationInfo paginationInfo = new PaginationInfo();
  paginationInfo.setCurrentPageNo(page); // 현재 페이지 번호
  paginationInfo.setRecordCountPerPage(perPage); // 한 페이지에 게시되는 게시글 건수
  paginationInfo.setPageSize(10); // 페이지 리스트 사이즈
  paginationInfo.setTotalRecordCount(totalRecordCount); // 총 페이지 수
    
  dto.setPage(paginationInfo.getFirstRecordIndex());

  model.addAttribute("list", adminService.boardList(dto));
  model.addAttribute("paginationInfo", paginationInfo);
  model.addAttribute("page", page);
  model.addAttribute("boardCount", perPage);
  model.addAttribute("search", search);
  model.addAttribute("searchTitle", sTitle);

  return "admin/boardList";
}

 

totalRecordCount 도 SearchDTO 를 넣어서 값 검색

검색과 totalRecord mapper

<select id="boardList" parameterType="searchDTO" resultType="boardDTO">
  select board_no, board_title, mname, board_date, board_del
  from board join member on board.mno = member.mno
  <where>
    <if test="search != null">
      <if test="searchTitle == 1">
        board_title like concat('%', #{search}, '%')
      </if>
      <if test="searchTitle == 2">
        board_content like concat('%', #{search}, '%')
      </if>
      <if test="searchTitle == 3">
        mname like concat('%', #{search}, '%')
      </if>
      <if test="searchTitle == 4">
        b.board_title like concat('%', #{search}, '%')
        or b.board_content like concat('%', #{search}, '%')
      </if>
    </if>
  </where>
  order by board_no desc
  limit #{page}, #{perPage}
</select>

<select id="totalRecordCount" parameterType="searchDTO" resultType="Integer">
  select count(*) from board b join member m on b.mno = m.mno
  <where>
    <if test="search != null">
      <if test="searchTitle == 1">
        b.board_title like concat('%', #{search}, '%')
      </if>
      <if test="searchTitle == 2">
        b.board_content like concat('%', #{search}, '%')
      </if>
      <if test="searchTitle == 3">
        m.mname like concat('%', #{search}, '%')
      </if>
      <if test="searchTitle == 4">
        b.board_title like concat('%', #{search}, '%')
        or b.board_content like concat('%', #{search}, '%')
      </if>
    </if>
  </where>
</select>

 

스크립트 내부 url 도 수정해야 함

<script type="text/javascript">
  function linkPage(page) {
    location.href = "./boardList?page=" + page + "&boardCount=${boardCount}" + "&searchTitle=${searchTitle}" + "&search=${search}";
  }

  $(function() {
    $('#boardCount').change(function() {
        location.href = "./boardList?page=${page}&boardCount=" + $('#boardCount').val() + "&searchTitle=${searchTitle}" + "&search=${search}";
    });
    
    $('#searchBtn').click(function() {
      location.href="./boardList?boardCount=${boardCount}&searchTitle=" + $('#searchTitle').val() + "&search=" + $('#search').val();
    });
  });
</script>

 

관리자 페이지에서 게시글 버튼 클릭으로 삭제 여부 바꾸기

<tr class="row${list.board_del }">
  <td class="bno">${list.board_no }</td>
  <td><a href="./detail?no=${list.board_no }">${list.board_title }</a></td>
  <td>${list.mname }</td>
  <td>${list.board_date }</td>
  <td>
    <input type="hidden" value="${list.board_del }" class="del" />
    <c:choose>
      <c:when test="${list.board_del eq 1}">
        <i class="fas fa-fw fa-regular fa-eye bdel"></i>
      </c:when>
      <c:otherwise>
        <i class="fas fa-fw fa-regular fa-eye-slash bdel"></i>
      </c:otherwise>
    </c:choose>
  </td>
</tr>

 

ajax 로 받아오기

$('.bdel').on('click', function() {
  let eyes = $(this); // 눈 모양 아이콘
  let bno = $(this).parent().siblings('.bno'); // 게시글 번호
  let del = $(this).siblings('.del'); // 게시글의 삭제 여부
  let className = $(this).parents('tr'); // 테이블의 행 받아오기
      
  // alert(bno.text() + " : " + del.val());
      
  $.ajax({
    url: '/admin/postDel',
    type: 'post',
    dataType: 'text',
    data: {'board_no': bno.text(), 'board_del' : del.val()},
    success: function(result) {
      if (result == 1) {
        if (del.val() == 1) {
          className.attr('class', 'row0'); // 행의 class 이름을 변경
          del.val('0'); // del 의 밸류 값 변경
          eyes.attr('class', 'fas fa-fw fa-regular fa-eye-slash bdel'); // 눈의 아이콘 변경
        } else {
          del.val('1');
          className.attr('class', 'row1');
          eyes.attr('class', 'fas fa-fw fa-regular fa-eye bdel');
        }
      } else {
        alert("수정 실패");
      }
    },
    error: function(error) {
      alert("ajax 통신 오류 " + error);
    }
  });
});

 

Controller 에서부터 Service, Repository 까지

@PostMapping("/postDel")
@ResponseBody
public int postDel(BoardDTO dto) {
//    (@RequestParam(value = "board_no") String board_no,
//    @RequestParam(value = "board_no") String board_del) {
  int result = adminService.postDel(dto);
  return result;
}

// Service
public int postDel(BoardDTO dto) {
  return adminRepository.postDel(dto);
}

// Repository
public int postDel(BoardDTO dto) {
  return sqlSession.update("admin.postDel", dto);
}
<update id="postDel" parameterType="boardDTO">
  <choose>
    <when test="board_del == 0">
      update board set board_del = '1' where board_no = #{board_no}
    </when>
    <otherwise>
      update board set board_del = '0' where board_no = #{board_no}
    </otherwise>
  </choose>
</update>

<!-- Mapper 는 이거로도 처리 가능 -->
<update id="postDel" parameterType="Integer">
  Update board SET 
  board_del= CASE WHEN board_del='0' THEN '1' ELSE '0' END 
  WHERE board_no=#{no}
</update>