본문 바로가기

Spring

240308 스프링 부트

이클립스에서 DB 연결해보기

Data Source Explorer -> 버튼 클릭

손+ 모양의 버튼 클릭하기

MySQL 선택하기, MariaDB 가 없음

MariaDB 대신 MySQL 선택

DB 추가하기

우측 나침반 모양+ 버튼 클릭

 

MySQL 5.1 버전 선택 후 MariaDB connector 넣기

Jar List 에서 기존에 있던 jar 은 제거하고 해당 링크의 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 등 서버 주소 변경하기

mysql 대신에 mariadb 넣기

 

 

연결까지 완료하면 하단의 Test Connection 해보기

succeeded! 가 떠야 제대로 연결된 것

 

쿼리 실행해보기, 우측 맨 끝 파란색 파일 모양 버튼 클릭

맨 우측 점 3개 바로 왼쪽 버튼 클릭
Type, Name, Database 선택 후 쿼리문 작성

 

실행결과 보기, 실행은 우클릭 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 문장 안에서 오류 발생

Long 형을 Integer 로 변환하는 과정에 생긴 오류

 

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 해보는 java 파일

 

정상 로그인 되는지 확인해보기

@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"))));
}

 

실행해보기 

WebApplication 우클릭 > Run As > JUnit Test 실행

 

해서 초록색으로 뜨면 통과, 빨간색으로 뜨면 오류 발생한 것

여기에서는 정상적으로 작동 완료

 

김영한님 강의에서는 실제로는 하드코딩을 하지 않고 어떤 값이 들어가도 정상적으로 통과되는 것이 좋은 테스트 라고 하였음

https://dingdingmin-back-end-developer.tistory.com/entry/Springboot-Test-%EC%BD%94%EB%93%9C-%EC%9E%91%EC%84%B1-1

 

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

 

'Spring' 카테고리의 다른 글

240312 스프링 부트  (0) 2024.03.12
240311 스프링 부트  (0) 2024.03.11
240307 스프링 부트  (0) 2024.03.07
240306 스프링 부트  (1) 2024.03.06
240305 스프링 프로젝트  (4) 2024.03.05