본문 바로가기

Spring

240227 스프링 프로젝트

오늘은 공지사항 notice 페이지 만들어보기

 

요구사항 파악해보기

https://github.com/hyunjong-96/Information_Processing_Engineer/blob/main/2.%EC%9A%94%EA%B5%AC%EC%82%AC%ED%95%AD%20%ED%99%95%EC%9D%B8.md

 

여기서 다른 사항들도 확인할 수 있음

 

GitHub - hyunjong-96/Information_Processing_Engineer: 정처기 실기

정처기 실기. Contribute to hyunjong-96/Information_Processing_Engineer development by creating an account on GitHub.

github.com

 

선생님이 준 요구사항들

내 방식대로 조금은 바꿔서 사용

   공지 게시판 notice
NoticeController
NoticeService
NoticeServiceImpl
NoticeDAO
NoticeDTO
notice-mapper.xml

   dto에 들어갈 내용
int nno, ndel, nread, nlike
Stgring ntitle, ncontent, ndate

   DB
table name : notice
column :  nno(int, auto, PK), ndel(int 1, 기본 1), nread(int, 기본 1), nlike(int, 기본 1),
      ntitle(VARCHAR 50), ncontent(VARCHAR 500), ndate(datetime, current timestamp)

   NoticeSerice에 들어갈 추상메소드
public List<NoticeDTO> noticeList();
public NoticeDTO detail(int no);
public int noticeWrite(NoticeDTO);
public int noticeDel(int no);
public int noticeUpdate(NoticeDTO);

 

DTO 만들기

@Getter
@Setter
public class NoticeDTO {
  private int nno, nread;
  private String ntitle, ncontent, ndate, ndel;
}

 

나는 삭제 여부를 enum 으로 하여 String 에 넣었고, 공지사항에 좋아요는 쓰지 않을 것 같아 제외했음

 

 

이번에는 Service 인터페이스를 먼저 만들어 인터페이스를 구현해 사용해보기

public interface NoticeService {
  public List<NoticeDTO> noticeList();
  public NoticeDTO noticeDetail(int nno);
  public int noticeWrite(NoticeDTO dto);
  public int noticeDelete(int nno);
  public int noticeUpdate(NoticeDTO dto);
}

 

NoticeService 를 구현해 사용하는 클래스 만들기

@Service("noticeService")
public class NoticeServiceImpl extends AbstractService implements NoticeService {

  @Autowired
  private NoticeRepository noticeRepository;
  
  @Override
  public List<NoticeDTO> noticeList() {
    return noticeRepository.noticeList();
  }

  @Override
  public NoticeDTO noticeDetail(int nno) {
    return null;
  }

  @Override
  public int noticeWrite(NoticeDTO dto) {
    return 0;
  }

  @Override
  public int noticeDelete(int nno) {
    return 0;
  }

  @Override
  public int noticeUpdate(NoticeDTO dto) {
    return 0;
  }
}

 

mybatis 와 mapper 설정하기

<typeAlias type="org.solbum.dto.NoticeDTO" alias="noticeDTO"/>

<mapper namespace="notice">
  <select id="noticeList" resultType="noticeDTO">
    select nno, ntitle, ncontent, nread,
    date_format(ndate,'%Y-%m-%d %h:%i') as ndate
    from notice where ndel = '1'
  </select>
</mapper>

 

Repository 에서는 기존 AbstractRepository 를 상속받아 SqlSession 을 사용

@Repository
public class NoticeRepository extends AbstractRepository {
  public List<NoticeDTO> noticeList() {
    return sqlSession.selectList("notice.noticeList");
  }
}

 

컨트롤러에서는 @Resource 로 Service 의 지정된 이름으로 Autowired 받아보기

notice.jsp 를 만들고 진행하기

@Controller
public class NoticeController extends AbstractController {
  
  @Resource(name="noticeService")
  private NoticeService noticeService;
  
  @GetMapping("/notice")
  public String noticeList(Model model) {
    List<NoticeDTO> list = noticeService.noticeList();
    model.addAttribute("list", list);
    return "notice";
  }
}

 

기존 게시글 List 를 보여주는 board.jsp 를 가져다가 사용하기

<table class="table table-hover">
  <thead>
    <tr class="table-light">
      <th class="col w15">#</th>
      <th class="col w45">제목</th>
      <th class="col w25">날짜</th>
      <th class="col w15">조회수</th>
    </tr>
  </thead>
  <tbody>
    <c:forEach items="${list }" var="list">
      <tr>
        <td onclick="detail(${list.nno})">${list.nno }</td>
        <td class="title">
          <a href="./noticeDetail?no=${list.nno }">${list.ntitle }</a>
        </td>
        <td>${list.ndate }</td>
        <td>${list.nread }</td>
      </tr>
    </c:forEach>
  </tbody>
</table>

 

DB에 직접 넣은 글이 보이는 모습

 

공지사항을 불러와서 공지사항이 있으면, 공지사항을 불러오고 없으면 없다는 문구 출력하기

<c:choose>
  <c:when test="${fn:length(list) gt 0}">
    <table> </table>
  </c:when>
  <c:otherwise>
   <h4>등록된 공지가 없습니다.</h4>
  </c:otherwise>
</c:choose>

 

공지사항 작성해보기, 공지는 관리자만 적을 수 있게 /admin 을 붙여 사용

// 공지 글 쓰기, 관리자 페이지에서
@GetMapping("admin/noticeWrite")
public String noticeWrite() {
  return "admin/noticeWrite";
}

 

Service 와 Repository, mapper 까지 이어주기

@Override
public int noticeWrite(NoticeDTO dto) {
  return noticeRepository.noticeWrite(dto);
}

public int noticeWrite(NoticeDTO dto) {
  return sqlSession.insert("notice.noticeWrite", dto);
}

 

<insert id="noticeWrite">
  insert into notice (ntitle, ncontent)
  values (#{ntitle}, #{ncontent})
</insert>

 

views 안에 admin 폴더를 만들어 noticeWrite.jsp 생성

 

입력 폼은 간단하게 테스트해보기

<form action="./noticeWrite" method="post">
  <input type="text" name="ntitle"/>
  <textarea type="text" name="ncontent"></textarea>
  <button type="submit">작성완료</button>
</form>

 

여기서 form 안에 ./admin/noticeWrite 로 적으면 /admin/admin/noticeWrite 로 들어가게 됨

이미 /admin 이 붙은 상태이기 때문에 ./noticeWrite 로만 작성

/admin/noticeWrite 로 작성해도 되지만, URL 에 localhost 대신 localhost/web 등 추가 주소가 있는 경우에

해당 주소가 삭제되면서 오류 발생

@PostMapping("/admin/noticeWrite")
public String noticeWrite(NoticeDTO dto) {
//  System.out.println("title : " + dto.getNtitle());
//  System.out.println("content : "  + dto.getNcontent());
  int result = noticeService.noticeWrite(dto); 
//  return "redirect:/notice";
return "";

 

post 로 값 받아 테스트와 기존 작성해둔 Service 로 연결

 

noticeDetail 만들기, 공지 제목을 클릭하면 게시글로 이동하도록 만들기

<td class="title"><a href="./noticeDetail?no=${list.nno }">${list.ntitle }</a></td>

 

Controller 에서 받기

@GetMapping("/noticeDetail")
public String noticeDetail(@RequestParam(value="no", defaultValue = "-1", required = true) int no, Model model) {
  if (no == -1) {
    return "redirect:/error";
  } else {
    NoticeDTO dto = noticeService.noticeDetail(no);
    model.addAttribute("detail", dto);
    return "noticeDetail";
  }
}

 

Service, Repository, mapper 연결

@Override
public NoticeDTO noticeDetail(int nno) {
  return noticeRepository.noticeDetail(nno);
}

public NoticeDTO noticeDetail(int nno) {
  return sqlSession.selectOne("notice.noticeDetail", nno);
}
<select id="noticeDetail" parameterType="Integer" resultType="noticeDTO">
  select nno, ntitle, ncontent, nread, 
  date_format(ndate, '%Y-%m-%d %h:%i') as ndate 
  from notice where ndel = '1' and nno = #{nno}
</select>

 

기존 detail 페이지를 그대로 사용하기

<div class="container">
  <div class="text-center">
    <h2 class="section-heading text-uppercase">자세히 보기</h2>
  </div>
  <div class="row text-center">
    <div class="btitle text-start fs-3">${detail.ntitle }</div>
    <hr>
    <div class="detailInfo">
      <span class="mname">관리자</span>
      <span class="bcount">${detail.nread }</span>
    </div>
    <div class="detailInfo">
      <span class="bdate">
        <a class="" onclick="location.href='./noticeDelete?no=${detail.nno}'">삭제</a>
        <a class="" onclick="location.href='./noticeUpdate?no=${detail.nno}'">수정</a>
      </span>
      <span class="bdate">${detail.ndate }</span>
    </div>
    <hr>
    <div class="bcontent text-start">${detail.ncontent }</div>
  </div>
  <div class="buttonList">
    <button class="btn btn-outline-dark" onclick="location.href='./notice'">/notice</button>
  </div>
  <hr id="commentHr">
</div>

 

공지사항 List 에 페이징 하기

기존 board 에서 사용했던 전자정부 페이징을 가져왔다

전체 글 수를 받아오는 것부터, limit 도 걸고 진행

https://alisyabob.tistory.com/243

 

전자정부프레임워크 Pagination 페이징처리

전자정부프레임워크 Pagination 페이징처리 기본적으로 전자정부 프레임워크에서는 페이징 처리를 편하게 하기 위해 태그를 제공한다. PaginationInfo는 렌더링에 필요한 데이터가 담겨져있는 빈 클

alisyabob.tistory.com

@GetMapping("/notice")
public String noticeList(Model model, @RequestParam(value = "page", required = false) String page) {
  int currentPageNo = 1;
  if (util.intCheck(page)) { // 여기 수정 필요
    currentPageNo = Integer.valueOf(page);
  }
  // 전체 글 수 받아오기
  int totalRecordCount = noticeService.totalRecordCount();
  PaginationInfo paginationInfo = new PaginationInfo();
  paginationInfo.setCurrentPageNo(currentPageNo); // 현재 페이지 번호
  paginationInfo.setRecordCountPerPage(15); // 한 페이지에 게시되는 게시글 건수
  paginationInfo.setPageSize(10); // 페이지 리스트 사이즈
  paginationInfo.setTotalRecordCount(totalRecordCount); // 총 페이지 수

  List<NoticeDTO> list = noticeService.noticeList(paginationInfo.getFirstRecordIndex());
  model.addAttribute("paginationInfo", paginationInfo);
  model.addAttribute("list", list);
  return "notice";
}

 

List 페이지에서 페이징 추가

<!-- 페이징 만들기 -->
<div class="">
  <ui:pagination paginationInfo="${paginationInfo}" type="text" jsFunction="linkPage" />
</div>

 

글 수정 만들기

먼저 글 수정에 대해 요청이 오면

@GetMapping("/noticeUpdate")
public String noticeUpdate(int no, Model model) {
  NoticeDTO detail = noticeService.noticeUpdate(no);
  if (detail != null) {
    model.addAttribute("detail", detail);
    return "/admin/noticeWrite";
  } else {
    return "redirect:/error";
  }
}

 

해당하는 글 번호를 받아, 글 제목과 내용을 받아옴

@Override
public NoticeDTO noticeUpdate(int no) {
  return noticeRepository.noticeUpdate(no);
}

public NoticeDTO noticeUpdate(int no) {
  return sqlSession.selectOne("notice.noticeUpdate", no);
}
<select id="noticeUpdate" parameterType="Integer" resultType="noticeDTO">
  select ntitle, ncontent from notice where nno = #{no} and ndel = '1'
</select>

 

해서 해당 dto 를 addAttribute 하여 넘김, 넘기는 곳은 noticeWrite.jsp

기존 글쓰기 페이지에 만약 값이 있으면, 없으면에 따라 값이 들어올 지 안들어올 지 체크

 

기존 input 과 textarea 칸에 값 넣은 것을 체크함

<c:if test="${detail.ntitle ne null }">value="${detail.ntitle }"</c:if>
<c:if test="${detail.ntitle ne null }">${detail.ncontent }</c:if>

 

다시 체크해보니,, 글을 수정할 때마다 새로운 글이 생성됨

다시 수정,,

Update를 위한 jsp 생성

 

@PostMapping("/noticeUpdate")
public String noticeUpdate(NoticeDTO dto) {
  int result = noticeService.noticeUpdate(dto);
  if (result == 1) {
    return "redirect:/noticeDetail?no=" + dto.getNno();
  } else {
    return "redirect:/error";
  }
}

 

글 작성 시 Post 로 값을 받아, 해당 글 번호의 제목과 내용 수정

'Spring' 카테고리의 다른 글

240229 스프링 프로젝트  (0) 2024.02.29
240228 스프링 프로젝트  (2) 2024.02.28
240226 스프링 프로젝트  (2) 2024.02.26
240223 스프링 프로젝트  (0) 2024.02.23
240222 스프링 프로젝트  (0) 2024.02.22