Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
Tags
- resttemplate
- ㅒ
- 처음 만나는 AI 수학 with Python
- network configuration
- 알파회계
- 페이징
- 친절한SQL튜닝
- 코드로배우는스프링부트웹프로젝트
- 데비안
- 선형대수
- d
- Kernighan의 C언어 프로그래밍
- 구멍가게코딩단
- 목록처리
- 코드로배우는스프링웹프로젝트
- 티스토리 쿠키 삭제
- 이터레이터
- 스프링 시큐리티
- 처음 만나는 AI수학 with Python
- iterator
- baeldung
- 서버설정
- 네트워크 설정
- 자료구조와 함께 배우는 알고리즘 입문
- 자바편
- 리눅스
- /etc/network/interfaces
- 스프링부트핵심가이드
- 자료구조와함께배우는알고리즘입문
- GIT
Archives
- Today
- Total
bright jazz music
guestbook: 11. 검색처리(3) 본문
1. 조회 페이지 검색 처리
기존의 조회 페이지는 Page 값만 처리했다.
따라서 다시 목록으로 돌아가는 링크 앞에서 처리한 것과 동일하게 type과 keyword값을 추가해 줘야 한다.
조회 페이지는 현재 PageRequestDTO 컨트롤러에서 @ModelAttribute를 이용해서 'requestDTO'라는 이름으로 처리하고 있다.
//GuestbookController.java
@GetMapping({"/read", "/modify"}) // modify도 추가하였다. 조회/수정을 위한 메서드
public void read(long gno, @ModelAttribute("requestDTO") PageRequestDTO requestDTO, Model model){
log.info("gno: " + gno);
GuestbookDTO dto = service.read(gno);
model.addAttribute("dto", dto);
}
조회 메서드.
2. 조회 페이지에서의 하단 링크 처리(type, keyword 추가)
<!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 area 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>
<a th:href="@{/guestbook/modify(gno=${dto.gno}, page=${requestDTO.page},
type=${requestDTO.type}, keyword=${requestDTO.keyword})}"><!--type과 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})}"><!--type과 keyword 추가 ##################-->
<button type="button" class="btn btn-info">List</button>
</a>
</th:block>
</th:block>
</html>
조회 페이지의 검색처리는 다음과 같은 순서로 확인할 수 있다.
- 목록 페이지에서 특정 조건으로 검색 수행
- 검색 완료한 상태에서 특정 글을 선택해서 조회 페이지로 이동
- 조회 페이지에서 목록 페이지로 이동하는 버튼 클릭해서 이동
3. 수정 작업 후 이동 처리(다시 조회 페이지로 돌아오기)
Controller에서 작업이 끝난 후 RedirectAttributes를 이용하는 경우가 존재한다.
- 등록처리: 1페이지로 이동
- 삭제처리: 2페이지로 이동
- 수정처리: 조회 페이지로 이동
이 가운데 수정은 수정을 완료하고 다시 조회 페이지로 돌아오는 편이 좋다.
다시 돌아오려면 검색조건을 유지해야 한다.
따라서 수정 페이지에서도 page 뿐만 아니라 type과 keyword를 처리해야 한다.
현재
따라서 수정 페이지(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"> <!-- form태그로 감싸기 -->
<!-- 페이지 번호: 수정 완료 후에도 동일한 정보를 유지하도록 하기 위해 추가!!!!-->
<input type="hidden" name="page" th:value="${requestDTO.page}">
<input type="hidden" name="type" th:value="${requestDTO.type}">
<input type="hidden" name="keyword" th:value="${requestDTO.keyword}">
<!--수정 완료 후에도 쿼리스트링에 type과 keyword를 유지하기 위해 추가하였다.############################### -->
<div class="form-group">
<label>Gno</label> <!--수정불가-->
<input type="text" class="form-control" name="gno" th:value="${dto.gno}" readonly>
<!--
name 속성은 DTO의 프로퍼티와 같게 해줘야 한다. DTO에서 소문자로 선언했으므로
여기서도 소문자 gno로 해야 한다. 대문자로 했다가 아래와 같은 에러를 만났다.
아래의 태그들의 속성 값도 전부 소문자로 해줄 것.
java.lang.IllegalStateException:
Optional long parameter 'gno' is present but cannot be translated into a null value
due to being declared as a primitive type. Consider declaring it as object wrapper
for the corresponding primitive type.
-->
</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 area 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> <!--수정불가, name 속성도 제거. 화면 수정 자체도 불가하고 jpa에서 자동처리 할 것이기 때문-->
<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> <!--수정불가, name 속성도 제거. 화면 수정 자체도 불가하고 jpa에서 자동처리 할 것이기 때문-->
<input type="text" class="form-control"
th:value="${#temporals.format(dto.modDate, 'yyyy/MM/dd HH:mm:ss')}" readonly>
</div>
</form> <!-- form태그로 감싸기 -->
<!--수정/삭제는 form 태그의 action을 이용해서 처리할 수 있음. 이 부분은 추후 처리-->
<!-- 버튼 구분을 위해 class 속성에 구분용 단어를 첨자하였다. -->
<!--<button type="button" class="btn btn-primary">Modify</button>-->
<button type="button" class="btn btn-primary modifyBtn">Modify</button>
<!--<button type="button" class="btn btn-info">List</button>-->
<button type="button" class="btn btn-info listBtn">List</button>
<!--<button type="button" class="btn btn-danger">Remove</button>-->
<button type="button" class="btn btn-danger removeBtn">Remove</button>
<script th:inline="javascript">
var actionForm = $("form"); //form 태그 객체
$(".removeBtn").click(function(){
//삭제 버튼 처리. 버튼을 누르면 form태그의 action 속성과 method 속성을 조정한다.
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태그의 모든 내용 삭제
// actionForm.append(pageInfo); //목록 페이지 이동에 필요한 내용 재 추가
actionForm.append(page); //수정 페이지에서 다시 목록 페이지로 이동할 때
actionForm.append(type); //타입 추가
actionForm.append(keyword); //키워드 추가
actionForm
.attr("action", "/guestbook/list")
.attr("method", "get")
// console.log(actionForm.html()); //먼저 확인 후에 주석 처리
actionForm.submit();
})
</script>
</th:block>
</th:block>
</html>
여기서 수정한 것은 <form> 태그를 보낼 때 page뿐만 아니라 type과 keyword부분도 함께 보관하도록 한 것이다.
이렇게 저장된 정보는 컨트롤러로 전송된다. 그러고 나면 keyword가 type이 쿼리스트링에 포함된 적합한 페이지를 반환 받는다.
따라서 다음은 이렇게 저장된 <form> 태그의 정보가 Controller에서 사용될 수 있도록 Controller를 수정해 줘야 한다.
3. Controller 수정
//GuestbookController.java
package com.example.guestbook.controller;
import com.example.guestbook.dto.GuestbookDTO;
import com.example.guestbook.dto.PageRequestDTO;
import com.example.guestbook.dto.PageResultDTO;
import com.example.guestbook.entity.Guestbook;
import com.example.guestbook.service.GuestbookService;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
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
@RequestMapping("/guestbook")
@Log4j2
@RequiredArgsConstructor //자동 주입을 위한 어노테이션
public class GuestbookController {
private final GuestbookService service; // final로 선언
@GetMapping("/")
public String index(){
return "redirect:/guestbook/list";
}
@GetMapping("/list")
public String list(PageRequestDTO pageRequestDTO, Model model){
log.info("list...................." + pageRequestDTO);
// model에 result를 key로 담아서 list 페이지에 뿌려준다.
model.addAttribute("result", service.getList(pageRequestDTO));
return "/guestbook/list";
}
/*
SpringDAta JPA를 이용하는 경우 @Pageable 어노테이션으로 Pageable 타입을 이용할 수도 있고,
application.properties에 0이 아닌 1부터 페이지 번호를 시작하도록 받을 수 있도록 처리할 수도 있다.
예제에서는 그냥 0부터 받는 방식을 사용하였다. 추후 검색조건 등과 같이 추가로 전달되어야 하는 데이터가
많을 경우 더욱 복잡해질 수 있기 때문이다.
*/
@GetMapping("/register")
public void register(){
log.info("register get...");
}
@PostMapping("/register")
public String registerPost(GuestbookDTO dto, RedirectAttributes redirectAttributes){
log.info("dto..." + dto);
//새로 추가된 엔티티의 번호
Long gno = service.register(dto);
redirectAttributes.addFlashAttribute("msg", gno);
return "redirect:/guestbook/list";
/*
* 등록 작업은 GET 방식에서는 화면을 보여주고 POST 방식에서는 처리 후에 목록페이지로 이동하도록 설계.
* 이 때 RedirectAttributes를 이용해서 한 번만 화면에서 'msg'라는 이름의 변수를 사용할 수 있도록 처리.
* addFlashAttribute()는 단 한 번만 데이터를 전달하는 용도로 사용함.
* --> 브라우저에 전달되는 'msg'를 이용해서 화면 창에 모달 창을 보여주는 용도로 사용.
* */
}
@GetMapping({"/read", "/modify"}) // modify도 추가하였다. 조회/수정을 위한 메서드
public void read(long gno, @ModelAttribute("requestDTO") PageRequestDTO requestDTO, Model model){
log.info("gno: " + gno);
GuestbookDTO dto = service.read(gno);
model.addAttribute("dto", dto);
}
@PostMapping("/remove") //삭제를 위한 메서드
public String remove(long gno, RedirectAttributes redirectAttributes) {
System.out.println("#######################################################################");
log.info("gno: " + 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){
log.info("post modify.............");
log.info("dto" + dto);
service.modify(dto);
redirectAttributes.addAttribute("page", requestDTO.getPage());
redirectAttributes.addAttribute("type", requestDTO.getType()); //수정 후에도 타입을 유지하기 위해 추가#################
redirectAttributes.addAttribute("keyword", requestDTO.getKeyword()); // 수정 후에도 키워드를 유지하기 위해 추가###############
redirectAttributes.addAttribute("gno", dto.getGno());
return "redirect:/guestbook/read";
/* 파라미터
* GuestbookDTO : 수정해야 하는 글의 정보를 보유
* PageRequestDTO : 기존 페이지 정보를 유지하기 위한 목적
* RedirectAttributes : 처리 후 리다이렉트. 이 때 목록 페이지로 이동. 기존 페이지 정보도 유지!!
* */
}
}
'Framework > Spring' 카테고리의 다른 글
[bootBoard] N:1(다대일) 연관관계: 2. 프로젝트 생성 (0) | 2022.07.25 |
---|---|
[bootBoard] N:1(다대일) 연관관계: 1.연관관계와 DB 설계 (0) | 2022.07.25 |
guestbook : 11. 검색처리(2) (0) | 2022.07.23 |
guestbook : 11. 검색처리(1) (0) | 2022.07.22 |
guestbook : 10. guestbook 게시글 수정/삭제 처리(3) (0) | 2022.07.21 |
Comments