본문 바로가기
학습/JSP

28. 게시판(기본)

by Elfen Lied 2022. 11. 25.
반응형

- sql

drop table board_t;

create table board_t(
    bno number(10) primary key, -- 게시물 번호
    title varchar2(500) not null,
    content varchar2(4000) not null, -- varchar2 최대 4000
    writer varchar2(100) not null,
    writeDate date default sysdate
);

create sequence bno_seq;
drop SEQUENCE bno_seq;

insert into board_t(bno, title, content, writer)
values(bno_seq.nextval,'제목입니다.01', '내용입니다01', '관리자');
insert into board_t(bno, title, content, writer)
values(bno_seq.nextval,'제목입니다.02', '내용입니다02', '관리자');
insert into board_t(bno, title, content, writer)
values(bno_seq.nextval,'제목입니다.03', '내용입니다03', '관리자');
insert into board_t(bno, title, content, writer)
values(bno_seq.nextval,'제목입니다.04', '내용입니다04', '관리자');

commit;

select * from board_t;

프로젝트 만들고 메이븐 프로젝트로 바꾼뒤 pom.xml에 필요한것 적용하기

- pom.xml

dependencies에 4개 추가

추가후 maven 업데이트 해주기

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>exer15</groupId>
  <artifactId>exer15</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>war</packaging>
  
  <dependencies>
		<!-- lombok, jstlm ojdbc6, tomcat dbcp-->
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<version>1.18.24</version>
			<scope>provided</scope>
		</dependency>

		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>

		<dependency>
			<groupId>com.oracle.database.jdbc</groupId>
			<artifactId>ojdbc6</artifactId>
			<version>11.2.0.4</version>
		</dependency>

		<dependency>
			<groupId>org.apache.tomcat</groupId>
			<artifactId>tomcat-dbcp</artifactId>
			<version>10.1.2</version>
		</dependency>

	</dependencies>

  
  <build>
    <plugins>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.8.1</version>
        <configuration>
          <release>11</release>
        </configuration>
      </plugin>
      <plugin>
        <artifactId>maven-war-plugin</artifactId>
        <version>3.2.3</version>
      </plugin>
    </plugins>
  </build>
</project>

 

- 패키지 생성 controller, dao, domain, common

 

 

 

- 한글 깨짐 방지를 위한 EncoderFilter필터 생성
package com.common;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpFilter;

@WebFilter("/*")
public class EncoderFilter extends HttpFilter implements Filter {
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		request.setCharacterEncoding("utf-8");
		chain.doFilter(request, response);
	}
}

 

 

 

- BoardVO

package com.domain;

import java.util.Date;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class BoardVO {
	private int bno;
	private String title;
	private String content;
	private String writer;
	private Date writeDate;
	
}

 

 

- BoardController 서블릿

package com.controller;

import java.io.IOException;
import java.util.List;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.dao.BoardDAO;
import com.domain.BoardVO;

@WebServlet("/board/*")
public class BoardController extends HttpServlet {
	private BoardDAO dao;
	
	@Override
	public void init() throws ServletException {
		dao = new BoardDAO();
	}
	
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doHandle(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doHandle(request, response);
	}
	private void doHandle(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String pathInfo = request.getPathInfo();
		String contextPath = request.getContextPath();
		final String PREFIX = "/WEB-INF/views/board/";
		final String SUFFIX = ".jsp";
		
		RequestDispatcher rd = null;
		String nextPage = null;
	
		if(pathInfo == null || pathInfo.equals("/") || pathInfo.equals("/list")) { // 게시글목록
			List<BoardVO> listArticles = dao.listArticles();
			request.setAttribute("list", listArticles);
			nextPage = "articleList";
		} else if(pathInfo.equals("/findArticle")) { // 글 상세
			String paramBno = request.getParameter("bno");
			int bno = Integer.parseInt(paramBno);
			BoardVO detail = dao.findArticle(bno);
			request.setAttribute("article", detail);
			nextPage = "detail";
		} else if(pathInfo.equals("/writeForm")) { // 글쓰기 폼
			nextPage = "writeForm";
		} else if(pathInfo.equals("/modifyForm")) {
			String paramBno = request.getParameter("bno");
			int bno = Integer.parseInt(paramBno);
			BoardVO findArticle = dao.findArticle(bno);
			request.setAttribute("article", findArticle);
			nextPage = "modifyForm";
		} else if(pathInfo.equals("/modArticle")) {
			String paramBno = request.getParameter("bno");
			int bno = Integer.parseInt(paramBno);
			BoardVO vo = BoardVO.builder()
					.bno(bno)
					.title(request.getParameter("title"))
					.content(request.getParameter("content")).build();
			dao.modArticle(vo);
			response.sendRedirect(contextPath + "/board");
			return;
		} else if(pathInfo.equals("/addArticle")) {// 글쓰기 처리
			BoardVO vo = BoardVO.builder()
					.title(request.getParameter("title"))
					.content(request.getParameter("content"))
					.writer(request.getParameter("writer")).build();
			dao.addArticle(vo);
			response.sendRedirect(contextPath + "/board");
			return;
		} else if(pathInfo.equals("/delArticle")) {
			String paramBno = request.getParameter("bno");
			int bno = Integer.parseInt(paramBno);
			dao.delArticle(bno);
			response.sendRedirect(contextPath + "/board");
			return;
		} else { // 404에러
			request.getRequestDispatcher("/WEB-INF/views/error/_404.jsp").forward(request, response);
			return;
		}
		rd = request.getRequestDispatcher(PREFIX + nextPage + SUFFIX);
		rd.forward(request, response);
	}

}

 

 

- MainController 서블릿

package com.controller;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/")
public class MainController extends HttpServlet {

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.getRequestDispatcher("/WEB-INF/views/index.jsp").forward(request, response);
	}
	
}

 

 

- BoardDAO

package com.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;

import com.domain.BoardVO;

public class BoardDAO {

	private DataSource dataSource;
	
	public BoardDAO() {
		try {
			Context ctx = new InitialContext();
			Context envCtx = (Context) ctx.lookup("java:/comp/env");
			dataSource = (DataSource) envCtx.lookup("jdbc/oracle");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	// 게시글 목록
	public List<BoardVO> listArticles() {
		List<BoardVO> list = new ArrayList<>();
		String query = "SELECT * FROM board_t ORDER BY bno DESC";
		try (
			Connection conn = dataSource.getConnection();
			PreparedStatement pstmt = conn.prepareStatement(query);
			ResultSet rs = pstmt.executeQuery();
		){
			while (rs.next()) {
				BoardVO vo = BoardVO.builder()
						.bno(rs.getInt("bno"))
						.title(rs.getString("title"))
						.content(rs.getString("content"))
						.writer(rs.getString("writer"))
						.writeDate(rs.getDate("writeDate")).build();
				list.add(vo);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return list;
	}
	
	// 게시글 추가
	public void addArticle(BoardVO vo) {
		String query = "INSERT INTO board_t(bno, title, content, writer) VALUES(bno_seq.NEXTVAL,?,?,?)";
		try (
			Connection conn = dataSource.getConnection(); 
			PreparedStatement pstmt = conn.prepareStatement(query);
		) {
			pstmt.setString(1, vo.getTitle());
			pstmt.setString(2, vo.getContent());
			pstmt.setString(3, vo.getWriter());
			pstmt.executeUpdate();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	// 게시글 찾기
	public BoardVO findArticle(int bno) {
		BoardVO vo = null;
		String query = "SELECT * FROM board_t WHERE bno=?";
		try (
			Connection conn = dataSource.getConnection(); 
			PreparedStatement pstmt = conn.prepareStatement(query);
		){
			pstmt.setInt(1, bno);
			try (ResultSet rs = pstmt.executeQuery();){
				if(rs.next()) {
					vo = BoardVO.builder()
						.bno(rs.getInt("bno"))
						.title(rs.getString("title"))
						.content(rs.getString("content"))
						.writer(rs.getString("writer"))
						.writeDate(rs.getDate("writeDate")).build();
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return vo;
	}
	
	// 게시글 수정
	public void modArticle(BoardVO vo) {
		String query = "UPDATE board_t SET title=?, content=? WHERE bno=?";
		try (
			Connection conn = dataSource.getConnection(); 
			PreparedStatement pstmt = conn.prepareStatement(query);
		){
			pstmt.setString(1, vo.getTitle());
			pstmt.setString(2, vo.getContent());
			pstmt.setInt(3, vo.getBno());
			pstmt.executeUpdate();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	// 게시글 삭제
		public void delArticle(int bno) {
			String query = "DELETE FROM board_t WHERE bno=?";
			try (
				Connection conn = dataSource.getConnection(); 
				PreparedStatement pstmt = conn.prepareStatement(query);
			){
				pstmt.setInt(1, bno);
				pstmt.executeUpdate();
			} catch (Exception e) {
				e.printStackTrace();
			}
					
		}
	
}

 

 

  • - webapp / WEB-INF / index.jsp
  • - webapp / WEB-INF / views / layout / footer.jsp, header.jsp 

 

 

 

- index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ include file="layout/header.jsp" %>
<h1>메인페이지</h1>
<%@ include file="layout/footer.jsp" %>

 

- footer.jsp, header.jsp

// header.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<c:set var="contextPath" value="${pageContext.request.contextPath}" />
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css">
<script	src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.slim.min.js"></script>
<script	src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js"></script>
<script	src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/js/bootstrap.bundle.min.js"></script>

</head>
<body>
	<nav class="navbar navbar-expand-sm bg-dark navbar-dark">
		<!-- Brand/logo -->
		<a class="navbar-brand" href="${contextPath}">Logo</a>

		<!-- Links -->
		<ul class="navbar-nav">
			<li class="nav-item"><a class="nav-link" href="${contextPath}/board/list">자유게시판</a></li>
			<li class="nav-item"><a class="nav-link" href="#">Link 2</a></li>
			<li class="nav-item"><a class="nav-link" href="#">Link 3</a></li>
		</ul>
	</nav>

============================================================

// footer.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<div class="jumbotron">
	<h1>푸터 영역</h1>
</div>

</body>
</html>

 

 

  • -  webapp / WEB-INF / views / board / article.jsp, detail.jsp, writeForm.jsp, modifyForm.jsp 생성

 

- articleList.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ include file="../layout/header.jsp" %>

<div class="container">
	<div class="jumbotron">
		<h1 style="text-align:center; color:red" >자유게시판</h1>
	</div>
	<a href="${contextPath }/board/writeForm" class="btn btn-primary mb-2">글쓰기</a>
	<table class="table">
		<tr>
			<th>번호</th>
			<th>제목</th>
			<th>내용</th>
			<th>작성자</th>
			<th>작성일</th>
		</tr>
		<c:choose>
			<c:when test="${empty list}">
				<tr>
					<td colspan="5">등록된 게시물이 없습니다</td>
				</tr>
			</c:when>
			<c:otherwise>
				<c:forEach items="${list }" var="b">
					<tr>
						<td>${b.bno }</td>
						<td><a href="${contextPath}/board/findArticle?bno=${b.bno}">${b.title}</a></td>
						<td>${b.content}</td>
						<td>${b.writer}</td>
						<td>${b.writeDate}</td>
					</tr>
				</c:forEach>			
			</c:otherwise>
		</c:choose>
	</table>
</div>

<%@ include file="../layout/footer.jsp" %>

 

 

- detail.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ include file="../layout/header.jsp" %>

<div class="container">
	<div class="jumbotron my-3">
		<h1>게시글조회</h1>
	</div>
  	<div class="card mb-3">
    	<div class="card-header">
			${article.title }
		</div>
    	<div class="card-body">
			${article.content}
		</div> 
    	<div class="card-footer d-flex justify-content-between">
			<div>
			    <span class="badge badge-primary">${article.writer}</span>
				<span class="badge badge-secondary">${article.writeDate}</span>
			</div>
			<div>
				<a href="${contextPath }/board/delArticle?bno=${article.bno}" class="btn btn-danger">삭제</a>
				<a href="#" class="btn btn-warning">수정</a>
			</div>
		</div>
 	</div>
</div>

<%@ include file="../layout/footer.jsp" %>

 

 

- writeForm.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ include file="../layout/header.jsp" %>

<div class="container">
	<div class="jumbotron mb-3">
		<h1>글쓰기</h1>
	</div>

	<form action="${contextPath}/board/addArticle" method="post">
		<div class="form-group">
			<label for="title">제목:</label>
			<input type="text" class="form-control" id="title" name="title">
		</div>

		<div class="form-group">
			<label for="content">내용</label>
			<textarea class="form-control" rows="5" id="content" name="content"></textarea>
		</div>

		<div class="form-group">
			<label for="writer">작성자:</label>
			<input type="text" class="form-control" id="writer" name="writer">
		</div>
		<button class="btn btn-primary">등록</button>	
		<a class="btn btn-secondary">목록으로</a>
	</form>
</div>

<%@ include file="../layout/footer.jsp" %>

 

 

- modifyForm.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ include file="../layout/header.jsp" %>
<c:set var="a" value="${article}" />
<div class="container">
	<div class="jumbotron mb-3">
		<h1>글수정</h1>
	</div>

	<form action="${contextPath}/board/modArticle" method="post">
		<input type="hidden" value="${a.bno}" name="bno">
		<div class="form-group">
			<label for="title">제목:</label>
			<input type="text" class="form-control" id="title" name="title" value="${a.title }">
		</div>

		<div class="form-group">
			<label for="content">내용</label>
			<textarea class="form-control" rows="5" id="content" name="content">${a.content }</textarea>
		</div>

		<div class="form-group">
			<label for="writer">작성자:</label>
			<input type="text" class="form-control" id="writer" name="writer" value="${a.writer }" readonly="readonly">
		</div>
		<button class="btn btn-primary">수정하기</button>	
		<a class="btn btn-secondary">목록으로</a>
	</form>
</div>

<%@ include file="../layout/footer.jsp" %>

 

 

 

- 에러페이지 만들기

- webapp / WEB-INF / views / error / _404.jsp

 

 

- _404.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    
<%@ include file="../layout/header.jsp" %>

	<div style="text-align: center">
		<h1>잘못된 페이지</h1>
		<a href="${contextPath }"><b>메인페이지로 돌아가기</b></a>
	</div>

<%@ include file="../layout/footer.jsp" %>

 


- 실행해보기

 

로고 누르면 메인화면으로 감

 

 

자유게시판 누르면 게시판으로 감

 

 

글쓰기

 

 

목록에서 글 선택후 삭제 누르기

 

 

 

4번 글 수정

수정 버튼 누르기 ( 기존에 썼던 제목, 내용, 작성자들이 다 받아지면 됨)

 

수정한 뒤

 

 

주소 잘못 요청해보기 (_404 화면)

 

반응형

댓글