MVC2

Let's Just Go·2022년 6월 7일
0

JSP

목록 보기
10/12

MVC2

  • MVC2
    • con.jsp가 너무 많아지는 단점을 보완하기 위해 나온 모델
    • Controller는 하나만 사용하며 데이터의 흐름만 제어
    • 실제 데이터에 접근하고 가공하는 역할은 Service가 담당

BOARD (CRUD)

  • MVC1으로 작성되었던 것을 MVC2로 변경
  • CREATE BOARD
    • BOARD 생성
      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;

  • IBoardDAO
    • 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);
      	
      }

  • BoardVO
    • Board에 들어가는 변수들을 한번에 모아주기 위해 객체 생성
      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;
      	}
      }

  • BoardDAO
    • Connection pool을 활용
    • 기존의 DAO와 유사하지만 Connection Pool을 활용하여 메소드마다 매번 적던 DB연결 코드를 간소화
      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();
      		}
      		
      	}
      
      }

Service

  • JSTL
  • Service
    • Controller는 흐름만 제어해주는 역할이며 나머지는 Service가 수행
    • Controller와 DAO 사이에 있으며 Controller를 도와주는 역할
    • 값을 받아오거나 연산은 모두 Service에서 수행 즉, controller의 역할인 흐름을 제어하는 것 이외에는 모두 service가 실행


IBoardService

  • IBoardService
    • Interface를 생성하여 하나의 틀에서 서로 다른 기능을 하도록 수행
      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를 매개 변수로 넘겨줌
      	
      	
      }

RegistService

  • RegistService
    • 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에서 데이터를 가져와서 화면에 출력할 수 있음
      	}
      
      }

ListService

  • ListService
    • 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 객체가 소멸해 버림
      		
      	}
      }

ContentService

  • ContentService
    • 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);
      	}
      
      }

ModifyService

  • ModifyService
    • 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());
      		
      		
      
      	}
      
      }

UpdateService

  • UpdateService
    • 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
      	}
      
      }

DeleteService

  • DeleteService
    • 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에서 삭제 연산 수행 
      
      	}
      
      }

SearchService

  • SearchService
    • 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를 건드리지 않고 여기서만 이름을 같게 해주면 동일한 결과 출력
      
      		
      
      	}
      }
  • 이제 Service는 다 만들었으므로 Controller 만들면 끄읏~
profile
안녕하세요! 공부한 내용을 기록하는 공간입니다.

0개의 댓글