240308 스프링 부트
이클립스에서 DB 연결해보기
Data Source Explorer -> 버튼 클릭
MySQL 선택하기, MariaDB 가 없음
DB 추가하기
MySQL 5.1 버전 선택 후 MariaDB connector 넣기
Jar List 에서 기존에 있던 jar 은 제거하고 해당 링크의 jar 파일 넣기
Download MariaDB Connectors for data access & analysis | MariaDB
Download MariaDB Connector/Python, MariaDB Connector/C, MariaDB Connector/J, MariaDB Connector/Node.js, MariaDB Connector/R2DBC, MariaDB Connector/ODBC and more
mariadb.com
Properties 에서 mysql, localhost 등 서버 주소 변경하기
연결까지 완료하면 하단의 Test Connection 해보기
쿼리 실행해보기, 우측 맨 끝 파란색 파일 모양 버튼 클릭
실행결과 보기, 실행은 우클릭 Execute All
Div 로 테이블 만들어보기, BootStrap 과 style 둘 다 넣어보기
기존의 <table> 로 작성한 테이블
<table class="text-center">
<thead>
<tr>
<th>번호</th>
<th>제목</th>
<th>작성자</th>
<th>작성일</th>
<th>IP</th>
<th>조회수</th>
</tr>
</thead>
<tbody>
<tr th:each="row : ${board}">
<td th:text="${row.mtno}">번호가나올곳</td>
<td><a th:href="@{/detail(no=${row.mtno})}" th:text="${row.mttitle}">제목이나올곳</a></td>
<td th:text="${row.mname}">작성자가나올곳</td>
<td th:text="${row.mtdate}">작성일이나올곳</td>
<td th:text="${row.mtip}">IP가나올곳</td>
<td th:text="${row.mtread}">조회수가나올곳</td>
</tr>
</tbody>
</table>
<div> 로 테이블 만들어보기, style="display" 가 부트스트랩 없이 style 적용하는 것
<div class="makeTable text-center">
<div class="table">
<div class="thead" style="display: table-row;">
<div class="col-1 th" style="display: table-cell">번호</div>
<div class="col-5 th" style="display: table-cell">제목</div>
<div class="col-2 th" style="display: table-cell">작성자</div>
<div class="col-2 th" style="display: table-cell">작성일</div>
<div class="col-1 th" style="display: table-cell">IP</div>
<div class="col-1 th" style="display: table-cell">조회수</div>
</div>
<div class="table tbody" th:each="row : ${board}" style="display: table-row;">
<div class="col-1 td" th:text="${row.mtno}" style="display: table-cell">번호내용</div>
<div class="col-5 text-start td" th:text="${row.mttitle}" style="display: table-cell">제목내용</div>
<div class="col-2 td" th:text="${row.mname}" style="display: table-cell">작성자내용</div>
<div class="col-2 td" th:text="${row.mtdate}" style="display: table-cell">작성일내용</div>
<div class="col-1 td" th:text="${row.mtip}" style="display: table-cell">IP내용</div>
<div class="col-1 td" th:text="${row.mtread}" style="display: table-cell">조회수내용</div>
</div>
</div>
</div>
카테고리 별로 게시글 다른 것 출력해보기
parameter 로 받아도되고, dto 만들어서 한꺼번에도 해보기
일단 카테고리 중 1번 카테고리 출력
@GetMapping("/board")
public String freeboard(UrlDTO urlDTO, Model model) {
if (urlDTO.getCate() == null) {
urlDTO.setCate("1");
}
List<BoardDTO> board = indexService.board(urlDTO);
model.addAttribute("board", board);
model.addAttribute("boardName", "자유게시판");
return "board";
}
2번 카테고리 출력
@GetMapping("/notice")
public String notice(UrlDTO urlDTO, Model model) {
if (urlDTO.getCate() == null) {
urlDTO.setCate("2");
}
List<BoardDTO> board = indexService.board(urlDTO);
model.addAttribute("board", board);
model.addAttribute("boardName", "공지사항");
return "board";
}
UrlDTO 는 이렇게 만들었음
지금은 카테고리만 받고 있지만 나중에는 검색, 페이지, 삭제 여부 등 url 에 들어갈 것이 많아 미리 만듦
@Getter
@Setter
public class UrlDTO {
private String cate, page, mtdel, boardName;
}
고민해야할 것
- dto 는 default 값을 어떻게 할까
- boardName 을 어떻게 띄우는 것이 좋을까
- page 어떻게 만드는게 좋을까
- 등등 부족한 것은 많은 것 같은데 생각이 잘 안남
게시판 이름도 직접 넣어보기, 게시판 이름이 들어간 테이블 만들기
-- 이건 내가 그냥 해보는 거
DB 에서 테이블 명을 받아와 model 에 add 하기 - 이렇게 하면 같은 html 로 여러 페이지를 띄울 수 있음
==> 아직 DB 에 못만듬 만들 게시판들을 5개 정도 추려서 해보기
지금은 Controller 에서 직접 하드코딩으로 add 하고 있음
model.addAttribute("boardName", "공지사항");
출력하기
<title th:text="${boardName}">타이틀넣는곳</title>
<h1 th:text="${boardName}">게시판 이름</h1>
게시판의 글이 있으면 출력, 없으면 없다는 멘트 띄우기
게시글 사이즈 보는 법
<span th:text="${#lists.size(board)}"></span> // 숫자 return
타임리프 if-else 문법
if 와 unless 의 조건은 같은 것으로 설정
<div th:if="${#lists.size(board) eq 0 }">
<h2>출력 값 없음</h2>
</div>
<div th:unless="${#lists.size(board) eq 0 }">
<h2>출력 값 있음</h2>
</div>
글쓰기 버튼 만들어보기
--- mtcate 가져오기
---- 글이 없다면 ? -- param 으로 받기 -- param 도 없다면 ?
글 받아보기, Map 사용
@PostMapping("/write")
public String write(@RequestParam Map<String, Object> map) {
System.out.println(map);
return "redirect:/board?cate=1";
}
로그인 해보기
로그인 페이지 만들기, 간단하게만 만들기
<form action="/login" method="post">
<input class="form-control" type="text" name="id" />
<input class="form-control" type="password" name="pw" />
<button class="btn btn-dark" type="submit">로그인</button>
</form>
새로운 MemberController 생성해서 쭉 이어보기, Service, DAO, Mapper
==> 로그인 하면 세션을 받아와 세션에 값 넣기
// Controller
@PostMapping("/login")
public String login(@RequestParam Map<String, Object> map) {
Map<String, Object> login = memberService.login(map);
if ((int) login.get("count") == 1) {
HttpSession session = util.getSession();
session.setAttribute("mid", login.get("mid"));
session.setAttribute("mname", login.get("mname"));
return "redirect:/board";
} else {
return "redirect:/login";
}
}
// Service
public Map<String, Object> login(Map<String, Object> map) {
return memberDAO.login(map);
}
// DAO, Interface
Map<String, Object> login(Map<String, Object> map);
Mapper
<select id="login" parameterType="Map" resultType="HashMap">
select count(*) as count , mno, mid, mname
from member
where mid = #{id} and mpw = HEX(AES_ENCRYPT(#{pw}, #{id}))
</select>
여기서 if 문장 안에서 오류 발생
Object 를 바로 (int) 로 캐스팅 하지말고, String -> int 로 바꾸기
Integer.valueOf((String) login.get("count"));
아니면 Util 에 int 로 변환할 수 있게 추가하기
public int str2Int2(String str) {
return Integer.parseInt(str.replaceAll("[^0-9]", ""));
}
public int str2Int2(Object obj) {
return str2Int2(String.valueOf(obj));
}
==>
util.str2Int2(login.get("count")) == 1
menu.html 에 로그인 한 것과 로그인 안된 상태 if 문 넣기
jsp 에서는 sessionScope 를 사용했는데, 여기서는 session 을 사용
<th:block th:if="${session.mid eq null}">
<li class="nav-item"><a class="nav-link me-lg-3" href="./login">/login</a></li>
</th:block>
<th:block th:unless="${session.mid eq null}">
<li class="nav-item"><a class="nav-link me-lg-3" href="./myInfo" th:text="|${session.mname} 님|">닉네임 님</a></li>
<li class="nav-item"><a class="nav-link me-lg-3" href="./logout">/logout</a></li>
</th:block>
Logout 넣기
@GetMapping("/logout")
public String logout() {
HttpSession session = util.getSession();
if (session.getAttribute("mid") != null) {
session.removeAttribute("mid");
}
if (session.getAttribute("mname") != null) {
session.removeAttribute("mname");
}
session.invalidate();
return "redirect:/";
}
Test 해보기
정상 로그인 되는지 확인해보기
@Test
void contextLoads() {
Map<String, Object> map = new HashMap<String, Object>();
map.put("id", "test1");
map.put("pw", "654321");
Map<String, Object> result = memberService.login(map);
// Assertions.assertEquals(1L, result.get("count"));
assertEquals(1, Integer.valueOf(String.valueOf(result.get("count"))));
}
실행해보기
해서 초록색으로 뜨면 통과, 빨간색으로 뜨면 오류 발생한 것
김영한님 강의에서는 실제로는 하드코딩을 하지 않고 어떤 값이 들어가도 정상적으로 통과되는 것이 좋은 테스트 라고 하였음
Springboot Test 코드 작성
Test 코드를 작성하는 법을 알아보기 전에 Test 코드의 필요성에 대해서 알아보겠습니다. 1. 왜 Test 코드를 작성하는가? 크게 2가지 이유가 있습니다.' 1-1. Test 코드를 작성하지 않고 결과를 검증하
dingdingmin-back-end-developer.tistory.com
글 삭제하기
detail.html 에 글 삭제하는 버튼 추가
<i class="bi bi-arrow-up" th:id="${detail.mtno}" onclick="update(this.id)"></i>
<i class="bi bi-arrow-down" th:id="${detail.mtno}" onclick="del(this.id)"></i>
스크립트 작성, 가상 form
function update(no){
Swal.fire({
title: "수정합니까?",
text: "해당 내용을 수정합니다.",
icon: "warning",
showCancelButton: true,
confirmButtonColor: "#3085d6",
cancelButtonColor: "#d33",
confirmButtonText: "수정"
}).then((result) => {
if (result.isConfirmed) {
// Swal.fire({ title: "수정을 선택했습니다.", text: "수정합니다.", icon: "success" });
}
});
}
function del(no){
Swal.fire({
title: "삭제합니까?",
text: "해당 내용을 삭제합니다. 복구가 불가능합니다.",
icon: "warning",
showCancelButton: true,
confirmButtonColor: "#3085d6",
cancelButtonColor: "#d33",
confirmButtonText: "삭제"
}).then((result) => {
if (result.isConfirmed) {
// Swal.fire({ title: "삭제를 선택했습니다.", text: "삭제합니다.", icon: "success" });
let form = document.createElement('form');
form.setAttribute('method', 'post');
form.setAttribute('action', '/postDel');
let input = document.createElement('input');
input.setAttribute('type', 'hidden');
input.setAttribute('name', 'no');
input.setAttribute('value', no);
form.appendChild(input);
document.body.appendChild(form);
form.submit();
}
});
Controller, Service, DAO, Mapper 타고 가서 Update 문 실행
@PostMapping("/postDel")
public String postDel(@RequestParam("no") String mtno) {
int result = indexService.postDel(mtno);
return "redirect:/board";
}
// Service
public int postDel(String mtno) {
return indexDAO.postDel(mtno);
}
// DAO, Interface
int postDel(String mtno);
Mapper
<update id="postDel" parameterType="String">
update multiboard set mtdel = '0'
where mtno = #{mtno}
</update>
페이징 만들기
https://chung-develop.tistory.com/17
[Thymeleaf]게시판 Table에서 Paging 적용하기(SpringBoot)
[Thymeleaf]게시판 Table에서 Paging 적용하기(SpringBoot) 안녕하세요! 보통 웹사이트에서 다량의 데이터들을 효율적으로 보여주고자 할 때 표를 많이 사용합니다. 이 때 페이징이 잘 안되서 주로 애를
chung-develop.tistory.com