MVC2 패턴을 사용할 것이므로 우선 DTO와 DAO를 생성해주겠습니다.
MVC2 패턴은 JSP에서 모든 것을 하는 MVC1 패턴과는 달리 Servlet에서 웹 브라우저가 요청하는 것을 처리하므로 유지보수가 쉽고, 코드 가독성도 좋습니다.
DTO와 DAO는 MVC에서 M(Model) 부분에 해당합니다. 프로그램의 데이터 부분에 속합니다.
DTO (Data Transfer Object) 생성
DAO 등과 연동하여 데이터를 실어나르는 객체로, 필요한 객체 (entity)만큼 작성합니다.
VO(Volumne Object)라고도 하는데, VO는 read only/immutable 속성을 가집니다.
웹 개발 시 클래스 필드명, DB 필드명, form의 name명은 일치시켜 주어야 편리합니다.
src/main/java 폴더 내에 com.beans 패키지를 생성한 뒤 BookDTO 클래스를 생성합니다.
package com.beans;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class BookDTO {
private int uid; // bk_uid
private String title; // bk_title
private String summary; // bk_summary
private int price; // bk_price
private int viewCnt; // bk_viewcnt
private LocalDateTime regDate; // bk_regdate
public BookDTO() {
super();
}
public BookDTO(int uid, String title, String summary, int price, int viewCnt, LocalDateTime regDate) {
super();
this.uid = uid;
this.title = title;
this.summary = summary;
this.price = price;
this.viewCnt = viewCnt;
this.regDate = regDate;
}
public int getUid() {
return uid;
}
public void setUid(int uid) {
this.uid = uid;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getSummary() {
return summary;
}
public void setSummary(String summary) {
this.summary = summary;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public int getViewCnt() {
return viewCnt;
}
public void setViewCnt(int viewCnt) {
this.viewCnt = viewCnt;
}
public LocalDateTime getRegDate() {
return regDate;
}
public void setRegDate(LocalDateTime regDate) {
this.regDate = regDate;
}
public String getRegDateTime() {
if (this.regDate == null) return "";
return this.regDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss"));
}
}
기본 생성자와 모든 매개변수를 가진 생성자를 만들어주고, 필드 각각의 getter와 setter도 생성해줍니다.
마우스 오른쪽 클릭하여 Source - Generate Getters and Setters를 클릭하면 getter와 setter를 편하게 만들 수 있고, 생성자도 Source - Fenerate Constructor user Fields를 이용하면 편리하게 만들 수 있습니다.
getRegDateTime() 메서드를 하나 생성해주었습니다.
RegDate 값을 가져올 때 포맷 형식을 지정해주기 위함입니다.
DAO (Data Access Object) 생성
특정 데이터 리소스(ex. DB)에 접속하여 트랜잭션 등을 전담하는 객체입니다.
DTO 객체를 통해 데이터를 연결합니다.
일반적으로 데이터 리소스별로 작성하거나 기능별(게시판용, 회원 관리용 등)로 작성합니다.
DAO에서 게시판 관리를 위한 코드를 작성하는데, 이때 데이터베이스와 관련된 부분은 DAO에 함께 두기보다는 따로 관리하는 게 더 좋습니다.
따라서 common 패키지를 생성한 뒤 해당 패키지 내에 D 클래스를 만들어 데이터베이스 연결 부분과 SQL문을 작성합니다. 만약 상수만 있는 경우에는 class가 아닌 interface로 생성하여도 됩니다.
D.java의 내용은 게시판 만들기 - 01에서 작성한 BookBatch.java 파일에서 복사해오면 됩니다.
package common;
public class D {
public static final String DRIVER = "com.mysql.cj.jdbc.Driver";
public static final String URL = "jdbc:mysql://localhost:3306/boards";
public static final String USERID =
public static final String USERPW =
public static final String SQL_WRITE_INSERT =
"INSERT INTO book"
+ "(bk_title, bk_summary, bk_price)"
+ "VALUES(?, ?, ?)";
}
우선 SQL 문은 INSERT문만 작성했습니다.
추후 기능을 구현하며 SQL문을 더 만들게 될 것입니다.
이제 DAO를 만들어보겠습니다.
package com.beans;
import java.sql.*;
import common.D;
public class BookDAO {
Connection conn;
PreparedStatement pstmt;
ResultSet rs;
public BookDAO() {
try {
Class.forName(D.DRIVER);
conn = DriverManager.getConnection(D.URL, D.USERID, D.USERPW);
} catch(Exception e) {
e.printStackTrace();
}
}
public void close() throws SQLException {
if (rs != null) rs.close();
if (pstmt != null) pstmt.close();
if (conn != null) conn.close();
}
}
D 클래스를 import하였습니다. DRIVER, URL, USERID, USERPW 모두 static으로 선언해주었기 때문에 D.으로 불러올 수 있습니다.
자원 관리를 위해 close() 메서드를 따로 만들어서 해당 메서드 내에서 모든 자원을 close() 해줍니다.
자원 누수는 큰 문제이므로 자원 반납을 잊으면 안됩니다 ! ! !
이때 SQLException을 throws하면 try~catch 문을 사용하지 않아도 되어서 조금 간편해집니다.
Controller 생성
지금까지는 Model 부분을 만들었습니다. 이제 MVC에서 C(Controller) 부분을 만듭니다. Servlet이 MVC2 패턴에서 Controller 역할을 합니다.
request가 오면 Controller 역할을 하는 Servlet에서 Model 작업을 처리하도록 하고, 처리된 작업을 다시 서블릿이 받으면 Servlet은 이를 View(현재 jsp)에 보내고 이를 사용자에게 response 하는 것입니다.
서블릿은 java 파일이므로 웹에서 접근 가능한 형태로 하기 위해 서블릿과 URL을 연결해주는 URL Mapping이 필수입니다.
src/main/java 폴더 내에 서블릿을 생성합니다.
Java package는 com.controller로 해주었고, Class Name은 BookController로 해줍니다.
사용자 정의 서블릿을 만들기 위해서는 반드시 HttpServelt을 상속받아야 합니다.
Next로 넘어가 URL mappings를 변경합니다.
/BookController로 되어있던 것을 *.do로 바꿔주었습니다. 이는 원래의 URL 주소 대신 *.do로 매핑합니다. * 부분에는 모든 문자열을 포함한다는 뜻으로 어떠한 문자열도 위치할 수 있습니다.
보통 클래스 명은 해당 클래스의 기능으로 짓게 되는데 이것이 URL에 그대로 보이는 경우 클래스가 어떤 기능을 할지 짐작할 수 있기 때문에 보안상 좋지 않습니다. 따라서 다른 이름으로 매핑하여 본 이름을 감추는 것입니다.
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;
/**
* Servlet implementation class BookController
*/
@WebServlet("*.do")
public class BookController extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public BookController() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
response.getWriter().append("Served at: ").append(request.getContextPath());
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
서블릿이 생성되면 위와 같이 생성됩니다.
위 코드와 같이 @WebServlet 어노테이션으로 URL 매핑을 할 수 있습니다.
또한 web.xml에서 설정하여 URL 매핑도 가능합니다.
현재까지 생성된 파일은 다음과 같습니다.
Github
https://github.com/MJKim99/JSP_Board_Book.git