쌍용교육(JAVA)/SpringBoot

쌍용교육 -JSP수업 88일차 ch14SpringThymeleadf

구 승 2024. 6. 24. 17:50

application.yml 그대로 복사해서 사용

jsp를 사용하지 않고 HTML을 사용하기 때문에 코드 수정이 필요.

mvc:

view: #view 경로 및 확장자 지정

prefix: /WEB-INF/views/

suffix: .jsp

여기를 삭제하고 thymeleadf 설정을 넣는다.

  thymeleaf:
    prefix: classpath:templates/
    suffix: .html
    check-template-location: true
    enabled: true
    mode: HTML5
    cache: false #캐시를 사용하지 않음. 새로고침하면 변경사항이 바로 확인

src/main/resources => messages와css 폴더를 ch12프로젝트에 있는걸 복사해서 사용 

kr.spring.board.vo => BoardVO

package kr.spring.board.vo;

import java.sql.Date;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;

public class BoardVO {
	private int num;
	@NotBlank
	private String writer;
	@NotBlank
	private String title;
	@NotBlank
	private String passwd;
	@NotEmpty
	private String content;
	private Date reg_date;
	public int getNum() {
		return num;
	}
	public void setNum(int num) {
		this.num = num;
	}
	public String getWriter() {
		return writer;
	}
	public void setWriter(String writer) {
		this.writer = writer;
	}
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	public String getPasswd() {
		return passwd;
	}
	public void setPasswd(String passwd) {
		this.passwd = passwd;
	}
	public String getContent() {
		return content;
	}
	public void setContent(String content) {
		this.content = content;
	}
	public Date getReg_date() {
		return reg_date;
	}
	public void setReg_date(Date reg_date) {
		this.reg_date = reg_date;
	}
	@Override
	public String toString() {
		return "BoardVO [num=" + num + ", writer=" + writer + ", title=" + title + ", passwd=" + passwd + ", content="
				+ content + ", reg_date=" + reg_date + "]";
	}
	
	
}

kr.spring.board.dao => BoardMapper

package kr.spring.board.dao;

import java.util.List;
import java.util.Map;

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

import kr.spring.board.vo.BoardVO;

@Mapper
public interface BoardMapper {
	public void insertBoard(BoardVO board);
	@Select("SELECT COUNT(*) FROM aboard")
	public int getBoardCount();
	public List<BoardVO> getBoardList(Map<String,Integer>map);
	public BoardVO getBoard(int num);
	public void updateBoard(BoardVO board);
	public void deleteBoard(int num);
}

BoardMapper.xml 역시 ch12에서 복사해서 사용

kr.spring.board.service=>BoardService 

package kr.spring.board.service;

import java.util.List;
import java.util.Map;



import kr.spring.board.vo.BoardVO;

public interface BoardService {
	public void insertBoard(BoardVO board);
	public int getBoardCount();
	public List<BoardVO> getBoardList(Map<String,Integer>map);
	public BoardVO getBoard(int num);
	public void updateBoard(BoardVO board);
	public void deleteBoard(int num);
}

BoardServiceImpl

package kr.spring.board.service;

import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import kr.spring.board.dao.BoardMapper;
import kr.spring.board.vo.BoardVO;

@Service
@Transactional
public class BoardServiceImpl implements BoardService {

    @Autowired
    private BoardMapper boardMapper;

    @Override
    public void insertBoard(BoardVO board) {
        boardMapper.insertBoard(board);
    }

    @Override
    public int getBoardCount() {
        return boardMapper.getBoardCount();
    }

    @Override
    public List<BoardVO> getBoardList(Map<String, Integer> map) {
        return boardMapper.getBoardList(map);
    }

    @Override
    public BoardVO getBoard(int num) {
        return boardMapper.getBoard(num);
    }

    @Override
    public void updateBoard(BoardVO board) {
        boardMapper.updateBoard(board);
    }

    @Override
    public void deleteBoard(int num) {
        boardMapper.deleteBoard(num);
    }
}

kr.spring.board.controller => BoardController (ch12에서 그대로 복사)

templates => views => selectList.html

그냥만들면 webapp으로 가기 때문에 위치를 변경해줘야된다.

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>게시판목록</title>
<link rel="stylesheet" th:href="@{/css/style/css}" type="text/css"> <!-- th: 를 쓰면 thymeleaf의 속성으로 적용. -->
</head>
<body>
<div class="page-main">
	<h2>게시판 목록</h2>
	<div class="align-right">
		<input type="button" value="글쓰기" onclick="location.href='insert.do'">
	</div>
	
	<!-- thymeleaf는 태그를 쓰지않고 속성을 쓴다고 생각하면된다. thymeleaf는 HTML하나만으로 view를 구현함. -->
	<!-- 기존의 <c:if>대신 th:if를 사용. 만약 false이면(0이 아니면) 이 div가 나오지않음 -->
	<div class="result-display" th:if="${count == 0}">표시할 내용이 없습니다.</div>
	<div th:if="${count > 0}">
	<table>
		<tr>
			<th>번호</th>
			<th>제목</th>
			<th>작성자</th>
			<th>작성일</th>
		</tr>
		<tr th:each="board : ${list}">
			<td th:text="${board.num}"></td>
			<!-- @{detail.do?num=${board.num}}에서 detail앞에 /를 넣으면 url형태이다. 안쓰면 파일형태 -->
			<!-- ? 대신에 ()소괄호로 감싸줘야된다. -->
			<td><a th:href="@{detail.do(num=${board.num})}" th:text="${board.title}"></a></td>
			<td th:text="${board.writer}"></td>
			<td th:text="${board.reg_date}"></td>
		</tr>
	</table>
	<div class="align-center" th:utext="${page}"></div>
	</div>
</div>
</body>
</html>

BoardController 내용수정

views/를 넣어줌

89라인

		//뷰 이름 설정
		mav.setViewName("views/selectList");
//글쓰기 폼 호출
	@GetMapping("/insert.do")
	public String form() {
		return "views/insertForm";
	}

templates => views =>insertForm.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>글쓰기</title>
<link rel="stylesheet" th:href="@{/css/style.css}" type="text/css">
</head>
<body>
<div class="page-main">
	<h2>글쓰기</h2>
	<!-- th:object : request에 저장되어있는 자바빈 호출 -->
	<form action="insert.do" method="post" th:object="${boardVO}">
		<ul>
			<li>
				<label for="writer">작성자</label>
				<!-- th:field : 자바빈에 필드 지정 (id와 클라이언트가 넣은 값value가 들어감)--> <!-- *{writer} 는 boardVO.writer라고 생각하면됨 -->
				<input type="text" name="writer" th:field="*{writer}" th:errorclass="field-error">
				<span th:errors="*{writer}" class="error-color"></span>
			</li>
			<li>
				<label for="title">제목</label>
				<input type="text" name="title" th:field="*{title}" th:errorclass="field-error">
				<span th:errors="*{title}" class="error-color"></span>
			</li>
			<li>
				<label for="passwd">비밀번호</label>
				<input type="password" name="passwd" th:field="*{passwd}" th:errorclass="field-error">
				<span th:errors="*{passwd}" class="error-color"></span>
			</li>
			<li>
				<label for="content">내용</label>
				<textarea th:field="*{content}" th:errorclass="field-error"></textarea>
				<span th:errors="*{content}" class="error-color"></span>
			</li>
		</ul>
		<div class="align-center">
			<input type="submit" value="등록">
			<input type="button" value="목록" onclick="location.href='list.do'">
		</div>
	</form>
</div>
</body>
</html>

BoardMapper.java 내용추가

@Select("SELECT * FROM aboard WHERE num=#{num}")
	public BoardVO getBoard(int num);

BoardController.java 내용추가

views/ 추가

//글상세
	@RequestMapping("/detail.do")
	public ModelAndView detail(int num) {
		BoardVO board = 
				boardService.getBoard(num);
		return new ModelAndView("views/selectDetail","board",board);
	}

templates => views =>selectDetail.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>글상세</title>
<link rel="stylesheet" th:href="@{/css/style.css}" type="text/css">
</head>
<body>
<div class="page-main">
	<h2 th:text="${board.title}"></h2>
	<p>
		<!-- 1,2번 방법중 어떤것을 써도 상관없음 -->
		<span th:text="'글번호 :' + ${board.num}"></span><br><!-- 1번 방법 -->
		<span>작성자 : [[${board.writer}]]</span><br><!-- 2번 방법 -->
		<span>작성일 : [[${board.reg_date}]]</span>
	</p>
	<hr width="100%" size="1" noshade="noshade">
	<p th:text="${board.content}"></p>
	<div class="align-center">
		<!-- th:onclick 을 쓸 떄는 ""안에 | 를 맨끝에 써줘야됨. 자바스크립트를 쓰기 위해 파이프(|)를 씀 -->				
		<input type="button" value="수정" th:onclick="|location.href='@{update.do(num=${board.num})}'|">
		<input type="button" value="삭제" th:onclick="|location.href='@{delete.do(num=${board.num})}'|">
		<input type="button" value="목록" onclick="location.href='list.do'">	
	</div>
</div>
</body>
</html>