Main functions
1. Connection Pool
2. Reply function
3. File attachment and download function by using cos library
4. request object
5. Controller Class: Java Servlet
6. Model = Service + DAO (Service, DTO, DAO class)
7. View(User Interface) : EL, JSLT
Please refer to the figures for a better understanding of the structure of this project.
1. Create a Dynamic Web Project model2board.
2. Test the Connection Pool
3. Create a folder(boardupload) to save uploaded files.
4. Create a sql folder and create board.sql.
5. Create a table and a sequence.
--Model2 Bulletin Board
select * from tab;
select * from seq;
select * from model2;
create table model2(
board_num number primary key,
board_name varchar2(20),
board_pass varchar2(15),
board_subject varchar2(50),
board_content varchar2(2000),
board_file varchar2(50),
board_re_ref number,
board_re_lev number,
board_re_seq number,
board_readcount number,
board_date timestamp );
create sequence model2_seq
start with 1
increment by 1
nocache;
6. Create a BoardBean(DTO) Class in src-model.
// DTO(Data Transfer Object)
package model;
import java.sql.Timestamp;
public class BoardBean {
private int board_num;
private String board_name;
private String board_pass;
private String board_subject;
private String board_content;
private String board_file;
private int board_re_ref;
private int board_re_lev;
private int board_re_seq;
private int board_readcount;
private Timestamp board_date;
public int getBoard_num() {
return board_num;
}
public String getBoard_name() {
return board_name;
}
public String getBoard_pass() {
return board_pass;
}
public String getBoard_subject() {
return board_subject;
}
public String getBoard_content() {
return board_content;
}
public String getBoard_file() {
return board_file;
}
public int getBoard_re_ref() {
return board_re_ref;
}
public int getBoard_re_lev() {
return board_re_lev;
}
public int getBoard_re_seq() {
return board_re_seq;
}
public int getBoard_readcount() {
return board_readcount;
}
public Timestamp getBoard_date() {
return board_date;
}
public void setBoard_num(int board_num) {
this.board_num = board_num;
}
public void setBoard_name(String board_name) {
this.board_name = board_name;
}
public void setBoard_pass(String board_pass) {
this.board_pass = board_pass;
}
public void setBoard_subject(String board_subject) {
this.board_subject = board_subject;
}
public void setBoard_content(String board_content) {
this.board_content = board_content;
}
public void setBoard_file(String board_file) {
this.board_file = board_file;
}
public void setBoard_re_ref(int board_re_ref) {
this.board_re_ref = board_re_ref;
}
public void setBoard_re_lev(int board_re_lev) {
this.board_re_lev = board_re_lev;
}
public void setBoard_re_seq(int board_re_seq) {
this.board_re_seq = board_re_seq;
}
public void setBoard_readcount(int board_readcount) {
this.board_readcount = board_readcount;
}
public void setBoard_date(Timestamp board_date) {
this.board_date = board_date;
}
}
7. Create a BoardDAO Class in src-dao and create a Singleton and Connection instance.
//DAO(Data Access Object)
package dao;
import java.sql.Connection;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;
public class BoardDAO {
// Singleton
private static BoardDAO instance = new BoardDAO();
public static BoardDAO getInstance() { // Static method
return instance;
}
// Connection from Connection Pool
private Connection getConnection() throws Exception {
Context init = new InitialContext();
DataSource ds = (DataSource) init.lookup("java:comp/env/jdbc/orcl");
return ds.getConnection();
}
}
8. Create BoardFrontController class in src-controller. The controller class has to be made as a Java Servlet Class.
.do is the general extension of actions using Apache Struts.
package 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 BoardFrontController
*/
@WebServlet("*.do") // Do extension
public class BoardFrontController extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doProcess(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String requestURI = request.getRequestURI();
String contextPath = request.getContextPath();
String command = requestURI.substring(contextPath.length());
System.out.println("requestURI: "+requestURI);
System.out.println("contextPath: "+contextPath);
System.out.println("command: "+command);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
System.out.println("get");
doProcess(request, response); // To call doProcess method
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
System.out.println("post");
doProcess(request, response); // To call doProcess method
}
}
9. Create an Action interface in src-service.
package service;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public interface Action {
// Abstract method
public ActionForward execute(HttpServletRequest request, HttpServletResponse response) throws Exception;
}
10. Create an ActionForward Class in src-service.
package service;
public class ActionForward {
private boolean redirect; // To set the forwarding method
private String path; // To save the file name to forward
public boolean isRedirect() {
return redirect;
}
public String getPath() {
return path;
}
public void setRedirect(boolean redirect) {
this.redirect = redirect;
}
public void setPath(String path) {
this.path = path;
}
}
11. Add action and forward part in the controller class.
Action action = null;
ActionForward forward = null;
// Writng a content
if(command.equals("/BoardAddAction.do")) {
try {
action = new BoardAddAction();
forward = action.execute(request, response);
}catch(Exception e) {
e.printStackTrace();
}
}
// Forwarding process
if(forward != null) {
if(forward.isRedirect()) { //true -> Redirect method
response.sendRedirect(forward.getPath());
}else { //not true -> Dispatcher method
RequestDispatcher dispatcher =
request.getRequestDispatcher(forward.getPath());
dispatcher.forward(request, response);
}
}
}
12. Create a BoardAddAction Class in src-service. This class is for file upload/download.
13. Create a qna_board_write.jsp.
Here, enctype="multipart/form-data" is essential for the file attachment function.
<%@ page language="java" contentType="text/html; charset=utf-8"%>
<html>
<head>
<title>MVC Bulletin Board</title>
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script src="<%=request.getContextPath() %>/board/script.js"></script>
<style>
@import url('https://fonts.googleapis.com/css2?family=Abril+Fatface&display=swap');
</style>
</head>
<body>
<form action="<%=request.getContextPath() %>/BoardAddAction.do" method="post"
enctype="multipart/form-data">
<table cellpadding="0" cellspacing="0" align=center border=1>
<tr align="center" valign="middle">
<td style="font-family: 'Abril Fatface', cursive;" colspan="5">MVC Bulletin Board</td>
</tr>
<tr>
<td style="font-family: 'Abril Fatface', cursive; font-size:12" height="16">
<div align="center">Writer</div>
</td>
<td>
<input name="board_name" id="board_name" type="text" size="10" maxlength="10"
value=""/>
</td>
</tr>
<tr>
<td style="font-family: 'Abril Fatface', cursive; font-size:12" height="16">
<div align="center">Password</div>
</td>
<td>
<input name="board_pass" id="board_pass" type="password" size="10" maxlength="10"
value=""/>
</td>
</tr>
<tr>
<td style="font-family: 'Abril Fatface', cursive; font-size:12" height="16">
<div align="center">Title</div>
</td>
<td>
<input name="board_subject" id="board_subject" type="text" size="50" maxlength="100"
value=""/>
</td>
</tr>
<tr>
<td style="font-family: 'Abril Fatface', cursive; font-size:12">
<div align="center">Content</div>
</td>
<td>
<textarea name="board_content" id="board_content" cols="67" rows="15"></textarea>
</td>
</tr>
<tr>
<td style="font-family: 'Abril Fatface', cursive; font-size:12">
<div align="center">Attach File</div>
</td>
<td>
<input name="board_file" type="file"/>
</td>
</tr>
<tr bgcolor="cccccc">
<td colspan="2" style="height:1px;">
</td>
</tr>
<tr><td colspan="2"> </td></tr>
<tr align="center" valign="middle">
<td colspan="5">
<input type=submit value="Post">
<input type=reset value="Cancel">
</td>
</tr>
</table>
</form>
</body>
</html>
14. In the DAO class, add the insert method.
// Insert method : Post
public int insert(BoardBean board) {
int result = 0;
Connection con = null;
PreparedStatement pstmt = null;
try {
con = getConnection();
String sql = "insert into model2 values(model2_seq.nextval,?,?,?,?,?,";
sql += " model2_seq.nextval,?,?,?,sysdate)";
pstmt = con.prepareStatement(sql);
pstmt.setString(1, board.getBoard_name());
pstmt.setString(2, board.getBoard_pass());
pstmt.setString(3, board.getBoard_subject());
pstmt.setString(4, board.getBoard_content());
pstmt.setString(5, board.getBoard_file());
pstmt.setInt(6, 0); // board_re_lev
pstmt.setInt(7, 0); // board_re_seq
pstmt.setInt(8, 0); // board_readcount
result = pstmt.executeUpdate(); // To execute SQL
} catch (Exception e) {
e.printStackTrace();
} finally {
if(pstmt != null) try { pstmt.close();} catch(Exception e) {}
if(con != null) try { con.close();} catch(Exception e) {}
}
return result;
}
When you upload the file, you will check the file by copying and pasting the path from the console.
15. Create BoardListAction.java in src-service.
package service;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import dao.BoardDAO;
public class BoardListAction implements Action{
@Override
public ActionForward execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
// TODO Auto-generated method stub
System.out.println("BoardListAction");
int page = 1; // Current Page
int limit = 10; // How many pages will be printed? 10
if(request.getParameter("page") != null) {
page = Integer.parseInt(request.getParameter("page"));
}
// ex) page = 1 : startRow = 1, endRow : 10
int startRow = (page -1) * limit + 1;
int endRow = page * limit;
BoardDAO dao = BoardDAO.getInstance();
int listcount = dao.getCount(); // Total data volume
System.out.println("listcount: "+listcount);
ActionForward forward = new ActionForward();
forward.setRedirect(false); // Dispatcher method
forward.setPath("./board/qna_board_list.jsp");
return forward;
}
}
16. In the Controller class, add the Post list part.
// Posts list
}else if(command.equals("/BoardListAction.do")){
try {
action = new BoardListAction();
forward = action.execute(request, response);
}catch(Exception e){
e.printStackTrace();
}
17. In the DAO class, add the total data volume part.
// Total data volum
public int getCount() {
int result = 0;
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
con = getConnection();
String sql="select count(*) from model2";
pstmt = con.prepareStatement(sql);
rs = pstmt.executeQuery();
if(rs.next()) {
// result = rs.getInt(1);
result = rs.getInt("count(*)");
}
}catch(Exception e) {
e.printStackTrace();
}finally {
if(pstmt != null) try { pstmt.close();} catch(Exception e) {}
if(con != null) try { con.close();} catch(Exception e) {}
if(rs != null) try { rs.close();} catch(Exception e) {}
}
return result;
}
18. Add the get list method in BoardListAction.java and DAO class.
BoardListAction.java
//To get List
List<BoardBean> boardlist = dao.getList(startRow, endRow);
System.out.println("boardlist: "+boardlist);
//Total pages number
int pageCount = listcount / limit + (( listcount%limit == 0 )? 0 : 1); //if the result of listcount%limit is 0, increase 0, otherwise increase 1.
int startPage = ((page-1)/ 10) * limit + 1; // 1, 11, 22...
int endPage = startPage + 10 - 1; // 10, 20, 30...
if(endPage > pageCount) endPage = pageCount;
request.setAttribute("page", page);
request.setAttribute("listcount", listcount);
request.setAttribute("boardlist", boardlist);
request.setAttribute("pageCount", pageCount);
request.setAttribute("startPage", startPage);
request.setAttribute("endPage", endPage);
BoardDAO.java
// Posts List ( 10 data)
public List<BoardBean> getList(int start, int end){
List<BoardBean> list = new ArrayList<BoardBean>();
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
con = getConnection();
String sql="select * from (select rownum rnum, board.* from ";
sql+=" (select * from model2 order by board_re_ref desc, ";
sql+=" board_re_seq asc) board ) ";
sql+=" where rnum >= ? and rnum <= ?";
pstmt = con.prepareStatement(sql);
pstmt.setInt(1, start);
pstmt.setInt(2, end);
rs = pstmt.executeQuery(); //SQL
while(rs.next()) {
BoardBean board = new BoardBean();
board.setBoard_num(rs.getInt("board_num"));
board.setBoard_name(rs.getString("board_name"));
board.setBoard_pass(rs.getString("board_pass"));
board.setBoard_subject(rs.getString("board_subject"));
board.setBoard_content(rs.getString("board_content"));
board.setBoard_file(rs.getString("board_file"));
board.setBoard_re_ref(rs.getInt("board_re_ref"));
board.setBoard_re_lev(rs.getInt("board_re_lev"));
board.setBoard_re_seq(rs.getInt("board_re_seq"));
board.setBoard_readcount(rs.getInt("board_readcount"));
board.setBoard_date(rs.getTimestamp("board_date"));
list.add(board);
}
}catch(Exception e) {
e.printStackTrace();
}finally {
if(pstmt != null) try { pstmt.close();} catch(Exception e) {}
if(con != null) try { con.close();} catch(Exception e) {}
if(rs != null) try { rs.close();} catch(Exception e) {}
}
return list;
}
19. Create qna_board_list.jsp and print out the posts list.
<%@ page language="java" contentType="text/html; charset=EUC-KR"
pageEncoding="EUC-KR"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<a href="./BoardForm.do">Write my post</a>
<br>
Posts : ${listcount}
<br>
<%
int count = ((Integer) request.getAttribute("listcount")).intValue();
%>
Total posts :<%=count%>
<br>
<table border=1 width=700 align=center>
<caption>Posts List</caption>
<tr>
<th>No.</th>
<th>Title</th>
<th>Writer</th>
<th>Date</th>
<th>View</th>
</tr>
<c:set var="num" value="${listcount - (page-1) * 10}" />
<c:forEach var="b" items="${boardlist}">
<tr>
<td>${num}<c:set var="num" value="${num-1}" />
</td>
<td>
<!-- Space before reply -->
<c:if test="${b.board_re_lev > 0}">
<c:forEach var="i" begin="0" end="${b.board_re_lev}">
</c:forEach>
</c:if>
<a href="./BoardDetailAction.do?board_num=${b.board_num}&page=${page}">
${b.board_subject}</a>
</td>
<td>${b.board_name}</td>
<td><fmt:formatDate value="${b.board_date}"
pattern="dd.MM.yyyy HH:mm:ss EEEE" /></td>
<td>${b.board_readcount }</td>
</tr>
</c:forEach>
</table>
When you run the index.jsp, you will see the posts list.
We will keep putting more functions into this project in the following posts.