연휴가 지나갔다.. ㅠoㅠ
# 잡담코너
GNB
Global Navigation Bar
내가 어느 위치에 있든 고정적으로 보여지는 메뉴 바
LNB
Local Navigation Bar
★복습
1. Controller를 만드는 기준
+ 개발자의 암묵적인? 약속?.. GNB에 있는 바에 있는 대분류 Controller를 두고 그 안에 들어갈 하위 컨트롤러를 만든다..?
2. 로그인 주소는 동일하게 맞추고
+Get 과 Post를 만들어준다. Get으로만 맞춰도 괜찮긴한데 Post로만 맞추는 건 X
+Get은 조회를 하고 싶을 때 그 외 CRUD 중 R 빼고 Post로 한다.
+주소를 아껴야 좋음!
+로그인시 마지막으로 접속한 날자를 남길때 Post를 사용할 수 도있음 입력이니까!
public String signupPost(@ModelAttribute Owner owner) {
System.out.println(owner);
ownerRepository.save(owner);
@ModelAttribute 에 쓰는 명과 save명을 같게
return "redirect:/auth/signup";
Post방식으로 요청을 마무리하면 로그인을 다시하게 됨 들어온게 Post이기에 나온 답도 Post라 Get방식으로 요청을 마무리
# 템플릿을 써서 마무리한게 포워드 라고 함
★학습목표
1. 게시글쓰기
2. 조회, 수정
+ 댓글 작성 및 조회
3. AOP
4. Filter / interceptor
★ 학습
게시글 기능을 구현할 때 필요한 사항
사람마다 다름!!
1. 디자인 - 사용자가 쓸 수 있는 모습을 보여줘야 함!
+ imput , textarea
2. 데이터 베이스 - 작성된 게시글이 저장이 되어야 함! JPA
+ Entity (@Entity, @id)
+ Repository
# JPA를 안쓸경우 create 작성하고 어쩌구 저쩌구 많음
3. Controller - 사용자 요청 -> 응답 (json , redirect, templates)
1. 만들기
html 파일을 만들어준다!
<form action="/board/write" method="post">
<!-- 제목, 내용, .... -->
<!-- name이 제대로 작성이 되어야 백엔드에서 편함 -->
<input type="text" name="title">
<textarea name="content" cols="30" rows="10"></textarea>
<button>작성 완료</button>
</form>
Board.java 만들기
package com.example.basic.model;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import lombok.Data;
@Entity
@Data
public class Board {
@Id @GeneratedValue
// id 없으면 프라이머리 키가 없어서 작동안하고
// @GeneratedValue 순서
int id;
String title;
String content;
}
이렇게 만들어주면 나는 h2를 사용중이기에
h2에 BOARD 파일이 생성!!
작성자칸을 만들면
<th:block th:if="${session.name} == null">
<input type="text" name="write" placeholder="입력해주세요.">
</th:block>
<th:block th:unless="${session.name} == null">
<input type="text" name="write" th:value="${session.name}">
</th:block>
HTML에 작성해주고 Board.java에 String wirte 써주면
이렇게 나오는데 이러면 로그인을 안해도 누구나 다쓰게되니까
세션을 이용해서 로그인을 안 했을 경우 작성을 하지 못하게 튕겨내기
@Autowired
HttpSession session;
@GetMapping("/writer")
public String write() {
String name = (String) session.getAttribute("name");
// trim 앞뒤 공백제거
if(name == null || name.trim().equals("")) {
return "redirect:/auth/signin";
}
return "board/write";
이렇게 작성하면 양식화면에서 튕겨낸다.
이후 로그인 화면으로 이동하게되고 로그인을 하고 들어가면
작성자에 name이 찍혀나온다.
보안조치를 더 해줘야 함...
2. title 리스트 만들기
@GetMapping({"/list","/"}) // 이렇게 하면 board/list써도 되고 board만 해도 이 페이지가 보여지게 됨
public String list(Model model) {
List<Board> boardList = boardRepository.findAll(); //model을 안쓰면 boardList 가 html로 전달 x 그래서 model씀
model.addAttribute("boardList", boardList);
// model을 씀으로써 연결해줌
return "board/list";
}
<ul th:each="board : ${boardList}">
<li th:text="${board}"></li>
</ul>
/ 까지만 써도 보여지게 됨
PageRequest 이용해서 페이지 만들어서 보여주기
@GetMapping({"/list","/"}) // 이렇게 하면 board/list써도 되고 board만 해도 이 페이지가 보여지게 됨
public String list(Model model,
@RequestParam(defaultValue = "1") int p) {
PageRequest page = PageRequest.of(p - 1,2);
Page<Board> boardList = boardRepository.findAll(page); //model을 안쓰면 boardList 가 html로 전달 x 그래서 model씀
model.addAttribute("boardList", boardList);
// model을 씀으로써 연결해줌
return "board/list";
}
이렇게 3페이지에 애들이 나오게됨 여기서 내림차순으로 만든다면
Direction dic = Direction.DESC; //내림차순
Sort sort = Sort.by(dic, "id");
이렇게 작성해주면
내림차순으로 나옴..!
목록에서 상세보기로 가게 만들기
<ul th:each="board : ${boardList}">
<li>
<a href="">
[[ ${board.id} ]] / [[ ${board.title} ]]
</a>
</li>
</ul>
작성해주면
id와 타이틀만 찍혀나옴
3. 상세보기
이제 목록을 클릭시 내용이 보이게 만들면
<ul th:each="board : ${boardList}">
<li>
<!-- th:href !! 꼭 th: 를 입력해야 오류가 없음 -->
<a th:href="@{/board/detail(id=${board.id})}">
[[ ${board.id} ]] / [[ ${board.title} ]]
</a>
</li>
</ul>
list 수정하고 detail이란 HTML 을 만들어준다
<p>번호 : [[${board.id}]]</p>
<p>제목 : [[${board.title}]]</p>
<p>내용 : [[${board.content}]]</p>
<p>작성자 : [[${board.writer}]]</p>
@GetMapping("/detail")
public String detail(
@RequestParam int id, Model model) {
Optional<Board> opt = boardRepository.findById(id);
model.addAttribute("board", opt.get());
return "board/detail";
}
그리고 Controller를 만들어주면 클릭
이렇게 나오게 된다
4. 수정하기
수정을 만들려면 html 을 새로만들고 Controller 을 조금만져주면 된다.
우선 detail.html에서 수정버튼을 만든다 여러 예시가 있음
<!-- 내가 몇번 게시글(id)을 수정할 것인지만 알려주면 됨 -->
<!-- 세션에 id를 담아놨다가 꺼내써도 좋음 -->
<!--board.id 가 없으면 데이터를 뿌려줄? 수 없음 -->
<button th:text="수정" th:onclick="'location=\'/board/update?id=' + ${board.id} '\'' "></button>
<!-- ' 1묶음 ' + 2묶음 ' ' << 3묶음
' '; 문법으로 나타내게 되면 ' 를 못쓰니까 \ 로 ' 를 나타냄 -->
<!-- 접두어/사 namespace // 000: < 이녀석 -->
<a th:href="@{/board/update(id=${board.id})}">수정</a>
<button onclick="update()">수정</button>
<script>
function update() {
location= '/board/update?id=[[${board.id}]]';
}
</script>
이런 코드말고도 여러가지가 있을 수 있음!!
다음 Controller
@GetMapping("/update")
public String update(
@RequestParam int id, Model model) {
Optional<Board> opt = boardRepository.findById(id);
model.addAttribute("board", opt.get());
return "board/update";
}
@PostMapping("/update")
public String updatePost(@ModelAttribute Board board){
boardRepository.save(board);
return "redirect:/board/update";
}
<form action="/board/update" method="post">
<input type="text" name="title" th:value="${board.title}">
<textarea name="content" cols="30" rows="10"> [[${board.content}]]</textarea>
<input type="text" name="writer" th:value="${board.writer}">
<input type="hidden" name="id" th:value="${board.id}">
<button>수정 완료</button>
</form>
update.html 을 만들어주면
이렇게 내용을 가져와서 수정할 수 있게된다.
수정이다아아
※ 지금은 PostMapping update에 return 주소를 안바꿔서 오류가 뜨지만 수정은 됨
※ 게시글 수정이나 회원정보 수정이나 똑같은 맥락
5.삭제하기
detail.html 에 작성
<button onclick="remove()">삭제</button>
function remove() {
const isOk = confirm('삭제하시겠습니까?');
if(isOk) {
location= '/board/remove?id=[[${board.id}]]';
}
}
Controller에 작성
@GetMapping("/remove")
public String remove(@RequestParam int id) {
Board board = new Board();
board.setId(id);
boardRepository.delete(board);
return "redirect:/board/list";
}
지저분.. 하지만 이렇게 삭제가 된당.
+ 작성자만 삭제하기 코드
@GetMapping("/remove")
public String remove(@RequestParam int id) {
//로그인된 이름
String loggedName = (String) session.getAttribute("name");
Optional<Board> dbboard = boardRepository.findById(id);
// 현재 게시글 작성자 이름
String savedName = dbboard.get().getWriter();
//자바의 문자열 비교 주의사항 - equals()
if(savedName.equals(loggedName)) {
Board board = new Board();
board.setId(id);
boardRepository.delete(board);
} else{
return "redirect:/board/detail?id=" + id;
}
return "redirect:/board/list";
}
이러면 session에 저장된 로그인 name과 writer가 일치해야 삭제 가능
※연습용이라 데이터베이스 컬럼이랑 게시글이랑 맞추지도 않았음.. 실제로는 컬럼명을 통일해서 프라이머리키와 외래키를 신경써서 만들어야함