SpringBoot with JPA 프로젝트 6.조회,수정,삭제,검색 구현

mingki·2022년 2월 1일
0

SpringBoot & JPA

목록 보기
10/26


📚 공부한 책 : 코드로배우는 스프링 부트 웹프로젝트
❤️ github 주소 : https://github.com/qkralswl689/LearnFromCode/tree/main/guestbook2022

1.작성된 게시물 조회

작성된 게시물의 번호를 클릭하면 상세내용을 조회할 수 있다

☆ 1-1.서비스 구현

  • service interface 작성
import com.example.guestbook2022.dto.GuestbookDTO;

public interface GuestbookService {

    GuestbookDTO read(Long gno);
   
}
  • service 구현클래스 작성

    findById()를 통해 엔티티 객체를 가져왔다면 entityToDto()를 이용해 엔티티 객체를 DTO로 변환해 반환한다

import com.example.guestbook2022.dto.GuestbookDTO;
import com.example.guestbook2022.entity.Guestbook;
import com.example.guestbook2022.repository.GuestbookRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;


@Service
@RequiredArgsConstructor // 의존성 자동 주입
public class GuestbookServiceImpl implements GuestbookService{

    private final GuestbookRepository repository;

    @Override
    public GuestbookDTO read(Long gno) {

        Optional<Guestbook> result = repository.findById(gno);
				// findById()를 통해 엔티티 객체를 가져왔다면 entityToDto()를 이용해 엔티티 객체를 DTO로 변환해 반환한다
        return result.isPresent() ? entityToDto(result.get()) : null;
    }

}

☆ 1-2.컨트롤러 구현

GET방식으로 gno값을 받아 Model에 GuestbookDTO 객체를 담아 전달한다, 추후 다시 목록 페이지로 돌아가는 데이터를 같이 저장하기 위해 PageRequestDTO를 파라미터로 같이 사용한다


import com.example.guestbook2022.dto.GuestbookDTO;
import com.example.guestbook2022.dto.PageRequestDTO;
import com.example.guestbook2022.service.GuestbookService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequiredArgsConstructor // 자동주입
@RequestMapping("/guestbook")
public class GuestbookController {

    private final GuestbookService service;

    @GetMapping({"/read","/modify"})
    							// 다시 목록 페이지로 돌아가는 데이터를 같이 저장하기 위해 PageRequestDTO를 파라미터로 같이 사용한다
    public void read(Long gno,@ModelAttribute("requestDTO") PageRequestDTO requestDTO,Model model){

		// GET방식으로 gno값을 받아 Model에 GuestbookDTO 객체를 담아 전달한다
        GuestbookDTO dto = service.read(gno);

        model.addAttribute("dto",dto);
    }

}

☆ 1-3.thymeleaf 구현

  • readonly 속성을 적용해 수정이 불가하도록 한다
  • dto라는 이름으로 전달된 DTO를 이용해 글의 내용 출력
  • @ModelAttribute로 처리된 requestDTO로 페이지와 관련된 부분 처리
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<th:block th:replace="~{/layout/basic :: setContent(~{this::content} )}">

  <th:block th:fragment="content">
    
    <h1 class="mt-4">GuestBook Read Page</h1>

    <div class="form-group">
      <label >Gno</label>
      									<!--readonly 속성을 적용해 수정이 불가하도록 한다-->
      									<!--dto라는 이름으로 전달된 DTO를 이용해 글의 내용 출력-->
      <input type="text" class="form-control" name="gno" th:value="${=dto.gno}" readonly >
    </div>

    <div class="form-group">
      <label >Title</label>>
      <input type="text" class="form-control" name="title" th:value="${dto.title}" readonly >
    </div>
    <div class="form-group">
      <label >Content</label>
      <textarea class="form-control" rows="5" name="content" readonly>[[${dto.content}]]</textarea>
    </div>
    <div class="form-group">
      <label >Writer</label>
      <input type="text" class="form-control" name="writer" th:value="${dto.writer}" readonly>
    </div>
    <div class="form-group">
      <label >RegDate</label>
      <input type="text" class="form-control" name="regDate" th:value="${#temporals.format(dto.regDate, 'yyyy/MM/dd HH:mm:ss')}" readonly>
    </div>
    <div class="form-group">
      <label >ModDate</label>
      <input type="text" class="form-control" name="modDate" th:value="${#temporals.format(dto.modDate, 'yyyy/MM/dd HH:mm:ss')}" readonly>
    </div>
						<!--@ModelAttribute로 처리된 requestDTO로 페이지와 관련된 부분 처리-->
   <a th:href="@{/guestbook/modify(gno = ${dto.gno}, page=${requestDTO.page})}">
     <button type="button" class="btn btn-primary">Modify</button>
   </a>
    <a th:href="@{/guestbook/list(page=${requestDTO.page})}">
      <button type="button" class="btn btn-info">List</button>
    </a>

  </th:block>

</th:block>
  • 화면 결과

2.작성된 게시물 수정/삭제

  • 수정시 : POST 방식으로 이루어져야 한다
  • 고려사항
    - 수정시 수정해야하는 내용(제목,내용,글번호)이 전달되어야한다
    - 수정후 목록페이지로 이동하거나 조회페이지로 이동해야한다 (기존의 페이지 번호를 유지하는것이 좋다)

☆ 2-1.서비스 구현

  • service interface 작성
import com.example.guestbook2022.dto.GuestbookDTO;

public interface GuestbookService {

    void remove(Long gno);

    void modify(GuestbookDTO dto);

}
  • service 구현 클래스 작성
import com.example.guestbook2022.dto.GuestbookDTO;
import com.example.guestbook2022.entity.Guestbook;
import com.example.guestbook2022.repository.GuestbookRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;


@Service
@RequiredArgsConstructor // 의존성 자동 주입
public class GuestbookServiceImpl implements GuestbookService{

    private final GuestbookRepository repository;

    @Override
    public void remove(Long gno) {
        repository.deleteById(gno);
    }

    @Override
    public void modify(GuestbookDTO dto) {

        Optional<Guestbook> result = repository.findById(dto.getGno());

        if(result.isPresent()){

            Guestbook entity = result.get();

            entity.changeTitle(dto.getTitle());
            entity.changeContent(dto.getContent());

            repository.save(entity);
        }
    }
}

☆ 2-2.컨트롤러 구현

수정 : 수정해야 하는 글의 정보를 가지는 GuestbookDTO, 기존 페이지 정보 유지를 위한 PageRequestDTO 가 필요하다
삭제 : POST방식으로 gno 값을 전달하고 삭제후 다시 목록의 첫 페이지로 이동한다

import com.example.guestbook2022.dto.GuestbookDTO;
import com.example.guestbook2022.dto.PageRequestDTO;
import com.example.guestbook2022.service.GuestbookService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

@Controller
@RequiredArgsConstructor // 자동주입
@RequestMapping("/guestbook")
public class GuestbookController {

    private final GuestbookService service;


    @GetMapping({"/read","/modify"})
    public void read(Long gno,@ModelAttribute("requestDTO") PageRequestDTO requestDTO,Model model){

        GuestbookDTO dto = service.read(gno);

        model.addAttribute("dto",dto);
    }

    @PostMapping("/remove")
    public String remove(Long gno, RedirectAttributes redirectAttributes){
    
	//  POST방식으로 gno 값을 전달하고 삭제후 
        service.remove(gno);

        redirectAttributes.addFlashAttribute("msg",gno);
        
	// 다시 목록의 첫 페이지로 이동한다
        return "redirect:/guestbook/list";
    }

    @PostMapping("modify")
    public String modify(GuestbookDTO dto,@ModelAttribute("requestDTO") PageRequestDTO requestDTO,RedirectAttributes redirectAttributes){
        service.modify(dto);

        redirectAttributes.addAttribute("page",requestDTO.getPage());
        redirectAttributes.addAttribute("gno",dto.getGno());

        return "redirect:/guestbook/read";
    }
  
}

☆ 2-3.thymeleaf 구현

  • 수정/삭제 작업을 POST 방식으로 처리하므로 form 태그로 수정하는 애용을 감싸도록 처리한다
  • 수정시 기존 페이지번호를 유지하기위해 페이지 번호를 전달한다
  • Remove 버튼을 클릭하면 form 태그의 action 속성과 method 속성을 조정한다
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">

<th:block th:replace="~{/layout/basic :: setContent(~{this::content} )}">

    <th:block th:fragment="content">

        <h1 class="mt-4">GuestBook Modify Page</h1>
		<!--수정/삭제 작업을 POST 방식으로 처리하므로 form 태그로 수정하는 애용을 감싸도록 처리한다-->
        <form action="/guestbook/modify" method="post">

            <!--페이지 번호 : 수정시 기존 페이지번호를 유지하기위해 페이지 번호를 전달한다  -->
            <input type="hidden" name="page" th:value="${requestDTO.page}">
        
            <div class="form-group">
                <label >Gno</label>
                <input type="text" class="form-control" name="gno" th:value="${dto.gno}" readonly >
            </div>

            <div class="form-group">
                <label >Title</label>>
                <input type="text" class="form-control" name="title" th:value="${dto.title}" >
            </div>
            <div class="form-group">
                <label >Content</label>
                <textarea class="form-control" rows="5" name="content">[[${dto.content}]]</textarea>
            </div>
            <div class="form-group">
                <label >Writer</label>
                <input type="text" class="form-control" name="writer" th:value="${dto.writer}" readonly>
            </div>
            <div class="form-group">
                <label >RegDate</label>
                <input type="text" class="form-control" th:value="${#temporals.format(dto.regDate, 'yyyy/MM/dd HH:mm:ss')}" readonly>
            </div>
            <div class="form-group">
                <label >ModDate</label>
                <input type="text" class="form-control" th:value="${#temporals.format(dto.modDate, 'yyyy/MM/dd HH:mm:ss')}" readonly>
            </div>

        </form>

        <button type="button" class="btn btn-primary modifyBtn">Modify</button>

        <button type="button" class="btn btn-info listBtn">List</button>

        <button type="button" class="btn btn-danger removeBtn">Remove</button>

        <script th:inline="javascript">

            var actionForm = $("form"); //form 태그 객체

          <!-- Remove 버튼을 클릭하면 form 태그의 action 속성과 method 속성을 조정한다-->
            $(".removeBtn").click(function(){

                actionForm
                    .attr("action", "/guestbook/remove")
                    .attr("method","post");

                actionForm.submit();

            });

            $(".modifyBtn").click(function() {

                if(!confirm("수정하시겠습니까?")){
                    return ;
                }

                actionForm
                    .attr("action", "/guestbook/modify")
                    .attr("method","post")
                    .submit();
            });

            $(".listBtn").click(function() {

                var pageInfo = $("input[name='page']");
          
                actionForm.empty(); //form 태그의 모든 내용을 지우고
                actionForm.append(pageInfo); // 목록 페이지 이동에 필요한 내용을 다시 추가
            
                actionForm
                    .attr("action", "/guestbook/list")
                    .attr("method","get");

               actionForm.submit(); 

            })

        </script>

    </th:block>

</th:block>
  • 화면

3.게시물 검색

검색 처리는 서버 사이드처리, 화면쪽의 처리로 나눌 수 있다

  • 서버 사이드 처리
    - PageRequestDTO에 검색 타입과 키워드 추가
    - 서비스에서 Querydsl 이용해 검색 처리
  • 검색 항목 정의
    - 제목(t),내용(c),작성자(w)

☆ 3-1.PageRequestDTO 클래스 수정

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;

@Builder
@AllArgsConstructor
@Data
public class PageRequestDTO { 
    private int page;
    private int size;
    
    // 검색 처리를 위해 추가
    private String type;
    private String keyword;


    public PageRequestDTO(){
        this.page = 1;
        this.size = 10;
    }

    public Pageable getPageable(Sort sort){
        return PageRequest.of(page -1, size,sort);
    }
}

☆ 3-2.service 구현 클래스 작성

  • getList() 메소드에도 적용
  • PageRequestDTO 를 파라미터로 받아 검색조건이 있는 경우 conditionBuilder 변수를 생성해 각 검색조건을 or로 연결해 처리한다
  • 검색 조건이 없다면 gno > 0 으로만 생성된다
import com.example.guestbook2022.dto.GuestbookDTO;
import com.example.guestbook2022.dto.PageRequestDTO;
import com.example.guestbook2022.dto.PageResultDTO;
import com.example.guestbook2022.entity.Guestbook;
import com.example.guestbook2022.entity.QGuestbook;
import com.example.guestbook2022.repository.GuestbookRepository;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.types.dsl.BooleanExpression;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;


@Service
@RequiredArgsConstructor // 의존성 자동 주입
public class GuestbookServiceImpl implements GuestbookService{

    private final GuestbookRepository repository;
		
        // 외 코드 생략
        @Override
    public PageResultDTO<GuestbookDTO, Guestbook> getList(PageRequestDTO requestDTO) {

        Pageable pageable = requestDTO.getPageable(Sort.by("gno").descending());

        BooleanBuilder booleanBuilder = getSearch(requestDTO); // 검색 조건 처리

        Page<Guestbook> result = repository.findAll(booleanBuilder,pageable); // Querydsl 사용

        Function<Guestbook,GuestbookDTO> fn = (entity -> entityToDto(entity));
        return new PageResultDTO<>(result,fn);
    }


    private BooleanBuilder getSearch(PageRequestDTO requestDTO){ // Querydsl 처리

        String type = requestDTO.getType();

        BooleanBuilder booleanBuilder = new BooleanBuilder();

        QGuestbook qGuestbook = QGuestbook.guestbook;

        String keyword = requestDTO.getKeyword();

	// 검색 조건이 없다면 gno > 0 으로만 생성된다
        BooleanExpression expression = qGuestbook.gno.gt(0L); // gno > 0 조건만 생성

        booleanBuilder.and(expression);

        if(type == null || type.trim().length() == 0 ){ // 검색 조건이 없는경우
            return booleanBuilder;
        }

        // 검색 조건 작성
        // PageRequestDTO 를 파라미터로 받아 검색조건이 있는 경우 conditionBuilder 변수를 생성해 각 검색조건을 or로 연결해 처리한다
        BooleanBuilder conditionBuilder = new BooleanBuilder();

        if(type.contains("t")){
            conditionBuilder.or(qGuestbook.title.contains(keyword));
        }
        if(type.contains("c")){
            conditionBuilder.or(qGuestbook.content.contains(keyword));
        }
        if(type.contains("w")){
            conditionBuilder.or(qGuestbook.writer.contains(keyword));
        }

        // 모든 조건 통합
        booleanBuilder.and(conditionBuilder);

        return booleanBuilder;
    }
}

☆ 3-3.thymeleaf 수정

- list.html
  • PageRequestDTO를 이용해 검색 타입에 맞게 자동으로 선택될 수 있도록 구성
  • Search 버튼을 클릭하면 무조건 1페이지를 지정하도록 한다
  • Clear 버튼을 클릭하면 모든 검색 조건 없이 새로 목록 페이지를 보여준다
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">

<th:block th:replace="~{/layout/basic :: setContent(~{this::content} )}">

    <th:block th:fragment="content">

       <h1>gestbook test
           <span>
                <a th:href="@{/guestbook/register}">
                    <button type="button" class="btn btn-outline-primary">REGISTER
                    </button>
                </a>
            </span>
       </h1>
      
      <!--추가-->		
        <form action="/guestbook/list" method="get" id="searchForm">
            <div class="input-group">
              <!--Search 버튼을 클릭하면 무조건 1페이지를 지정하도록 한다-->
                <input type="hidden" name="page" value = "1">
                <div class="input-group-prepend">
                    <select class="custom-select" name="type">
                      <!--PageRequestDTO를 이용해 검색 타입에 맞게 자동으로 선택될 수 있도록 구성-->
                        <option th:selected="${pageRequestDTO.type == null}">-------</option>
                        <option value="t" th:selected="${pageRequestDTO.type =='t'}" >제목</option>
                        <option value="c" th:selected="${pageRequestDTO.type =='c'}"  >내용</option>
                        <option value="w"  th:selected="${pageRequestDTO.type =='w'}" >작성자</option>
                        <option value="tc"  th:selected="${pageRequestDTO.type =='tc'}" >제목 + 내용</option>
                        <option value="tcw"  th:selected="${pageRequestDTO.type =='tcw'}" >제목 + 내용 + 작성자</option>
                    </select>
                </div>
                <input class="form-control" name="keyword" th:value="${pageRequestDTO.keyword}">
                <div class="input-group-append" id="button-addon4">
                    <button class="btn btn-outline-secondary btn-search" type="button">Search</button>
                    <button class="btn btn-outline-secondary btn-clear" type="button">Clear</button>
                </div>
            </div>
        </form>

        <table class="table table-striped">
            <thead>

            <tr>
                <th scope="col">Gno</th>
                <th scope="col">Title</th>
                <th scope="col">Writer</th>
                <th scope="col">Regdate</th>

            </tr>
            </thead>
            <tbody>
		<!--수정 : type 과 keyword 항목 추가-->	
         <tr th:each="dto : ${result.dtoList}" >
                <th scope="row">
                    <a th:href="@{/guestbook/read(gno = ${dto.gno},
                    page= ${result.page},
                    type=${pageRequestDTO.type} ,
                    keyword = ${pageRequestDTO.keyword})}">
                        [[${dto.gno}]]
                    </a>
                </th>
                <td>[[${dto.title}]]</td>
                <td>[[${dto.writer}]]</td>
                <td>[[${#temporals.format(dto.regDate, 'yyyy/MM/dd')}]]</td>
            </tr>

            </tbody>
        </table>
      <!--수정 : type 과 keyword 항목 추가-->	
        <ul class="pagination h-100 justify-content-center align-items-center">
            <li class="page-item " th:if="${result.prev}">
                <a class="page-link" th:href="@{/guestbook/list(page= ${result.start -1},
                    type=${pageRequestDTO.type} ,
                    keyword = ${pageRequestDTO.keyword} ) }" tabindex="-1">Previous</a>
            </li>

            <li th:class=" 'page-item ' + ${result.page == page?'active':''} " th:each="page: ${result.pageList}">
                <a class="page-link" th:href="@{/guestbook/list(page = ${page} ,
                   type=${pageRequestDTO.type} ,
                   keyword = ${pageRequestDTO.keyword}  )}">
                    [[${page}]]
                </a>
            </li>

            <li class="page-item" th:if="${result.next}">
                <a class="page-link" th:href="@{/guestbook/list(page= ${result.end + 1} ,
                    type=${pageRequestDTO.type} ,
                    keyword = ${pageRequestDTO.keyword} )}">Next</a>
            </li>

        </ul>

        <div class="modal" tabindex="-1" role="dialog">
            <div class="modal-dialog" role="document">
                <div class="modal-content">
                    <div class="modal-header">
                        <h5 class="modal-title">Modal title</h5>
                        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                            <span aria-hidden="true">&times;</span>
                        </button>
                    </div>
                    <div class="modal-body">
                        <p>Modal body text goes here.</p>
                    </div>
                    <div class="modal-footer">
                        <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
                        <button type="button" class="btn btn-primary">Save changes</button>
                    </div>
                </div>
            </div>
        </div>

        <script th:inline="javascript">
          
            var msg = [[${msg}]];

            console.log(msg);

            if(msg){
                $(".modal").modal();
            }
          	<!--수정-->	
            var searchForm = $("#searchForm");

            $('.btn-search').click(function(e){

                searchForm.submit();

            });

          // Clear 버튼을 클릭하면 모든 검색 조건 없이 새로 목록 페이지를 보여준다
            $('.btn-clear').click(function(e){

                searchForm.empty().submit();

            });


        </script>

    </th:block>

</th:block>
- read.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">

<th:block th:replace="~{/layout/basic :: setContent(~{this::content} )}">

    <th:block th:fragment="content">

        <h1 class="mt-4">GuestBook Read Page</h1>

        <div class="form-group">
            <label>Gno</label>
            <input type="text" class="form-control" name="gno" th:value="${dto.gno}" readonly>
        </div>

        <div class="form-group">
            <label>Title</label>>
            <input type="text" class="form-control" name="title" th:value="${dto.title}" readonly>
        </div>
        <div class="form-group">
            <label>Content</label>
            <textarea class="form-control" rows="5" name="content" readonly>[[${dto.content}]]</textarea>
        </div>
        <div class="form-group">
            <label>Writer</label>
            <input type="text" class="form-control" name="writer" th:value="${dto.writer}" readonly>
        </div>
        <div class="form-group">
            <label>RegDate</label>
            <input type="text" class="form-control" name="regDate"
                   th:value="${#temporals.format(dto.regDate, 'yyyy/MM/dd HH:mm:ss')}" readonly>
        </div>
        <div class="form-group">
            <label>ModDate</label>
            <input type="text" class="form-control" name="modDate"
                   th:value="${#temporals.format(dto.modDate, 'yyyy/MM/dd HH:mm:ss')}" readonly>
        </div>

      <!-- 수정 : type 과 keyword 항목 추가-->
           <a th:href="@{/guestbook/modify(gno = ${dto.gno}, page=${requestDTO.page}, type=${requestDTO.type}, keyword =${requestDTO.keyword})}">
             <button type="button" class="btn btn-primary">Modify</button>
           </a>

           <a th:href="@{/guestbook/list(page=${requestDTO.page} , type=${requestDTO.type}, keyword =${requestDTO.keyword})}">
             <button type="button" class="btn btn-info">List</button>
           </a>

    </th:block>

</th:block>
- modify.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">

<th:block th:replace="~{/layout/basic :: setContent(~{this::content} )}">

    <th:block th:fragment="content">

        <h1 class="mt-4">GuestBook Modify Page</h1>

        <form action="/guestbook/modify" method="post">

            <!--페이지 번호  -->
            <input type="hidden" name="page" th:value="${requestDTO.page}">
          <!--수정 : type 과 keyword 항목 추가-->	
            <input type="hidden" name="type" th:value="${requestDTO.type}" >
            <input type="hidden" name="keyword" th:value="${requestDTO.keyword}" >


            <div class="form-group">
                <label >Gno</label>
                <input type="text" class="form-control" name="gno" th:value="${dto.gno}" readonly >
            </div>

            <div class="form-group">
                <label >Title</label>
                <input type="text" class="form-control" name="title" th:value="${dto.title}" >
            </div>
            <div class="form-group">
                <label >Content</label>
                <textarea class="form-control" rows="5" name="content">[[${dto.content}]]</textarea>
            </div>
            <div class="form-group">
                <label >Writer</label>
                <input type="text" class="form-control" name="writer" th:value="${dto.writer}" readonly>
            </div>
            <div class="form-group">
                <label >RegDate</label>
                <input type="text" class="form-control" th:value="${#temporals.format(dto.regDate, 'yyyy/MM/dd HH:mm:ss')}" readonly>
            </div>
            <div class="form-group">
                <label >ModDate</label>
                <input type="text" class="form-control" th:value="${#temporals.format(dto.modDate, 'yyyy/MM/dd HH:mm:ss')}" readonly>
            </div>

        </form>

        <button type="button" class="btn btn-primary modifyBtn">Modify</button>

        <button type="button" class="btn btn-info listBtn">List</button>

        <button type="button" class="btn btn-danger removeBtn">Remove</button>

        <script th:inline="javascript">

            var actionForm = $("form"); //form 태그 객체

            $(".removeBtn").click(function(){

                actionForm
                    .attr("action", "/guestbook/remove")
                    .attr("method","post");

                actionForm.submit();

            });

            $(".modifyBtn").click(function() {

                if(!confirm("수정하시겠습니까?")){
                    return ;
                }

                actionForm
                    .attr("action", "/guestbook/modify")
                    .attr("method","post")
                    .submit();
            });

             $(".listBtn").click(function() {

                //var pageInfo = $("input[name='page']");
                var page = $("input[name='page']");
                var type = $("input[name='type']");
                var keyword = $("input[name='keyword']");

                actionForm.empty(); //form 태그의 모든 내용을 지우고

           	<!--수정 : type 과 keyword 항목 추가-->	
                actionForm.append(page);
                actionForm.append(type);
                actionForm.append(keyword);


                actionForm
                    .attr("action", "/guestbook/list")
                    .attr("method","get");

               actionForm.submit();

            })

        </script>


    </th:block>

</th:block>

☆ 3-4.컨트롤러 클래스 수정

import com.example.guestbook2022.dto.GuestbookDTO;
import com.example.guestbook2022.dto.PageRequestDTO;
import com.example.guestbook2022.service.GuestbookService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

@Controller
@RequiredArgsConstructor // 자동주입
@RequestMapping("/guestbook")
public class GuestbookController {

    private final GuestbookService service;

    @PostMapping("modify")
    public String modify(GuestbookDTO dto,@ModelAttribute("requestDTO") PageRequestDTO requestDTO,RedirectAttributes redirectAttributes){
        service.modify(dto);

        redirectAttributes.addAttribute("page",requestDTO.getPage());
        redirectAttributes.addAttribute("gno",dto.getGno());

        // 검색조건 추가
        redirectAttributes.addAttribute("type",requestDTO.getType());
        redirectAttributes.addAttribute("keyword",requestDTO.getKeyword());

        return "redirect:/guestbook/read";
    }

}
  • 화면
profile
비전공초보개발자

0개의 댓글