CREATE TABLE my_board(
board_id NUMBER PRIMARY KEY,
writer VARCHAR2(30) NOT NULL,
title VARCHAR2(100) NOT NULL,
content VARCHAR2(2000),
reg_date DATE DEFAULT sysdate,
hit NUMBER DEFAULT 0
);
CREATE SEQUENCE board_seq
START WITH 1
INCREMENT BY 1
MAXVALUE 1000
NOCYCLE
NOCACHE;
BoardDAO의 틀을 구축하기 위해 Interface 생성
package kr.co.jsp.board.model;
import java.util.List;
public interface IBoardDAO {
// 글 등록 메서드
void regist(BoardVO newBoard);
// 글 전체 목록을 가지고 오는 메서드
List<BoardVO> listBoard();
// 글 상세보기 요청을 처리할 메서드
BoardVO contentBoard(int Boardid);
// 글 수정 요청을 처리할 메서드(제목, 내용)
void updateBoard(String title, String content, int Boardid);
// 글 삭제 요청을 처리할 메서드
void deleteBoard(int Boardid);
}
package kr.co.jsp.board.model;
import java.sql.Timestamp;
public class BoardVO {
/*
* CREATE TABLE my_board( board_id NUMBER PRIMARY KEY, writer VARCHAR2(30) NOT
* NULL, title VARCHAR2(100) NOT NULL, content VARCHAR2(2000), reg_date DATE
* DEFAULT sysdate, hit NUMBER DEFAULT 0 );
*
* CREATE SEQUENCE board_seq START WITH 1 INCREMENT BY 1 MAXVALUE 1000 NOCYCLE
* NOCACHE;
*/
private int boardId;
private String writer;
private String title;
private String content;
private Timestamp regDate;
private int hit;
public BoardVO() {
// TODO Auto-generated constructor stub
}
public BoardVO(int board_id, String writer, String title, String content, Timestamp regDate, int hit) {
super();
this.boardId = board_id;
this.writer = writer;
this.title = title;
this.content = content;
this.regDate = regDate;
this.hit = hit;
}
public int getboardId() {
return boardId;
}
public void setboardId(int boardId) {
this.boardId = boardId;
}
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 getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Timestamp getRegDate() {
return regDate;
}
public void setRegDate(Timestamp regDate) {
this.regDate = regDate;
}
public int getHit() {
return hit;
}
public void setHit(int hit) {
this.hit = hit;
}
}
package kr.co.jsp.board.model;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import javax.naming.InitialContext;
import javax.sql.DataSource;
public class BoardDAO implements IBoardDAO {
// Connection pool
private DataSource ds;
// 객체를 생성할 때 connection pool 연결
private BoardDAO() {
try {
InitialContext ct = new InitialContext();
// connection pool 대입
ds = (DataSource) ct.lookup("java:comp/env/jdbc/myOracle");
} catch(Exception e) {
e.printStackTrace();
}
}
// Singleton
private static BoardDAO dao = new BoardDAO();
// 단 하나의 객체의 주소값만 반환
public static BoardDAO getInstance() {
if (dao == null) {
dao = new BoardDAO();
}
return dao;
}
///////////////////////////////////////////////
@Override
public void regist(String writer, String title, String content) {
String sql = "INSERT INTO my_board(board_id, writer, title, content) VALUES(board_seq.NEXTVAL, ?, ?, ?)";
try(Connection conn = ds.getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setString(1, writer);
pstmt.setString(2, title);
pstmt.setString(3, content);
pstmt.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public List<BoardVO> listBoard() {
List<BoardVO> articles = new ArrayList<>();
String sql = "SELECT * FROM my_board ORDER BY board_id DESC";
try(Connection conn = ds.getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql);
ResultSet rs = pstmt.executeQuery()){
while (rs.next()) {
BoardVO board = new BoardVO(
rs.getInt("board_id"),
rs.getString("writer"),
rs.getString("title"),
rs.getString("content"),
rs.getTimestamp("reg_date"),
rs.getInt("hit")
);
articles.add(board);
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return articles;
}
@Override
public BoardVO contentBoard(int Boardid) {
BoardVO board = null;
String sql = "SELECT * FROM my_board WHERE board_id = ?";
try(Connection conn = ds.getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql)){
// DB 연결
pstmt.setInt(1, Boardid);
ResultSet rs = pstmt.executeQuery();
if(rs.next()) {
board = new BoardVO(
rs.getInt("board_id"),
rs.getString("writer"),
rs.getString("title"),
rs.getString("content"),
rs.getTimestamp("reg_date"),
rs.getInt("hit"));
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return board;
}
@Override
public void updateBoard(String title, String content, int Boardid) {
String sql = "UPDATE my_board SET title = ?, content = ? WHERE board_id = ?";
try(Connection conn = ds.getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql)){
pstmt.setString(1, title);
pstmt.setString(2, content);
pstmt.setInt(3, Boardid);
pstmt.executeUpdate();
// 쿼리 실행
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void deleteBoard(int Boardid) {
String sql = "DELETE FROM my_board WHERE board_id = ?";
try(Connection conn = ds.getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql)){
pstmt.setInt(1, Boardid);
pstmt.executeUpdate();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public List<BoardVO> searchBoard(String keyword, String category) {
List<BoardVO> boards = new ArrayList<>();
String sql = "SELECT * FROM my_board WHERE " + category + " LIKE ?";
try(Connection conn = ds.getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql)){
pstmt.setString(1, "%" + keyword + "%");
ResultSet rs = pstmt.executeQuery();
while(rs.next()) {
BoardVO board = new BoardVO(
rs.getInt("BOARD_ID"),
rs.getString("WRITER"),
rs.getString("TITLE"),
rs.getString("CONTENT"),
rs.getTimestamp("REG_DATE"),
rs.getInt("HIT")
);
boards.add(board);
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return boards;
}
// hit를 올리기 위한 로직
@Override
public void upHit(int Boardid) {
String sql = "UPDATE my_board SET hit = hit+1 WHERE board_id = ?";
try(Connection conn = ds.getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql)){
pstmt.setInt(1, Boardid);
pstmt.executeUpdate();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
package kr.co.jsp.board.service;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
// 모든 서비스 객체가 하나의 인터페이스 타입으로 객체를 생성할 수 있게 하고 같은 이름의 메서드로 동작할 수 있게 하기 위해 생성
public interface IBoardService {
// 추상 메서드 제작
void execute(HttpServletRequest request, HttpServletResponse response);
// request와 response를 매개 변수로 넘겨줌
}
Controller에서 Regist라는 요청이 들어오면 RegistService로 이동하여 DAO를 활용하여 연산 진행
데이터 베이스에 값을 넣어주는 로직 구현
request객체를 통해 값을 받아서 연산을 진행
package kr.co.jsp.board.service;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import kr.co.jsp.board.model.BoardDAO;
public class RegistService implements IBoardService {
@Override
public void execute(HttpServletRequest request, HttpServletResponse response) {
// controller에서 작성한 값을 받아와서 여기서 실행
System.out.println("글 등록 요청이 들어옴!");
String writer = request.getParameter("bWriter");
String title = request.getParameter("bTitle");
String content = request.getParameter("bContent");
System.out.println("title명" + title);
BoardDAO.getInstance().regist(writer, title, content);
//.board 확장자를 가지고 이름이 list인 곳으로 보냄
// 요청이 다시 들어가야 db에서 데이터를 가져와서 화면에 출력할 수 있음
}
}
Controller에서 List라는 요청이 들어오면 ListService로 이동하여 DAO를 활용하여 연산 진행
request객체를 통해 값을 받아서 연산을 진행
현재 데이터베이스에 있는 모든 게시물을 출력하는 로직 구현
currentTimeMillis()라는 메서드를 활용하여 게시글 작성 시간 차이를 계산
package kr.co.jsp.board.service;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import kr.co.jsp.board.model.BoardDAO;
import kr.co.jsp.board.model.BoardVO;
public class GetListService implements IBoardService {
// 글목록을 가져오는 로직 구현
@Override
public void execute(HttpServletRequest request, HttpServletResponse response) {
// controller에서 수행하던 작업(이동 제어제외) 모두 가져옴
List<BoardVO> boardList = BoardDAO.getInstance().listBoard();
// request에 boardlist에 담으면 응답을 한 뒤 소멸하기 때문에 관리하기 좋음
// boardlist에서 BoardVO를 하나씩 뽑아서 현재 날짜 기준으로 1일이 지났는지 파악
// 이후 1일이 지나지 않았으면 newMark를 사용하는 로직 구현
for(BoardVO board: boardList) {
// 운영체제의 현재 시간을 읽어서 밀리초로 리턴하는 메서드
// currentTimeMillis은 1970년 1월 1일 자정을 기준으로 현재까지 흐른 시간을 밀리초로 리턴
//
long now = System.currentTimeMillis();
// 게시물의 작성 시간을 밀리초로 읽어오기
long regTime = board.getRegDate().getTime();
if (now - regTime < 60 * 60 * 24 * 1000) {
// 하루의 시간보다 작으면
board.setNewMark(true);
}
// else는 굳이 쓸 필요가 없음 (boolean은 default type이 false)
}
request.setAttribute("bList", boardList);
//sendRedirect를 하면 안되는 이유
//request객체에 list를 담아서 전달하려 하는데, sendRedirect를 사용하면
//응답이 나가면서 request 객체가 소멸해 버림
}
}
Controller에서 Content라는 요청이 들어오면 ContentService로 이동하여 DAO를 활용하여 연산 진행
request객체를 통해 값을 받아서 연산을 진행
BoardId를 통해 DAO에 접근해서 BoardId에 맞는 게시물 내용을 보여주는 로직 구현
Cookie를 활용하여 조회 수 조작을 방지하는 로직 구현
package kr.co.jsp.board.service;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import kr.co.jsp.board.model.BoardDAO;
import kr.co.jsp.board.model.BoardVO;
public class ContentService implements IBoardService {
@Override
public void execute(HttpServletRequest request, HttpServletResponse response) {
// content에 대해 controller가 하는 잡일을 모두 가져옴
int bId = Integer.parseInt(request.getParameter("bId"));
/*
# 쿠키로 조회수를 컨트롤 해 보자.
1. 사용자가 글 제목을 눌러서 상세보기 요청을 보낼 때
글 번호로 된 쿠키를 하나 만들어 줄 겁니다. (String)
쿠키 이름과 쿠키에 저장할 값을 모두 글 번호로 만들어 주겠습니다.
2. 요청을 보낼 때 같이 넘어온 쿠키 중에,
현재 글 번호와 일치하는 쿠키가 존재한다면 조회수를 올려주지 않을 겁니다.
현재 글 번호와 일치하는 쿠키가 없다면 조회수를 올려주도록 하겠습니다.
쿠키의 수명은 15초로 설정하겠습니다.
*/
String boardId = request.getParameter("bId");
Cookie cookie = new Cookie(boardId, boardId);
cookie.setMaxAge(15);
response.addCookie(cookie);
Cookie[] hitcookie = request.getCookies();
if (hitcookie.length > 0) {
boolean flag = false;
for (Cookie c : hitcookie) {
if (c.getName().equals(boardId)) {
flag = true;
break;
}
}
if (!flag) {
BoardDAO.getInstance().upHit(bId);
// 조회수 증가
}
}
BoardVO board = BoardDAO.getInstance().contentBoard(bId);
// contentBoard에서 값을 boardvo객체를 받아옴
request.setAttribute("content", board);
}
}
Controller에서 modify라는 요청이 들어오면 ModifyService로 이동하여 DAO를 활용하여 연산 진행
request객체를 통해 값을 받아서 연산을 진행
BoardId를 받아와서 특정 게시물을 찾고 찾은 게시물의 내용을 화면에 출력하여 게시물 수정 준비를 하기 위한 로직 구현
package kr.co.jsp.board.service;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import kr.co.jsp.board.model.BoardDAO;
import kr.co.jsp.board.model.BoardVO;
public class ModifyService implements IBoardService {
@Override
public void execute(HttpServletRequest request, HttpServletResponse response) {
System.out.println(request.getParameter("bId"));
int bId = Integer.parseInt(request.getParameter("bId"));
BoardVO board = BoardDAO.getInstance().contentBoard(bId);
// 글번호를 바탕으로 기존에 저장되어 있는 board 불러오기
request.setAttribute("ModiBoard", board);
System.out.println("modify service 동작 " + board.getboardId());
}
}
Controller에서 update라는 요청이 들어오면 UpdateService로 이동하여 DAO를 활용하여 연산 진행
request객체를 통해 값을 받아서 연산을 진행
BoardId와 수정하고 싶은 제목과 내용을 받아 해당 게시물을 수정하는 로직 구현
package kr.co.jsp.board.service;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import kr.co.jsp.board.model.BoardDAO;
import kr.co.jsp.board.model.BoardVO;
public class UpdateService implements IBoardService {
@Override
public void execute(HttpServletRequest request, HttpServletResponse response) {
int bId = Integer.parseInt(request.getParameter("bId"));
String title = request.getParameter("bTitle");
String content = request.getParameter("bContent");
BoardDAO.getInstance().updateBoard(title, content, bId);
// board_modify.jsp에서 값을 받아와서 update
}
}
Controller에서 delete라는 요청이 들어오면 DeleteService로 이동하여 DAO를 활용하여 연산 진행
request객체를 통해 값을 받아서 연산을 진행
BoardId를 받아서 해당 값을 바탕으로 삭제 연산을 진행하는 로직 구현
package kr.co.jsp.board.service;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import kr.co.jsp.board.model.BoardDAO;
public class DeleteService implements IBoardService {
@Override
public void execute(HttpServletRequest request, HttpServletResponse response) {
int bId = Integer.parseInt(request.getParameter("bId"));
// 요청에서 준 값을 bId로 저장
BoardDAO.getInstance().deleteBoard(bId);
// 받은 값을 바탕으로 DAO에서 삭제 연산 수행
}
}
Controller에서 search라는 요청이 들어오면 SearchService로 이동하여 DAO를 활용하여 연산 진행
request객체를 통해 값을 받아서 연산을 진행
keyword로 검색하고자 하는 값을 받고 category로 검색하고자 하는 컬럼을 받아 특정 검색 값으로 게시물을 검색하는 로직을 구현
만약 검색하고자 하는 게시물이 없다면 다시 전체 게시물을 보여주는 로직을 구현
package kr.co.jsp.board.service;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import kr.co.jsp.board.model.BoardDAO;
import kr.co.jsp.board.model.BoardVO;
public class SearchService implements IBoardService {
@Override
public void execute(HttpServletRequest request, HttpServletResponse response) {
String keyword = request.getParameter("search");
String category = request.getParameter("category");
List<BoardVO> boards = BoardDAO.getInstance().searchBoard(keyword, category);
// 방법1
// if (boards.size() == 0) {
// // 검색 결과가 없으면
// request.setAttribute("searchFail", true);
// } else {
// request.setAttribute("bList", boards);
// board_list.jsp에 값을 보내줄꺼라서 이름을 같게 해야 화면에 출력됨
// board_list.jsp를 건드리지 않고 여기서만 이름을 같게 해주면 동일한 결과 출력
// 방법2
// 자바 클래스에서 html이나 js문법을 사용하는 방법 : PrintWriter 객체를 사용
if (boards.size() == 0) {
response.setContentType("text/html; charset=UTF-8");
try {
PrintWriter out = response.getWriter();
// 원하는 html, js 코드를 문자열 형태로 작성
String htmlCode = "<script> \r\n + "
+ "alert('검색 결과가 없습니다.'); \r\n"
+ "location.href = '/MyWeb/list.board;' \r\n"
+ "</script>";
out.print(htmlCode); // 버퍼에 작성한 문자열을 저장
out.flush(); // 버퍼에 저장되어 있는 내용을 클라이언트로 전송하고 버퍼를 비움
return;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// return 으로 메소드를 강제종료시키면 else안써도 됨
request.setAttribute("bList", boards);
// board_list.jsp에 값을 보내줄꺼라서 이름을 같게 해야 화면에 출력됨
// board_list.jsp를 건드리지 않고 여기서만 이름을 같게 해주면 동일한 결과 출력
}
}