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">&nbsp;</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}">
					&nbsp;
				</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. 

+ Recent posts