헬창 개발자
[스프링부트] 게시판 만들기 본문
https://github.com/whcksdud/board
전체 프로젝트는 해당 깃허브에서 다운 가능합니다
Spring Initializr로 Spring Boot 프로젝트 생성하기
스프링부트 버전은 3.1.2 자바는 17 버전을 사용한다.
의존성은 다음 처럼 추가하자
파일을 다운받아서 인텔리제이로 열면
위 처럼 프로젝트 구조가 만들어 진다.
그러면 src 폴더 내부를
다음 처럼 구조화 하자 (jsp, js, css 파일은 깃허브에서 다운)
그리고 application.properties에 다음 처럼 추가해주자
#h2 console
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console
#h2 db
spring.datasource.url=jdbc:h2:~/test;
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect
spring.sql.init.mode=always
#hibernate ??
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.show_sql=true
spring.jpa.hibernate.ddl-auto=create
spring.mvc.view.prefix=/WEB-INF/views/
spring.mvc.view.suffix=.jsp
나는 간단한 게시판을 만들거라서 DB 테이블은 다음 처럼 구상했다.
CREATE TABLE BOARD (
num BIGINT AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(255),
writerDate DATE,
id VARCHAR(255),
pw VARCHAR(255),
context VARCHAR(255)
);
num은 게시글 번호, title은 게시글 제목, writeDate는 작성일, id는 사용자, pw는 비밀번호, context는 내용이다.
이제 DTO를 작성해자
//BoardDTO.java
package com.example.demo.domain;
import jakarta.persistence.*;
import java.util.Date;
@Entity
@Table(name = "BOARD")
public class BoardDTO {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long num;
private String title;
@Temporal(TemporalType.DATE)
private Date writerDate;
private String id;
private String pw;
private String context;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public Date getWriterDate() {
return writerDate;
}
public void setWriterDate(Date writerDate) {
this.writerDate = writerDate;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getPw() { return pw; }
public void setPw(String pw) {
this.pw = pw;
}
public String getContext() {
return context;
}
public void setContext(String context) {
this.context = context;
}
@Override
public String toString() {
return "Board{" +
", title='" + title + '\'' +
", writerDate=" + writerDate +
", id='" + id + '\'' +
", pw='" + pw + '\'' +
", context='" + context + '\'' +
'}';
}
}
//BoardRepository.interface
package com.example.demo.domain;
import com.example.demo.domain.BoardDTO;
import org.springframework.stereotype.Repository;
import org.springframework.data.jpa.repository.JpaRepository;
@Repository
public interface BoardRepository extends JpaRepository<BoardDTO, String> {
}
DAO는 다음과 같다. 그리고 form 태그를 이용해 사용자가 작성한 글을 한번에 받아오기 때문에 WebServlet도 만들어주자
//BoardDAO.java
package com.example.demo.dao;
import com.example.demo.domain.BoardDTO;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.sql.Connection;
public class BoardDAO {
private Connection conn;
public BoardDAO(Connection conn) {
this.conn = conn;
}
public void insertBoard(BoardDTO boardDTO) throws SQLException {
String insertQuery = "INSERT INTO BOARD (title, id, pw, context, writer_date) VALUES (?, ?, ?, ?, ?)";
try (PreparedStatement pstmt = conn.prepareStatement(insertQuery)) {
pstmt.setString(1, boardDTO.getTitle());
pstmt.setString(2, boardDTO.getId());
pstmt.setString(3, boardDTO.getPw());
pstmt.setString(4, boardDTO.getContext());
pstmt.setTimestamp(5, new Timestamp(System.currentTimeMillis()));
pstmt.executeUpdate();
}
}
}
//BoardServlet.java
package com.example.demo.dao;
import com.example.demo.dao.BoardDAO;
import com.example.demo.domain.BoardDTO;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
@WebServlet( name = "BoardServlet" , urlPatterns = "/BoardServlet")
public class BoardServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String title = request.getParameter("title");
String id = request.getParameter("id");
String pw = request.getParameter("pw");
String context = request.getParameter("context");
BoardDTO boardDTO = new BoardDTO();
boardDTO.setTitle(title);
boardDTO.setId(id);
boardDTO.setPw(pw);
boardDTO.setContext(context);
try {
Class.forName("org.h2.Driver");
Connection conn = DriverManager.getConnection("jdbc:h2:~/test", "sa", "");
BoardDAO boardDAO = new BoardDAO(conn);
boardDAO.insertBoard(boardDTO);
conn.close();
response.sendRedirect("/feature");
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
System.out.println("실패");
}
}
}
컨트롤러는 다음처럼 구현했다
//MyController.java
package com.example.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class MyController {
@GetMapping("/")
public String index(Model model) {
return "index";
}
@GetMapping("/home")
public String home(Model model) {
return "index";
}
@GetMapping("/feature")
public String feature(Model model) {
return "feature";
}
@GetMapping("/add")
public String add(Model model) {
return "add";
}
@GetMapping("/post")
public String post(Model model) {
return "post";
}
@GetMapping("/404")
public String error(Model model) {
return "404";
}
}
코드가 너무 길어서 jsp의 중요 코드만 리뷰하겠다 전체코드는 깃허브에서 확인 가능
<%
try {
Class.forName("org.h2.Driver");
Connection conn = DriverManager.getConnection("jdbc:h2:~/test", "sa", "");
Statement stmt = conn.createStatement();
String query = "SELECT * FROM BOARD"; // 데이터를 가져올 쿼리문
ResultSet rs = stmt.executeQuery(query);
%>
<div class="container">
<%
String searchKeyword = request.getParameter("searchKeyword");
if (searchKeyword != null) {
searchKeyword = searchKeyword.trim();
if (!searchKeyword.isEmpty()) {
String searchQuery = "SELECT * FROM BOARD WHERE title LIKE ?";
try (PreparedStatement pstmt = conn.prepareStatement(searchQuery)) {
pstmt.setString(1, "%" + searchKeyword + "%");
ResultSet searchResult = pstmt.executeQuery();
if (searchResult.next()) { // 검색 결과가 있을 때만 테이블 표시
%>
<h4 class="mt-4">검색 결과</h4>
<table class="table">
<thead>
<tr>
<th scope="col">번호</th>
<th scope="col">제목</th>
<th scope="col">작성자</th>
<th scope="col">작성일</th>
</tr>
</thead>
<tbody>
<% do { %>
<tr>
<th scope="row"><%= searchResult.getString("num") %></th>
<td><a href="/post?num=<%= searchResult.getString("num") %>"><%= searchResult.getString("title") %></a></td>
<td><%= searchResult.getString("id") %></td>
<td><%= searchResult.getString("writer_date") %></td>
</tr>
<% } while (searchResult.next()); %>
</tbody>
</table>
<%
} else {
out.println("<h3>검색 결과가 없습니다.</h3>");
}
searchResult.close();
} catch (SQLException e) {
out.println("검색 도중 오류가 발생하였습니다: " + e.getMessage());
}
}
}
%>
<table class="table">
<thead>
<tr>
<th scope="col">번호</th>
<th scope="col">제목</th>
<th scope="col">작성자</th>
<th scope="col">작성일</th>
</tr>
</thead>
<tbody>
<% while (rs.next()) { %>
<tr>
<th scope="row"><%= rs.getString("num") %></th>
<td><a href="/post?num=<%= rs.getString("num") %>"><%= rs.getString("title") %></a></td>
<td><%= rs.getString("id") %></td>
<td><%= rs.getString("writer_date") %></td>
</tr>
<% }
rs.close();
stmt.close();
conn.close();
} catch (Exception e) {
out.println("데이터베이스 조회 도중 오류가 발생하였습니다: " + e.getMessage());
}
%>
</tbody>
</table>
<div class="text-center">
<button type="button" class="btn btn-primary" onClick="location.href='add'">글 작성</button>
</div>
</div>
위 코드는 h2db에 데이터베이스를 연결하고 게시글을 불러오며, 검색을 할 수 있는 기능이다.
<div class="container">
<!-- Sample Posts -->
<div class="container mt-5">
<div class="mt-5">
<%
String num = request.getParameter("num");
try {
Class.forName("org.h2.Driver");
Connection conn = DriverManager.getConnection("jdbc:h2:~/test", "sa", "");
Statement stmt = conn.createStatement();
String query = "SELECT * FROM BOARD WHERE num = " + num; // 해당 게시글의 데이터를 가져올 쿼리문
ResultSet rs = stmt.executeQuery(query);
if (rs.next()) {
%>
</div>
<table class="table">
<thead>
<tr>
<th colspan="4" style="text-align: center;"><%= rs.getString("title") %></th>
</tr>
</thead>
<tbody>
<tr>
<th style="text-align: center;">작성자</th>
<td><%= rs.getString("id") %></td>
<th style="text-align: center;">작성일</th>
<td><%= rs.getString("writer_date") %></td>
</tr>
<td colspan="4" style="padding: 30px;">
<%= rs.getString("context") %>
</td>
<%
} else {
out.println("게시글을 찾을 수 없습니다.");
}
rs.close();
stmt.close();
conn.close();
} catch (Exception e) {
out.println("데이터베이스 조회 도중 오류가 발생하였습니다: " + e.getMessage());
}
%>
</tbody>
</table>
</div>
</div>
위 코드는 게시글을 클릭했을때 내용을 볼 수 있는 코드이다.
<form method="post" action="BoardServlet" class="needs-validation" novalidate>
<div class="form-group row">
<label for="title" class="col-sm-2 col-form-label">제목 *</label>
<div class="col-sm-10">
<input type="text" name="title" class="form-control" required>
</div>
</div>
<br>
<div class="form-group row">
<label for="name" class="col-sm-2 col-form-label">아이디 *</label>
<div class="col-sm-10">
<input type="text" name="id" class="form-control" required>
</div>
</div>
<br>
<div class="form-group row">
<label for="pass" class="col-sm-2 col-form-label">비밀번호 *</label>
<div class="col-sm-10">
<input type="password" name="pw" class="form-control" required>
</div>
</div>
<br>
<div class="form-group row">
<label for="content" class="col-sm-2 col-form-label">내용</label>
<div class="col-sm-10">
<textarea cols="100" rows="5" name="context" class="form-control"></textarea>
</div>
</div>
<br>
<div class="form-group row">
<div class="col-sm-10 offset-sm-2">
<button type="submit" class="btn btn-primary">등록</button>
</div>
</div>
</form>
위 코드는 사용자가 게시글 내용을 적으면 BoardServlet.java 파일에 요청을 보내는 코드이다.
모든 코드가 작성이 끝났으니 서버를 실행시켜서 확인해보자
먼저 테이블이 생성되었는지 확인하기위해 localhost:8080/h2-console/ 에 접속하자
BOARD 테이블이 잘생성됐다.
이제 웹에 접속을 하면
성공적으로 접속이 된다.
게시판에 들어가면 다음 처럼 잘나온다.
글작성 페이지에 들어가 게시글을 적어보자
스프링부트를 통해 간단한 게시판을 만들어보았다. 아직 기능은 게시글 작성, 검색만 있지만 추후 기능을 추가해서 CRUD의 기능을 넣어봐야겠다.
'공부방' 카테고리의 다른 글
RAG, 랭체인 그게 뭔데?? (3) | 2024.01.22 |
---|---|
동적 페이지 스크롤을 이용한 크림 시세 크롤링 (1) | 2023.12.08 |
prophet 설치 오류 해결 방법 (0) | 2022.11.03 |
도커 맛만 보기 (0) | 2022.10.29 |
passport 구현 (0) | 2022.10.25 |