Model 2

To modify our project with Model 2, you first need to learn about EL and JSTL.

EL

EL is an expression made for easy access to the data available in JSP.
EL is included in the JSP specification. EL provides easier access to JavaBean's property values.
${user.email} is equivalent to calling the getEmail() method of the User object.
You do not need to know exactly which scope the User object is in.
User objects in ${user.email} are retrieved in the following order: pageScope, requestScope, sessionScope, applicationScope.

The following is a list of the implicit objects available in the EL.

  • pageScope
  • requestScope
  • sessionScope
  • applicationScope
  • param
  • paramValues
  • header
  • headerValues
  • initParam
  • cookie
  • pageContext

When accessing the value of the searchWord parameter, use an implicit object like ${param.searchWord}.
${param.searchWord} prints "" instead of null, even if the searchWord parameter is not passed.

In Model 2, the view only serves to show the data received.
The role of producing data should be the responsibility of the model.
Therefore, you should not use a scriptlet as much as possible in the view of Model 2.

JSTL

A tag library is a technique for creating tags that change into Java code.
The JST Standard Tag Library (JSTL) provides a standard for tag libraries. JSTL is not included in the JSP specification.
Therefore, you need to download the library to use JSTL.
Download and extract the most recent version of JSTL from http://archive.apache.org/dist/jakarta/taglibs/standard/binaries/.
Copy jstl.jar and standard.jar from the lib folder to WEB-INF/lib.
The core of JSTL is the most used. To use the core, add the taglib directive to the JSP as shown below.

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

The following is a JSP for testing JSTL. Create it on the document base.

/jstl.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.util.*" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%
int firstPage = 21;
int lastPage = 30;
ArrayList<Integer> a = new ArrayList<Integer>();
a.add(1);a.add(2);a.add(3);
a.add(4);a.add(5);a.add(6);
a.add(7);a.add(8);a.add(9);a.add(10);
%>
<c:set var="a" value="<%=a %>" />
<c:set var="c" value="" />
<c:set var="firstPage" value="<%=firstPage %>" />
<c:set var="lastPage" value="<%=lastPage %>" />
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>JSTL core examples</title>
</head>
<body>
<h1>if statement</h1>

<c:if test="${empty b }">
    <h4>b list is empty.</h4>
</c:if>

<c:if test="${not empty c }">
    <h4>c is not null and is not "".</h4>
</c:if>

<c:choose>
    <c:when test="${empty a }">
        <h4>List is empty.</h4>
    </c:when>
</c:choose>

<h1>if ~ else statement</h1>
<c:choose>
    <c:when test="${empty a }">
        <h4>List is empty.</h4>
    </c:when>
    <c:otherwise>
        <h4>List is not empty.</h4>
    </c:otherwise>
</c:choose>

<h1>for statement</h1>
<c:forEach var="i" begin="${firstPage }" end="${lastPage }">
    [${i }]
</c:forEach>

<h1>for statement</h1>
<table>
<c:forEach var="i" items="${a }" varStatus="status">
    <tr>
        <td>${status.index }</td><td>${i }</td>
    </tr>
</c:forEach>
</table>
</body>
</html>

The above example briefly introduces the most important core usage in JSTL.
Now you are ready to change the Model 1 board to the Model 2 board.
Major changes are as follows.

  • All JSPs use EL and JSTL.
  • JSP only shows the data it receives.
  • Create an action class that is responsible for the business logic.
  • Requests with the extension * .do are sent to the controller.
  • Change the parameter name curPage, which contains the page number, to page.

Update JSPs

Use EL and JSTL to modify the code, and change all .jsp to .do, except for the jsp used in the include directive.

header.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<h1 style="float: left;width: 150px;"><a href="/"><img src="/images/ci.gif" alt="java-school" /></a></h1>
<div id="memberMenu" style="float: right;position: relative;top: 7px;">
<c:choose>
    <c:when test="${empty user}">
        <input type="button" value="Login" onclick="location.href='/users/login.do'" />
        <input type="button" value="SignUp" onclick="location.href='/users/signUp.do'" />
    </c:when>
    <c:otherwise>
        <input type="button" value="Logout" onclick="location.href='/users/logout.do'" />
        <input type="button" value="Modify Account" onclick="location.href='/users/editAccount.do'" />
    </c:otherwise>
</c:choose>
</div>
bbs-sub.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<h1>BBS</h1>
<ul>
    <li>
        <ul>
            <li><a href="list.do?boardCd=free&page=1">Small talk</a></li>
            <li><a href="list.do?boardCd=qna&page=1">Q & A</a></li>
        </ul>
    </li>
</ul>

In the same way, modify main-menu.jsp.
The above JSP file is simple and does not require program logic.
JSPs that show lists require program logic.
Therefore, we add a tag library directive to use JSTL core.
Delete the code that includes loginCheck.jsp.
The logic in logincheck.jsp will be implemented in the action class.

list.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="Keywords" content="Board list" />
<meta name="Description" content="Board list" />
<title>Small talk</title>
<link rel="stylesheet" href="/css/screen.css" type="text/css"  />
<script>
function goList(page) {
    var form = document.getElementById("listForm");
    form.page.value = page;
    form.submit();
}
function goView(articleNo) {
    var form = document.getElementById("viewForm");
    form.articleNo.value = articleNo;
    form.submit();
}
function goWrite() {
    var form = document.getElementById("writeForm");
    form.submit();
}
</script>           
</head>
<body>

<div id="wrap">

    <div id="header">
        <%@ include file="../inc/header.jsp" %>
    </div>

    <div id="main-menu">
        <%@ include file="../inc/main-menu.jsp" %>
    </div>

    <div id="container">
        <div id="content">
<div id="content-categories">Small talk</div>
<!-- List heading -->
<table class="bbs-table">
<tr>
    <th style="width: 60px">NO</th>
    <th>TITLE</th>
    <th style="width: 84px;">DATE</th>
    <th style="width: 60px;">HIT</th>
</tr>
<!-- List itmes -->
<c:forEach var="article" items="${list }" varStatus="status">
<tr>
    <td style="text-align: center;">${listItemNo - status.index }</td>
    <td>
        <a href="javascript:goView('${article.articeNo }')">${article.title }</a>
        <c:if test="${article.attachFileNum > 0 }">
        <img src="../images/attach.png" alt="Attach File" style="vertical-align: middle;" />
        </c:if>
        <c:if test="${article.commentNum > 0 }">
        <span class="bbs-strong">[${article.commentNum }]</span>
        </c:if>
    </td>
    <td style="text-align: center;">${article.regdate }</td>
    <td style="text-align: center;">${article.hit }</td>
</tr>
</c:forEach>
<!-- List items end -->
</table>
<div id="paging">
    <c:if test="${prevPage > 0 }">
        <a href="javascript:goList('${prevPage }')">[Prev]</a>
    </c:if>
    <c:forEach var="i" begin="${firstPage }" end="${lastPage }">
        <c:choose>
            <c:when test="${param.page == i }">
            <span class="bbs-strong">${i }</span>
            </c:when>
            <c:otherwise>
            <a href="javascript:goList('${i }')">${i }</a>
            </c:otherwise>
        </c:choose>
    </c:forEach>
    <c:if test="${nextPage > 0 }">
        <a href="javascript:goList('${nextPage }')">[Next]</a>
    </c:if>
</div>
<div id="list-menu">
    <input type="button" value="New" onclick="goWrite()" />
</div>
<form action="list.do" method="get">
    <input type="hidden" name="page" value="1" />
    <input type="hidden" name="boardCd" value="${param.boardCd }" />
    <div id="search">
    <input type="text" name="searchWord" size="15" maxlength="30" />
    <input type="submit" value="Search" />
    </div>
</form>

        </div><!-- content end -->
    </div><!-- container end -->
    
    <div id="sidebar">
        <%@ include file="bbs-sub.jsp" %>
    </div>
    
    <div id="extra">
        <%@ include file="../inc/extra.jsp" %>
    </div>

    <div id="footer">
        <%@ include file="../inc/footer.jsp" %>
    </div>

</div>

<div id="form-group" style="display: none">
    <form id="listForm" action="list.do" method="get">
        <input type="hidden" name="boardCd" value="${param.boardCd }" />
        <input type="hidden" name="page" />
        <input type="hidden" name="searchWord" value="${param.searchWord }" />
    </form>
    <form id="viewForm" action="view.do" method="get">
        <input type="hidden" name="articleNo" />
        <input type="hidden" name="boardCd" value="${param.boardCd }" />
        <input type="hidden" name="page" value="${param.page }" />
        <input type="hidden" name="searchWord" value="${param.searchWord }" />
    </form>
    <form id="writeForm" action="write_form.do" method="get">
        <input type="hidden" name="boardCd" value="${param.boardCd }" />
        <input type="hidden" name="page" value="${param.page }" />
        <input type="hidden" name="searchWord" value="${param.searchWord }" />
    </form>
</div>

</body>
</html>

The action class should create the following data and pass it to list.jsp.

  • boardNm: Board name
  • list: List of articles
  • listItemNo: List items No
  • prevPage: page number for [Prev]
  • firstPage: first page number of current block
  • lastPage: last page number of current block
  • nextPage: page number fo [Next]
view.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="Keywords" content="Board detailed view" />
<meta name="Description" content="Board detailed view" />
<title>${boardNm }</title>
<link rel="stylesheet" href="/css/screen.css" type="text/css" />
<script>
function modifyCommentToggle(articleNo) {
    var p_id = "comment" + articleNo;
    var form_id = "modifyCommentForm" + articleNo;
    var p = document.getElementById(p_id);
    var form = document.getElementById(form_id);
    
    var p_display;
    var form_display;
    
    if (p.style.display) {
        p_display = '';
        form_display = 'none';
    } else {
        p_display = 'none';
        form_display = '';
    }
    
    p.style.display = p_display;
    form.style.display = form_display;
}
function goList(page) {
    var form = document.getElementById("listForm");
    form.page.value = page;
    form.submit();
}
function goView(articleNo) {
    var form = document.getElementById("viewForm");
    form.articleNo.value = articleNo;
    form.submit();
}
function goWrite() {
    var form = document.getElementById("writeForm");
    form.submit();
}
function goModify() {
    var form = document.getElementById("modifyForm");
    form.submit();
}
function goDelete() {
    var check = confirm("Are you sure you want to delete it?");
    if (check) {
        var form = document.getElementById("delForm");
        form.submit();
    }
}
function deleteAttachFile(attachFileNo) {
    var check = confirm("Are you sure you want to delete it?");
    if (check) {
        var form = document.getElementById("deleteAttachFileForm");
        form.attachFileNo.value = attachFileNo;
        form.submit();
    }
}
function deleteComment(commentNo) {
    var check = confirm("Are you sure you want to delete it?");
    if (check) {
        var form = document.getElementById("deleteCommentForm");
        form.commentNo.value = commentNo;
        form.submit();
    }
}
</script>           
</head>
<body>

<div id="wrap">

    <div id="header">
        <%@ include file="../inc/header.jsp" %>
    </div>

    <div id="main-menu">
        <%@ include file="../inc/main-menu.jsp" %>
    </div>

    <div id="container">
        <div id="content">
<!-- content begin -->
<div id="content-categories">${boardNm }</div>
<div class="view-menu" style="margin-top: 15px;margin-bottom: 5px;">
    <c:if test="${user.email == email }">
    <div class="fl">
        <input type="button" value="Modify" onclick="goModify()" />
        <input type="button" value="Del" onclick="goDelete()"/>
    </div>
    </c:if>
    <div class="fr">
        <c:if test="${nextArticle != null }">
        <input type="button" value="Next Article" onclick="goView('${nextArticle.articleNo }')" />
        </c:if>
        <c:if test="${prevArticle != null }">
        <input type="button" value="Prev Article" onclick="goView('${prevArticle.articleNo }')" />
        </c:if>
        <input type="button" value="List" onclick="goList('${param.page }')" />
        <input type="button" value="New" onclick="goWrite()" />
    </div>
</div>
<table class="bbs-table">
<tr>
    <th style="width: 47px;text-align: left;vertical-align: top;font-size: 1em;">TITLE</th>
    <th style="text-align: left;color: #555;font-size: 1em;">${title }</th>
</tr> 
</table>
<div id="detail">
    <div id="date-writer-hit">edited ${regdate } by ${name } hit ${hit }</div>
    <div id="article-content">${content }</div>
    <div id="file-list" style="text-align: right">
    <c:forEach var="file" items="${attachFileList }" varStatus="status">
        <div id="attach-file">
            <a href="${uploadPath }${file.filename }">${file.filename }</a>
            <c:if test="${user.email == file.email }">
            <a href="javascript:deleteAttachFile('${file.attachFileNo }')">x</a>
            </c:if>
         </div>
    </c:forEach>
    </p>
</div>
<form id="addCommentForm" action="addComment.do" method="post">
    <input type="hidden" name="articleNo" value="${param.articleNo }"/>
    <input type="hidden" name="boardCd" value="${param.boardCd }" />
    <input type="hidden" name="page" value="${param.page }" />
    <input type="hidden" name="searchWord" value="${param.searchWord }" />       
    <div id="addComment">
        <textarea name="memo" rows="7" cols="50"></textarea>
    </div>
    <div style="text-align: right;">
        <input type="submit" value="Add comment" />
    </div>
</form>
<c:forEach var="comment" items="${commentList }" varStatus="status">
<div class="comments">
    <span class="writer">${comment.name }</span>
    <span class="date">${comment.regdate }</span>
    <c:if test="${user.email == comment.email }">
    <span class="modify-del">
        <a href="javascript:modifyCommentToggle('${comment.commentNo }')">Modify</a>
         | <a href="javascript:deleteComment('${comment.commentNo }')">Del</a>
    </span>
    </c:if>
    <p id="comment${comment.commentNo }">${comment.memo }</p>
    <form id="modifyCommentForm${comment.commentNo }" class="comment-form" action="updateComment.do" method="post" style="display: none;">
        <input type="hidden" name="commentNo" value="${comment.commentNo }" />
        <input type="hidden" name="boardCd" value="${param.boardCd }" />
        <input type="hidden" name="articleNo" value="${param.articleNo }" />
        <input type="hidden" name="page" value="${param.page }" />
        <input type="hidden" name="searchWord" value="${param.searchWord }" />
	    <div class="fr">
	            <a href="javascript:document.forms.modifyCommentForm${comment.commentNo }.submit()">Submit</a>
	            | <a href="javascript:modifyCommentToggle('${comment.commentNo }')">Cancel</a>
	    </div>
	    <div>
	        <textarea class="comment-textarea" name="memo" rows="7" cols="50">${comment.memo }</textarea>
	    </div>
    </form>
</div>
</c:forEach>
<div id="next-prev">
    <c:if test="${nextArticle != null }">
    <p>Next Article : <a href="javascript:goView('${nextArticle.articleNo }')">${nextArticle.title }</a></p>
    </c:if>
    <c:if test="${prevArticle != null }">
    <p>Prev Article : <a href="javascript:goView('${prevArticle.articleNo }')">${prevArticle.title }</a></p>
    </c:if>
</div>
<div class="view-menu">
    <c:if test="${user.email == email }">
    <div class="fl">
        <input type="button" value="Modify" onclick="goModify()" />
        <input type="button" value="Del" onclick="goDelete()"/>
    </div>
    </c:if>
    <div class="fr">
        <c:if test="${nextArticle != null }">
        <input type="button" value="Next Article" onclick="goView('${nextArticle.articleNo }')" />
        </c:if>
        <c:if test="${prevArticle != null }">
        <input type="button" value="Prev Article" onclick="goView('${prevArticle.articleNo }')" />
        </c:if>
        <input type="button" value="List" onclick="goList('${param.page }')" />
        <input type="button" value="New" onclick="goWrite()" />
    </div>
</div>
<!-- List -->
<table class="bbs-table">
<tr>
    <th style="width: 60px">NO</th>
    <th>TITLE</th>
    <th style="width: 84px;">DATE</th>
    <th style="width: 60px;">HIT</th>
</tr>
<c:forEach var="article" items="${list }" varStatus="status">
<tr>
    <td style="text-align: center;">
    <c:choose>
        <c:when test="${param.articleNo == article.articleNo }">
        <img src="../images/arrow.gif" alt="You are reading this" />
        </c:when>
        <c:otherwise>
        ${listItemNo - status.index }
        </c:otherwise>
    </c:choose>
    </td>
    <td>
        <a href="javascript:goView('${article.articleNo }')">${article.title }</a>
        <c:if test="${article.attachFileNum > 0 }">
        <img src="/images/attach.png" alt="Attach File" style="vertical-align: middle;" />
        </c:if>
        <c:if test="${article.commentNum > 0 }">
        <span class="bbs-strong">[${article.commentNum }]</span>
        </c:if>
    </td>
    <td style="text-align: center;">${article.regdate }</td>
    <td style="text-align: center;">${article.hit }</td>
</tr>
</c:forEach>
</table>
<div id="paging">
    <c:if test="${prevPage > 0 }">
        <a href="javascript:goList('${prevPage }')">[Prev]</a>
    </c:if>
    <c:forEach var="i" begin="${firstPage }" end="${lastPage }">
        <c:choose>
            <c:when test="${param.page == i }">
                <span class="bbs-strong">${i }</span>
            </c:when>
            <c:otherwise>
                <a href="javascript:goList('${i }')">${i }</a>
            </c:otherwise>
        </c:choose>  
    </c:forEach>
    <c:if test="${nextPage > 0 }">
        <a href="javascript:goList('${nextPage }')">[Next]</a>
    </c:if>
</div>
<div id="list-menu">
    <input type="button" value="New" onclick="goWrite()" />
</div>
<form action="list.do" method="get">
    <input type="hidden" name="page" value="1" />
    <input type="hidden" name="boardCd" value="${param.boardCd }" />
    <div id="search">
        <input type="text" name="searchWord" size="15" maxlength="30" />
        <input type="submit" value="Search" />
    </div>
</form>
<!-- content end -->
        </div><!-- content end -->
    </div><!--  container end -->
    
    <div id="sidebar">
        <%@ include file="bbs-sub.jsp" %>
    </div>
    
    <div id="extra">
        <%@ include file="../inc/extra.jsp" %>
    </div>

    <div id="footer">
        <%@ include file="../inc/footer.jsp" %>
    </div>

</div>

<div id="form-group" style="display: none">
    <form id="listForm" action="list.do" method="get">
        <input type="hidden" name="boardCd" value="${param.boardCd }" />
        <input type="hidden" name="page" />
        <input type="hidden" name="searchWord" value="${param.searchWord }" />
    </form>
    <form id="viewForm" action="view.do" method="get">
        <input type="hidden" name="articleNo" />
        <input type="hidden" name="boardCd" value="${param.boardCd }" />
        <input type="hidden" name="page" value="${param.page }" />
        <input type="hidden" name="searchWord" value="${param.searchWord }" />
    </form>
    <form id="writeForm" action="write_form.do" method="get">
        <input type="hidden" name="articleNo" value="${param.articleNo }" />
        <input type="hidden" name="boardCd" value="${param.boardCd }" />
        <input type="hidden" name="page" value="${param.page }" />
        <input type="hidden" name="searchWord" value="${param.searchWord }" />
    </form>
    <form id="modifyForm" action="modify_form.do" method="get">
        <input type="hidden" name="articleNo" value="${param.articleNo }" />
        <input type="hidden" name="boardCd" value="${param.boardCd }" />
        <input type="hidden" name="page" value="${param.page }" />
        <input type="hidden" name="searchWord" value="${param.searchWord }" />
    </form>
    <form id="delForm" action="del.do" method="post">
        <input type="hidden" name="articleNo" value="${param.articleNo }" />
        <input type="hidden" name="boardCd" value="${param.boardCd }" />
        <input type="hidden" name="page" value="${param.page }" />
        <input type="hidden" name="searchWord" value="${param.searchWord }" />
    </form>
    <form id="deleteCommentForm" action="deleteComment.do" method="post">
        <input type="hidden" name="commentNo" />
        <input type="hidden" name="articleNo" value="${param.articleNo }" />
        <input type="hidden" name="boardCd" value="${param.boardCd }" />
        <input type="hidden" name="page" value="${param.page }" />
        <input type="hidden" name="searchWord" value="${param.searchWord }" />
    </form>   
    <form id="deleteAttachFileForm" action="deleteAttachFile.do" method="post">
        <input type="hidden" name="attachFileNo" />
        <input type="hidden" name="articleNo" value="${param.articleNo }" />
        <input type="hidden" name="boardCd" value="${param.boardCd }" />
        <input type="hidden" name="page" value="${param.page }" />
        <input type="hidden" name="searchWord" value="${param.searchWord }" />
    </form>       
</div>

</body>
</html>

The data that the action class creates and passes to view.jsp is as follows.

  • boardNm
  • title
  • regdate
  • name: Owner'name
  • hit: read count
  • content: content of the article
  • attachFileList: List of attachfiles
  • commentList: List of comments
  • nextArticle: Next article object
  • prevArticle: Prev article object
  • -- Below are the same as the list --
  • list
  • listItemNo
  • prevPage
  • firstPage
  • lastPage
  • nextPage

Modify the contents and file name of the write_form.jsp of model 1 as follows.

write.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> 
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="Keywords" content="New article form" />
<meta name="Description" content="New article form" />
<title>${boardNm }</title>
<link rel="stylesheet" href="/css/screen.css" type="text/css" />
<script>
function goList() {
    var form = document.getElementById("listForm");
    form.submit();
}
function goView() {
    var form = document.getElementById("viewForm");
    form.submit();
}
</script>           
</head>
<body>

<div id="wrap">

    <div id="header">
        <%@ include file="../inc/header.jsp" %>
    </div>

    <div id="main-menu">
        <%@ include file="../inc/main-menu.jsp" %>
    </div>

    <div id="container">
        <div id="content">
<!-- content begin -->
<div id="content-categories">${boardNm }</div>
<h3>New article</h3>
<form id="writeForm" action="write.do" method="post" enctype="multipart/form-data">
<input type="hidden" name="boardCd" value="${param.boardCd }" />
<table id="write-form" class="bbs-table">
<tr>
    <td>Title</td>
    <td><input type="text" name="title" style="width: 90%;" /></td>
</tr>
<tr>
    <td colspan="2">
        <textarea name="content" rows="17" cols="50"></textarea>
    </td>
</tr>
<tr>
    <td>Attach File</td>
    <td><input type="file" name="attachFile" /></td>
</tr>
</table>
<div style="text-align: center;padding-bottom: 15px;">
    <input type="submit" value="Submit" />
    <input type="button" value="List" onclick="goList()" />
    <c:if test="${not empty param.articleNo }">
    <input type="button" value="Detailed view" onclick="goView()" />
    </c:if>
</div>
</form>
<!-- content end -->
        </div>
    </div>
    
    <div id="sidebar">
        <%@ include file="bbs-sub.jsp" %>
    </div>
    
    <div id="extra">
        <%@ include file="../inc/extra.jsp" %>
    </div>

    <div id="footer">
        <%@ include file="../inc/footer.jsp" %>   
    </div>

</div>

<div id="form-group" style="display: none">
    <form id="viewForm" action="view.do" method="get">
        <input type="hidden" name="articleNo" value="${param.articleNo }" />
        <input type="hidden" name="boardCd" value="${param.boardCd }" />
        <input type="hidden" name="page" value="${param.page }" />
        <input type="hidden" name="searchWord" value="${param.searchWord }" />
    </form>
    <form id="listForm" action="list.do" method="get">
        <input type="hidden" name="boardCd" value="${param.boardCd }" />
        <input type="hidden" name="page" value="${param.page }" />
        <input type="hidden" name="searchWord" value="${param.searchWord }" />
    </form>   
</div>

</body>
</html>

The data that the action class creates and passes to write.jsp is the name of the board.

Modify the contents and filename of modify_form.jsp in Model 1 as shown below.

modify.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="Keywords" content="Modify form page" />
<meta name="Description" content="Modify form page" />
<title>${boardNm }</title>
<link rel="stylesheet" href="/css/screen.css" type="text/css"  />
<script>
function check() {
    //var form = document.getElementById("modifyForm");
    //TODO validaion logic
    return true;
}
function goView() {
    var form = document.getElementById("viewForm");
    form.submit();
}
</script>           
</head>
<body>

<div id="wrap">

    <div id="header">
        <%@ include file="../inc/header.jsp" %>
    </div>

    <div id="main-menu">
        <%@ include file="../inc/main-menu.jsp" %>
    </div>

    <div id="container">
        <div id="content">
<!-- content begin -->
<div id="content-categories">${boardNm }</div>
<h3>Modify</h3>
<form id="modifyForm" action="modify.do" method="post" enctype="multipart/form-data" onsubmit="return check();">
<input type="hidden" name="articleNo" value="${param.articleNo }" />
<input type="hidden" name="boardCd" value="${param.boardCd }" />
<input type="hidden" name="page" value="${param.page }" />
<input type="hidden" name="searchWord" value="${param.searchWord }" />
<table id="write-form" class="bbs-table">
<tr>
    <td>Title</td>
    <td><input type="text" name="title" style="width: 90%;" value="${title }" /></td>
</tr>
<tr>
    <td colspan="2">
        <textarea name="content" rows="17" cols="50">${content }</textarea>
    </td>
</tr>
<tr>
    <td>Attach File</td>
    <td><input type="file" name="attachFile" /></td>
</tr>
</table>
<div style="text-align: center;padding-bottom: 15px;">
    <input type="submit" value="Submit" />
    <input type="button" value="Detailed view" onclick="goView()" />
</div>
</form>
<!-- content end -->
        </div><!-- content end -->
    </div><!--  container end -->
    
    <div id="sidebar">
        <%@ include file="bbs-sub.jsp" %>
    </div>
    
    <div id="extra">
        <%@ include file="../inc/extra.jsp" %>
    </div>

    <div id="footer">
        <%@ include file="../inc/footer.jsp" %>
    </div>

</div>

<div id="form-group" style="display: none">
    <form id="viewForm" action="view.do" method="get">
        <input type="hidden" name="articleNo" value="${param.articleNo }" />
        <input type="hidden" name="boardCd" value="${param.boardCd }" />
        <input type="hidden" name="page" value="${param.page }" />
        <input type="hidden" name="searchWord" value="${param.searchWord }" />
    </form>
</div>

</body>
</html>

The data that the action class creates and passes to modify.jsp is as follows.

  • boardNm
  • title
  • content

Next, we modify the screen design of the member.
Replace all .jsp files except for the jsp used in the include directive with .do.

user-sub.jsp
<h1><Membership</h1>
<ul>
  <c:choose>
      <c:when test="${empty check}">
        <li><a href="/users/login">Login</a></li>
        <li><a href="/users/signUp">SignUp</a></li>
        <li><a href="#">Forgot ID</a></li>
        <li><a href="#">Forgot Password</a></li>
      </c:when>
      <c:otherwise>
        <li><a href="/users/editAccount">Modify Account</a></li>
        <li><a href="/users/changePasswd">Change Password</a></li>
        <li><a href="/users/bye">Bye</a></li>
      </c:otherwise>
  </c:choose>
</ul>
login.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="Keywords" content="Login" />
<meta name="Description" content="Login" />
<title>Login</title>
<link rel="stylesheet" href="/css/screen.css" type="text/css" />
<script>
function check() {
    //var form = document.getElementById("loginForm");
    //TODO validation logic
    return true;
}
</script>           
</head>
<body>

<div id="wrap">

    <div id="header">

    </div>

    <div id="main-menu">
        <%@ include file="../inc/main-menu.jsp" %>
    </div>

    <div id="container">
        <div id="content">
<!-- content begin -->
<div id="content-categories">Membership</div>
<h2>Login</h2>
<c:if test="${not empty param.msg }">
<p style="color: red;">Login Failed!</p>
</c:if>      
<form id="loginForm" action="login.do" method="post" onsubmit="return check()">
<p style="margin: 0; padding: 0;">
<input type="hidden" name="url" value="${param.url }" />
</p>
<table>
<tr>
    <td style="width: 200px;">Email</td>
    <td style="width: 390px"><input type="text" name="email" style="width: 99%;" /></td>
</tr>
<tr>
    <td>Password</td>
    <td><input type="password" name="passwd" style="width: 99%;" /></td>
</tr>
</table>
<div style="text-align: center;padding: 15px 0;">
    <input type="submit" value="Submit" />
    <input type="button" value="Sign Up" onclick="location.href='signUp.do'" />
</div>
</form>
<!-- content end -->
        </div><!-- content end -->
    </div><!--  container end -->
    
    <div id="sidebar">
        <%@ include file="user-sub.jsp" %>
    </div>
    
    <div id="extra">
        <%@ include file="../inc/extra.jsp" %>
    </div>

    <div id="footer">
        <%@ include file="../inc/footer.jsp" %>
    </div>

</div>

</body>
</html>
signUp.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="Keywords" content="Sign Up" />
<meta name="Description" content="Sign Up" />
<title>Sign Up</title>
<link rel="stylesheet" href="/css/screen.css" type="text/css" />
<script>
function check() {
    //var form = document.getElementById("signUpForm");
    //TODO validation logic
    return true;
}
</script>           
</head>
<body>

<div id="wrap">

    <div id="header">
        <%@ include file="../inc/header.jsp" %>
    </div>

    <div id="main-menu">
        <%@ include file="../inc/main-menu.jsp" %>
    </div>

    <div id="container">
        <div id="content">
<!-- content begin -->        
<h3>Sign Up</h3>
<form id="signUpForm" action="signUp.do" method="post" onsubmit="return check()">
<table>
<tr>
    <td style="width: 200px;">Full Name</td>
    <td style="width: 390px"><input type="text" name="name" style="width: 99%;" /></td>
</tr>
<tr>
    <td>Password</td>
    <td><input type="password" name="passwd" style="width: 99%;" /></td>
</tr>
<tr>
    <td colspan="2" style="text-align: center;font-weight: bold;">
    Do not make the password the same as your email account password because Email is used as an ID.
    </td>
</tr>
<tr>
    <td>Confirm</td>
    <td><input type="password" name="confirm" style="width: 99%;" /></td>
</tr>
<tr>
    <td>Email</td>
    <td><input type="text" name="email" style="width: 99%;" /></td>
</tr>
<tr>
    <td>Mobile</td>
    <td><input type="text" name="mobile" style="width: 99%;" /></td>
</tr>
</table>
<div style="text-align: center;padding-bottom: 15px;">
    <input type="submit" value="Submit" />
</div>
</form>
<!-- content end -->
        </div><!-- content end -->
    </div><!--  container end -->
    
    <div id="sidebar">
        <%@ include file="user-sub.jsp" %>
    </div>
    
    <div id="extra">
        <%@ include file="../inc/extra.jsp" %>
    </div>

    <div id="footer">
        <%@ include file="../inc/footer.jsp" %>
    </div>

</div>

</body>
</html>
welcome.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="Keywords" content="Welcome" />
<meta name="Description" content="Welcome" />
<title>Welcome</title>
<link rel="stylesheet" href="/css/screen.css" type="text/css"  />
</head>
<body>

<div id="wrap">

    <div id="header">
        <%@ include file="../inc/header.jsp" %>
    </div>

    <div id="main-menu">
        <%@ include file="../inc/main-menu.jsp" %>
    </div>

    <div id="container">
        <div id="content">
<!-- content begin -->        
<h3>Welcome</h3>
<p>
The email you entered at registration will be used as an ID.<br />
<input type="button" value="Login" onclick="javascript:location.href='login.do'" />
</p>
<!-- content end -->
        </div><!-- content end -->
    </div><!--  container end -->
    
    <div id="sidebar">
        <h1>Welcome</h1>
    </div>
    
    <div id="extra">
        <%@ include file="../inc/extra.jsp" %>
    </div>

    <div id="footer">
        <%@ include file="../inc/footer.jsp" %>
    </div>

</div>

</body>
</html>
editAccount.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="Keywords" content="Modify account" />
<meta name="Description" content="Modify account" />
<title>Modify account</title>
<link rel="stylesheet" href="/css/screen.css" type="text/css"  />
<script>
function check() {
    //var form = document.getElementById("editAccountForm");
    //TODO validation logic
    return true;
}
</script>
</head>
<body>

<div id="wrap">

    <div id="header">
        <%@ include file="../inc/header.jsp" %>
    </div>

    <div id="main-menu">
        <%@ include file="../inc/main-menu.jsp" %>
    </div>

    <div id="container">
        <div id="content">
<!-- content begin -->        
<h3>Modify account</h3>
<p>
You can edit your account information except your password. <a href="changePasswd.do">Change password</a>
</p>
<form id="editAccountForm" action="editAccount.do" method="post" onsubmit="return check()">
<table>
<tr>
    <td>Full Name</td>
    <td><input type="text" name="name" value="${user.name }" /></td>
</tr>
<tr>
    <td>Mobile</td>
    <td><input type="text" name="mobile" value="${user.mobile }" /></td>
</tr>
<tr>
    <td>Password</td>
    <td><input type="password" name="passwd" /></td>
</tr>
<tr>
    <td colspan="2"><input type="submit" value="전송" /></td>
</tr>
</table>
</form>
<!-- content end -->
        </div><!-- content end -->
    </div><!--  container end -->
    
    <div id="sidebar">
        <%@ include file="user-sub.jsp" %>
    </div>
    
    <div id="extra">
        <%@ include file="../inc/extra.jsp" %>
    </div>

    <div id="footer">
        <%@ include file="../inc/footer.jsp" %>
    </div>

</div>

</body>
</html>
changePasswd.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="Keywords" content="Change password" />
<meta name="Description" content="Change password" />
<title>Change password</title>
<link rel="stylesheet" href="/css/screen.css" type="text/css"  />
<script>
function check() {
    var form = document.getElementById("changePasswordForm");
    if (form.newPasswd.value == form.confirm.value) {
        return true;    
    } else {
        alert("[Change Password] and [Change Password Confirm] values are not the same.");
        return false;
    }
}
</script>           
</head>
<body>

<div id="wrap">

    <div id="header">
        <%@ include file="../inc/header.jsp" %>
    </div>

    <div id="main-menu">
        <%@ include file="../inc/main-menu.jsp" %>
    </div>

    <div id="container">
        <div id="content">
<!-- content begin -->        
<h3>Change password</h3>
<p>
${user.name }<br />
${user.mobile }<br />
</p>
<form id="changePasswordForm" action="changePasswd.do" method="post" onsubmit="return check()">
<table>
<tr>
    <td>Current Password</td>
    <td><input type="password" name="currentPasswd" /></td>   
</tr>
<tr>
    <td>Change password</td>
    <td><input type="password" name="newPasswd" /></td>
</tr>
<tr>
    <td>Change password confirm</td>
    <td><input type="password" name="confirm" /></td>
</tr>
<tr>
    <td colspan="2"><input type="submit" value="Submit" /></td>
</tr>
</table>
</form>
        </div><!-- content end -->
    </div><!--  container end -->

    <div id="sidebar">
        <%@ include file="user-sub.jsp" %>
    </div>

    <div id="extra">
        <%@ include file="../inc/extra.jsp" %>
    </div>

    <div id="footer">
        <%@ include file="../inc/footer.jsp" %>
    </div>

</div>

</body>
</html>
changePasswd_confirm.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="Keywords" content="Password change confirm" />
<meta name="Description" content="Password change confirm" />
<title>Password change confirm</title>
<link rel="stylesheet" href="/css/screen.css" type="text/css"  />
</head>
<body>

<div id="wrap">

    <div id="header">
        <%@ include file="../inc/header.jsp" %>
    </div>

    <div id="main-menu">
        <%@ include file="../inc/main-menu.jsp" %>
    </div>

    <div id="container">
<div id="content">
<!-- content begin -->        
<h3>Password Changed.</h3>
<p>
You can login with the changed password.<br />
<input type="button" value="Login" onclick="javascript:location.href='login.do'" />
</p>
<!-- content end -->
        </div>
    </div><!--  container end -->
    
    <div id="sidebar">
        <%@ include file="user-sub.jsp" %>
    </div>
    
    <div id="extra">
        <%@ include file="../inc/extra.jsp" %>
    </div>

    <div id="footer">
        <%@ include file="../inc/footer.jsp" %>
    </div>

</div>

</body>
</html>
bye.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="Keywords" content="Bye" />
<meta name="Description" content="Bye" />
<title>Bye</title>
<link rel="stylesheet" href="/css/screen.css" type="text/css" />
<script>
function check() {
    //var form = document.getElementById("byeForm");
    //TODO validation logic
    return true;
}
</script>           
</head>
<body>

<div id="wrap">

    <div id="header">
        <%@ include file="../inc/header.jsp" %>
    </div>

    <div id="main-menu">
        <%@ include file="../inc/main-menu.jsp" %>
    </div>

    <div id="container">
        <div id="content">
<!-- content begin -->
<div id="content-categories">Membership</div>
<h3>Bye</h3>
<form id="byeForm" action="bye.do" method="post" onsubmit="return check()">
<table>
<tr>
    <td>Email</td>
    <td><input type="text" name="email" /></td>   
</tr>
<tr>
    <td>Password</td>
    <td><input type="password" name="passwd" /></td>  
</tr>
<tr>
    <td colspan="2"><input type="submit" value="Submit" /></td>
</tr>
</table>
</form>
<!-- content end -->
        </div>
    </div><!--  container end -->

    <div id="sidebar">
        <%@ include file="user-sub.jsp" %>
    </div>

    <div id="extra">
        <%@ include file="../inc/extra.jsp" %>
    </div>

    <div id="footer">
        <%@ include file="../inc/footer.jsp" %>
    </div>

</div>

</body>
</html>

error.jsp

You do not need to modify it with JSTL because it handles all errors with one error page.
Modify all .jsp files except for the jsp used in the include directive to .do.

/error.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="net.java_school.user.User" %>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="Keywords" content="Error" />
<meta name="Description" content="Error" />
<title>Error</title>
<link rel="stylesheet" href="/css/screen.css" type="text/css" />
</head>
<body>
<%
//Analyze the servlet exception
Throwable throwable = (Throwable) request.getAttribute("javax.servlet.error.exception");
Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
String servletName = (String) request.getAttribute("javax.servlet.error.servlet_name");

if (servletName == null) {
    servletName = "Unknown";
}

String requestUri = (String) request.getAttribute("javax.servlet.error.request_uri");

if (requestUri == null) {
    requestUri = "Unknown";
}
%>
<div id="wrap">

    <div id="header">
        <%@ include file="./inc/header.jsp" %>
    </div>

    <div id="main-menu">
        <%@ include file="./inc/main-menu.jsp" %>
    </div>

    <div id="container">
        <div id="content">
<!--  content begin -->
<div id="content-categories">Error</div>
<h3>Error Page</h3>
<%
if(statusCode != 500){
    out.write("<h3>Error Details</h3>");
    out.write("<strong>Status Code</strong>:" + statusCode + "<br>");
    out.write("<strong>Requested URI</strong>:"+requestUri);
}
if (throwable != null) {
    out.write("<h3>Exception Details</h3>");
    out.write("<ul><li>Servlet Name:" + servletName + "</li>");
    out.write("<li>Exception Name:" + throwable.getClass().getName() + "</li>");
    out.write("<li>Requested URI:" + requestUri + "</li>");
    out.write("<li>Exception Message:" + throwable.getMessage() + "</li>");
    out.write("</ul>");
}
%>
<!-- content end -->
        </div>
    </div><!--  container end -->
    
    <div id="sidebar">
        <h1>Error</h1>
    </div>
    
    <div id="extra">
        <%@ include file="./inc/extra.jsp" %> 
    </div>

    <div id="footer">
        <%@ include file="./inc/footer.jsp" %>
    </div>

</div>

</body>
</html>

The home page also changes all .jsp to .do, except for the jsp used in the include directive.

Implementation

The ActionForward class is the type returned by the execute() method of the action class.
The ActionForward object stores only the address information to be moved and whether to redirect.
If the redirect is false, it is forwarded to the configured address.
The action class creates an address that is forwarded or redirected, stores it in ActionForward, and returns ActionForward.

ActionForward.java
package net.java_school.action;

public class ActionForward {
    private boolean isRedirect;
    private String view;
    
    public boolean isRedirect() {
        return isRedirect;
    }
    public void setRedirect(boolean isRedirect) {
        this.isRedirect = isRedirect;
    }
    public String getView() {
        return view;
    }
    public void setView(String view) {
        this.view = view;
    }
}

All action classes must implement the Action interface.

Action.java
package net.java_school.action;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public interface Action {
    public ActionForward execute(HttpServletRequest req, HttpServletResponse resp) throws IOException;
}

This is a custom exception class to use when authentication fails.
It inherits runtime exceptions.

AuthenticationException.java
package net.java_school.exception;

public class AuthenticationException extends RuntimeException {

    private static final long serialVersionUID = -2916142666133028059L;

    public AuthenticationException() {
        super();
    }

    public AuthenticationException(String message, Throwable cause,
            boolean enableSuppression, boolean writableStackTrace) {
        super(message, cause, enableSuppression, writableStackTrace);
    }

    public AuthenticationException(String message, Throwable cause) {
        super(message, cause);
    }

    public AuthenticationException(String message) {
        super(message);
    }

    public AuthenticationException(Throwable cause) {
        super(cause);
    }
    
}

Create a controller that handles * .do requests.

Controller.java
package net.java_school.controller;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.java_school.action.Action;
import net.java_school.action.ActionForward;
import net.java_school.exception.AuthenticationException;

public class Controller extends HttpServlet {

    private static final long serialVersionUID = 4024375917229853991L;
    
    @Override
    public void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        doPost(req,resp);
    }
    
    @Override
    public void doPost(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
            
        req.setCharacterEncoding("UTF-8");
        
        String uri = req.getRequestURI();
        String contextPath = req.getContextPath();
        String command = uri.substring(contextPath.length());
        
        String view = null;
        Action action = null;
        ActionForward forward = null;
        
        try {
            if (command.equals("/bbs/list.do") && req.getMethod().equals("GET")) {
                //action = new ListAction();
                forward = action.execute(req, resp);
            } else if (command.equals("/bbs/view.do") && req.getMethod().equals("GET")) {
                //action = new ViewAction();
                forward = action.execute(req, resp);
            } else if (command.equals("/bbs/write.do") && req.getMethod().equals("GET")) {
                //action = new WriteFormAction();
                forward = action.execute(req, resp);
            } else if (command.equals("/bbs/write.do") && req.getMethod().equals("POST")) {
                //action = new WriteAction();
                forward = action.execute(req, resp);
            } else if (command.equals("/bbs/addComment.do") && req.getMethod().equals("POST")) {
                //action = new AddCommentAction();
                forward = action.execute(req, resp);
            } else if (command.equals("/bbs/updateComment.do") && req.getMethod().equals("POST")) {
                //action = new UpdateCommentAction();
                forward = action.execute(req, resp);
            } else if (command.equals("/bbs/deleteComment.do") && req.getMethod().equals("POST")) {
                //action = new DeleteCommentAction();
                forward = action.execute(req, resp);
            } else if (command.equals("/bbs/deleteAttachFile.do") && req.getMethod().equals("POST")) {
                //action = new DeleteAttachFileAction();
                forward = action.execute(req, resp);                
            } else if (command.equals("/bbs/modify.do") && req.getMethod().equals("GET")) {
                //action = new ModifyFormAction();
                forward = action.execute(req, resp);
            } else if (command.equals("/bbs/modify.do") && req.getMethod().equals("POST")) {
                //action = new ModifyAction();
                forward = action.execute(req, resp);
            } else if (command.equals("/bbs/del.do") && req.getMethod().equals("POST")) {
                //action = new DeleteAction();
                forward = action.execute(req, resp);
            } else if (command.equals("/users/changePasswd.do") && req.getMethod().equals("GET")) {
                //action = new ChangePasswdFormAction();
                forward = action.execute(req, resp);
            } else if (command.equals("/users/changePasswd.do") && req.getMethod().equals("POST")) {
                //action = new ChangePasswdAction();
                forward = action.execute(req, resp);
            } else if (command.equals("/users/changePasswd_confirm.do") && req.getMethod().equals("GET")) {
                forward = new ActionForward();
                forward.setView("/users/changePasswd_confirm.jsp");             
            } else if (command.equals("/users/signUp.do") && req.getMethod().equals("GET")) {
                forward = new ActionForward();
                forward.setView("/users/signUp.jsp");
            } else if (command.equals("/users/signUp.do") && req.getMethod().equals("POST")) {
                //action = new SignUpAction();
                forward = action.execute(req, resp);
            } else if (command.equals("/users/welcome.do") && req.getMethod().equals("GET")) {
                forward = new ActionForward();
                forward.setView("/users/welcome.jsp");              
            } else if (command.equals("/users/editAccount.do") && req.getMethod().equals("GET")) {
                //action = new EditAccountFormAction();
                forward = action.execute(req, resp);
            } else if (command.equals("/users/editAccount.do") && req.getMethod().equals("POST")) {
                //action = new EditAccountAction();
                forward = action.execute(req, resp);
            } else if (command.equals("/users/bye.do") && req.getMethod().equals("GET")) {
                //action = new ByeFormAction();
                forward = action.execute(req, resp);
            } else if (command.equals("/users/bye.do") && req.getMethod().equals("POST")) {
                //action = new ByeAction();
                forward = action.execute(req, resp);
            } else if (command.equals("/users/login.do") && req.getMethod().equals("GET")) {
                forward = new ActionForward();
                forward.setView("/users/login.jsp");
            } else if (command.equals("/users/login.do") && req.getMethod().equals("POST")) {
                //action = new LoginAction();
                forward = action.execute(req, resp);
            } else if (command.equals("/users/logout.do") && req.getMethod().equals("POST")) {
                //action = new LogoutAction();
                forward = action.execute(req, resp);
            }
            
            view = forward.getView();
            
            if (forward.isRedirect() == false) {
                RequestDispatcher rd = this.getServletContext().getRequestDispatcher(view);
                rd.forward(req, resp);
            } else {
                resp.sendRedirect(view);
            }
        } catch (AuthenticationException e) {
            //If an authentication failure exception is passed to the controller, the controller passes an error message to the container.
            resp.sendError(HttpServletResponse.SC_FORBIDDEN, e.getMessage());
        }
        
    }
    
}

Declare the controller servlet in web.xml and map it to the specific URL.

web.xml
<servlet>
   <servlet-name>controller</servlet-name>
   <servlet-class>net.java_school.controller.Controller</servlet-class>
   <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
   <servlet-name>controller</servlet-name>
   <url-pattern>*.do</url-pattern>
</servlet-mapping>

Add Line Separator to the WebContants.java.

WebContants.java
package net.java_school.commons;

public class WebContants {
    //Session key
    public final static String USER_KEY = "user";
    //Error Message
    public final static String NOT_LOGIN = "Not Login";
    public final static String AUTHENTICATION_FAILED = "Authentication Failed";
    //Line Separator
    public final static String LINE_SEPARATOR = System.getProperty("line.separator");
}

Bulletin boards are available only to logged-in users.
So implement login first.
Refer to the implementation of login_proc.jsp in Model 1 to create an action class to handle login.
This class works when a login.do POST request comes in.
If login fails, go back to login page.

LoginAction.java
package net.java_school.user.action;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import net.java_school.action.Action;
import net.java_school.action.ActionForward;
import net.java_school.commons.WebContants;
import net.java_school.user.User;
import net.java_school.user.UserService;

public class LoginAction implements Action {

    @Override
    public ActionForward execute(HttpServletRequest req, 
        HttpServletResponse resp) throws IOException {
        
        String url = req.getParameter("url");
        
        String email = req.getParameter("email");
        String passwd = req.getParameter("passwd");

        UserService service = new UserService();
        User user = service.login(email, passwd);

        ActionForward forward = new ActionForward();
         
        if (user == null) {
            forward.setView("/users/login.do?url=" + url +"&msg=Login-Failed");
            forward.setRedirect(true);
        } else {
            HttpSession session = req.getSession();
            session.setAttribute(WebContants.USER_KEY, user);
            if (url != null && !url.equals("")) {
                forward.setView(url);
                forward.setRedirect(true);
            } else {
                forward.setView("/bbs/list.do?boardCd=free&page=1");
                forward.setRedirect(true);
            }
        }
        
        return forward;
    }

}

The code that redirects to the login screen was used to get the context path so that login would work on any other URL.
The address for redirect and the address for forwarding should be obtained differently.
Addresses for forwarding use addresses that begin with / after the context path, not the context path.
In the case of a redirect, a relative path is obtained based on the position of a page to which a redirect URL is sent, or an address including a context path is used.

LogoutAction.java
package net.java_school.user.action;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import net.java_school.action.Action;
import net.java_school.action.ActionForward;
import net.java_school.commons.WebContants;

public class LogoutAction implements Action {

    @Override
    public ActionForward execute(HttpServletRequest req,
            HttpServletResponse resp) throws IOException {
            
        ActionForward forward = new ActionForward();
                
        HttpSession session = req.getSession();
        session.removeAttribute(WebContants.USER_KEY);

        String contextPath = req.getContextPath();
        forward.setView("/");//go to homepage
        forward.setRedirect(true);

        return forward;
    }

}

The SignUpAction action class handles subscription.

SignUpAction.java
package net.java_school.user.action;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.java_school.action.Action;
import net.java_school.action.ActionForward;
import net.java_school.user.User;
import net.java_school.user.UserService;

public class SignUpAction implements Action {

    @Override
    public ActionForward execute(HttpServletRequest req,
            HttpServletResponse resp) throws IOException {

        ActionForward forward = new ActionForward();

        String email = req.getParameter("email");
        String passwd = req.getParameter("passwd");
        String name = req.getParameter("name");
        String mobile = req.getParameter("mobile");

        User user = new User(email, passwd, name, mobile);

        UserService service = new UserService();
        service.addUser(user);

        forward.setView("welcome.do");
        forward.setRedirect(true);

        return forward;
    }

}

The EditAccountFormAction action class works when the /users/editAccount.do request is passed to the controller by clicking the Edit My Info button.

EditAccountFormAction.java
package net.java_school.user.action;

import java.io.IOException;
import java.net.URLEncoder;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import net.java_school.action.Action;
import net.java_school.action.ActionForward;
import net.java_school.commons.WebContants;
import net.java_school.user.User;

public class EditAccountFormAction implements Action {

    @Override
    public ActionForward execute(HttpServletRequest req,
            HttpServletResponse resp) throws IOException {

        ActionForward forward = new ActionForward();

        HttpSession session = req.getSession();
        User user = (User) session.getAttribute(WebContants.USER_KEY);

        //Same as loginCheck.jsp logic.
        if (user == null) {
            String url = req.getRequestURI();
            String query = req.getQueryString();
            if (query != null) url += "?" + query;
            url = URLEncoder.encode(url, "UTF-8");
            forward.setRedirect(true);
            forward.setView("/users/login.do?url=" + url);

            return forward;
        }

        forward.setView("/users/editAccount.jsp");

        return forward;
    }

}

The EditAccountAction action class acts on the /users/editAccount.do POST request to modify the user's information.

EditAccountAction.java
package net.java_school.user.action;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import net.java_school.action.Action;
import net.java_school.action.ActionForward;
import net.java_school.commons.WebContants;
import net.java_school.exception.AuthenticationException;
import net.java_school.user.User;
import net.java_school.user.UserService;

public class EditAccountAction implements Action {

    @Override
    public ActionForward execute(HttpServletRequest req,
            HttpServletResponse resp) throws IOException {
            
        ActionForward forward = new ActionForward();
        
        HttpSession session = req.getSession();
        User user = (User) session.getAttribute(WebContants.USER_KEY);

        String name = req.getParameter("name");
        String mobile = req.getParameter("mobile");
        String passwd = req.getParameter("passwd");
        
        if (user == null) {
            throw new AuthenticationException(WebContants.NOT_LOGIN);
        }
        
        String email = user.getEmail();
        
        UserService service = new UserService();
        
        //user.setEmail(email);
        user.setPasswd(passwd);
        user.setName(name);
        user.setMobile(mobile);
        
        int check = service.editAccount(user);
        
        if (check > 0) {
            session.setAttribute(WebContants.USER_KEY, user);
            forward.setView("changePasswd.do");
            forward.setRedirect(true);
        } else {
            throw new AuthenticationException(WebContants.AUTHENTICATION_FAILED);
        }
        
        return forward;
    }

}

The ChangePasswdFormAction action class works on the /users/changePasswd.do request.

ChangePasswdFormAction.java
package net.java_school.user.action;

import java.io.IOException;
import java.net.URLEncoder;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import net.java_school.action.Action;
import net.java_school.action.ActionForward;
import net.java_school.commons.WebContants;
import net.java_school.user.User;

public class ChangePasswdFormAction implements Action {
    
    @Override
    public ActionForward execute(HttpServletRequest req, 
        HttpServletResponse resp) throws IOException {
        
        ActionForward forward = new ActionForward();
        
        HttpSession session = req.getSession();
        User user = (User) session.getAttribute(WebContants.USER_KEY);
        
        if (user == null) {
            String url = req.getRequestURI();
            String query = req.getQueryString();
            if (query != null) url += "?" + query;
            url = URLEncoder.encode(url, "UTF-8");
            forward.setView("/users/login.do?url=" + url);
            forward.setRedirect(true);
            
            return forward;
        }

        forward.setView("/users/changePasswd.jsp");
        
        return forward;
    }
}

The ChangePasswdAction action class works on the /users/changePasswd.do POST request.

ChangePasswdAction.java
package net.java_school.user.action;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import net.java_school.action.Action;
import net.java_school.action.ActionForward;
import net.java_school.commons.WebContants;
import net.java_school.exception.AuthenticationException;
import net.java_school.user.User;
import net.java_school.user.UserService;

public class ChangePasswdAction implements Action {
    
    @Override
    public ActionForward execute(HttpServletRequest req,
    		HttpServletResponse resp) throws IOException {
       
        ActionForward forward = new ActionForward();
        
        HttpSession session = req.getSession();
        User user = (User) session.getAttribute(WebContants.USER_KEY);
        
        if (user == null) {
            throw new AuthenticationException(WebContants.NOT_LOGIN);
        }

        String currentPasswd = req.getParameter("currentPasswd");
        String newPasswd = req.getParameter("newPasswd");
        String email = user.getEmail();

        UserService service = new UserService();
        int check = service.changePasswd(currentPasswd, newPasswd, email);
                
        if (check < 1) {
            throw new AuthenticationException(WebContants.AUTHENTICATION_FAILED);
        }
        
        forward.setView("changePasswd_confirm.do");
        forward.setRedirect(true);
        
        return forward;
    }
}

The ByeFormAction action class works on the /users/bye.do GET request.

ByeFormAction.java
package net.java_school.user.action;

import java.io.IOException;
import java.net.URLEncoder;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import net.java_school.action.Action;
import net.java_school.action.ActionForward;
import net.java_school.user.User;

public class ByeFormAction implements Action {

    @Override
    public ActionForward execute(HttpServletRequest req,
            HttpServletResponse resp) throws IOException {

        ActionForward forward = new ActionForward();

        HttpSession session = req.getSession();
        User user = (User) session.getAttribute(WebContants.USER_KEY);
        
        if (user == null) {
            String url = req.getRequestURI();
            String query = req.getQueryString();
            if (query != null) url += "?" + query;
            url = URLEncoder.encode(url, "UTF-8");
            forward.setView("/users/login.do?url=" + url);
            forward.setRedirect(true);
 
            return forward;
        }

        forward.setView("/users/bye.jsp");
        
        return forward;
    }

}

The ByeAction action class works on the /users/bye.do POST request.

ByeAction.java
package net.java_school.user.action;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import net.java_school.action.Action;
import net.java_school.action.ActionForward;
import net.java_school.commons.WebContants;
import net.java_school.exception.AuthenticationException;
import net.java_school.user.User;
import net.java_school.user.UserService;

public class ByeAction implements Action {

    @Override
    public ActionForward execute(HttpServletRequest req,
            HttpServletResponse resp) throws IOException {

        ActionForward forward = new ActionForward();
        
        HttpSession session = req.getSession();
        User user = (User) session.getAttribute(WebContants.USER_KEY);

        if (user == null) {
            throw new AuthenticationException(WebContants.NOT_LOGIN); 
        }

        String email = req.getParameter("email");
        String passwd = req.getParameter("passwd");

        UserService service = new UserService();

        service.bye(email, passwd);
        session.removeAttribute(WebContants.USER_KEY);

        forward.setView("/users/bye_confirm.jsp");
        
        return forward;
    }

}

The ListAction action class works on the /bbs/list.do GET request.

ListAction.java
package net.java_school.board.action;

import java.io.IOException;
import java.net.URLEncoder;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import net.java_school.action.Action;
import net.java_school.action.ActionForward;
import net.java_school.board.Article;
import net.java_school.board.BoardService;
import net.java_school.commons.WebContants;
import net.java_school.user.User;

public class ListAction implements Action {
    public NumbersForPaging getNumbersForPaging(int totalRecord, int page, int numPerPage, int pagePerBlock) {
        int totalPage = totalRecord / numPerPage;
        if (totalRecord % numPerPage != 0) totalPage++;
        int totalBlock = totalPage / pagePerBlock;
        if (totalPage % pagePerBlock != 0) totalBlock++;
        int block = page / pagePerBlock;
        if (page % pagePerBlock != 0) block++;
        int firstPage = (block - 1) * pagePerBlock + 1;
        int lastPage = block * pagePerBlock;
        int prevPage = 0;
        if (block > 1) {
            prevPage = firstPage - 1;
        }
        int nextPage = 0;
        if (block < totalBlock) {
            nextPage = lastPage + 1;
        }
        if (block >= totalBlock) {
            lastPage = totalPage;
        }
        int listItemNo = totalRecord - (page - 1) * numPerPage;
        
        NumbersForPaging numbers = new NumbersForPaging();
        
        numbers.setTotalPage(totalPage);
        numbers.setFirstPage(firstPage);
        numbers.setLastPage(lastPage);
        numbers.setPrevBlock(prevPage);
        numbers.setNextBlock(nextPage);
        numbers.setListItemNo(listItemNo);
        
        return numbers;
    }    
    @Override
    public ActionForward execute(HttpServletRequest req, HttpServletResponse resp) throws IOException {

        ActionForward forward = new ActionForward();
        
        HttpSession session = req.getSession();
        User user = (User) session.getAttribute(WebContants.USER_KEY);
        
        if (user == null) {
            String url = req.getRequestURI();
            String query = req.getQueryString();
            if (query != null) url += "?" + query;
            url = URLEncoder.encode(url, "UTF-8");
            forward.setView("/users/login.do?url=" + url);
            forward.setRedirect(true);
            
            return forward;
        }
        
        String boardCd = req.getParameter("boardCd");
        int page = Integer.parseInt(req.getParameter("page"));
        String searchWord = req.getParameter("searchWord");
        
        BoardService service = new BoardService();
           
        int numPerPage = 10;
        int pagePerBlock = 10;
                 
        int totalRecord = service.getTotalRecord(boardCd, searchWord);
        
        int startRecord = (page - 1) * numPerPage + 1;
        int endRecord = page * numPerPage;
        
        List<Article> list = service.getArticleList(boardCd, searchWord, startRecord, endRecord);
        
        NumbersForPaging numbers = this.getNumbersForPaging(totalRecord, page, numPerPage, pagePerBlock);
        
        String boardNm = service.getBoardNm(boardCd);
        
        req.setAttribute("list", list);
        req.setAttribute("listItemNo", numbers.getListItemNo());
        req.setAttribute("prevPage", numbers.getPrevPage());
        req.setAttribute("firstPage", numbers.getFirstPage());
        req.setAttribute("lastPage", numbers.getLastPage());
        req.setAttribute("nextPage", numbers.getNextPage());
        req.setAttribute("boardNm", boardNm);
        
        forward.setView("/bbs/list.jsp");
        
        return forward;
        
    }
}

The ViewAction action class works on the /bbs/view.do GET request.

ViewAction.java
package net.java_school.board.action;

import java.io.IOException;
import java.net.URLEncoder;
import java.util.List;
import java.util.Date;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import net.java_school.action.Action;
import net.java_school.action.ActionForward;
import net.java_school.board.Article;
import net.java_school.board.AttachFile;
import net.java_school.board.BoardService;
import net.java_school.board.Comment;
import net.java_school.commons.NumbersForPaging;
import net.java_school.commons.WebContants;
import net.java_school.user.User;

public class ViewAction implements Action {
    public NumbersForPaging getNumbersForPaging(int totalRecord, int page, int numPerPage, int pagePerBlock) {
        int totalPage = totalRecord / numPerPage;
        if (totalRecord % numPerPage != 0) totalPage++;
        int totalBlock = totalPage / pagePerBlock;
        if (totalPage % pagePerBlock != 0) totalBlock++;
        int block = page / pagePerBlock;
        if (page % pagePerBlock != 0) block++;
        int firstPage = (block - 1) * pagePerBlock + 1;
        int lastPage = block * pagePerBlock;
        int prevPage = 0;
        if (block > 1) {
            prevPage = firstPage - 1;
        }
        int nextPage = 0;
        if (block < totalBlock) {
            nextPage = lastPage + 1;
        }
        if (block >= totalBlock) {
            lastPage = totalPage;
        }
        int listItemNo = totalRecord - (page - 1) * numPerPage;
        
        NumbersForPaging numbers = new NumbersForPaging();
        
        numbers.setTotalPage(totalPage);
        numbers.setFirstPage(firstPage);
        numbers.setLastPage(lastPage);
        numbers.setPrevBlock(prevPage);
        numbers.setNextBlock(nextPage);
        numbers.setListItemNo(listItemNo);
        
        return numbers;
    }    

    @Override
    public ActionForward execute(HttpServletRequest req, 
        HttpServletResponse resp) throws IOException {

        ActionForward forward = new ActionForward();
        
        HttpSession session = req.getSession();
        User user = (User) session.getAttribute(WebContants.USER_KEY);
        
        if (user == null) {
            String url = req.getRequestURI();
            String query = req.getQueryString();
            if (query != null) url += "?" + query;
            url = URLEncoder.encode(url, "UTF-8");
            forward.setView("/users/login.do?url=" + url);
            forward.setRedirect(true);
                        
            return forward;
        }

        int articleNo = Integer.parseInt(req.getParameter("articleNo"));
        String boardCd = req.getParameter("boardCd");
        int page = Integer.parseInt(req.getParameter("page"));
        String searchWord = req.getParameter("searchWord");

        BoardService service = new BoardService();
        
        service.increaseHit(articleNo);

        int numPerPage = 10;
        int pagePerBlock = 10;
        
        int startRecord = (page - 1) * numPerPage + 1;
        int endRecord = page * numPerPage;        
        
        Article article = service.getArticle(articleNo);
        List<AttachFile> attachFileList = service.getAttachFileList(articleNo);
        Article nextArticle = service.getNextArticle(articleNo, boardCd, searchWord);
        Article prevArticle = service.getPrevArticle(articleNo, boardCd, searchWord);
        List<Article> list = service.getArticleList(boardCd, searchWord, startRecord, endRecord);
        List<Comment> commentList = service.getCommentList(articleNo);
        String boardNm = service.getBoardNm(boardCd);

        String title = article.getTitle();
        String content = article.getContent();
        content = content.replaceAll(WebContants.LINE_SEPARATOR, "<br />");
        int hit = article.getHit();
        String name = article.getName();
        String email = article.getEmail();
        Date regdate = article.getRegdate();
        String contextPath = req.getContextPath();
        String uploadPath = contextPath + "/upload/";

        int totalRecord = service.getTotalRecord(boardCd, searchWord);
        NumbersForPaging numbers = this.getNumbersForPaging(totalRecord, page, numPerPage, pagePerBlock);
        
        req.setAttribute("title", title);
        req.setAttribute("content", content);
        req.setAttribute("hit", hit);
        req.setAttribute("name", name);
        req.setAttribute("email", email);
        req.setAttribute("regdate", regdate);
        req.setAttribute("uploadPath", uploadPath);
        req.setAttribute("attachFileList", attachFileList);
        req.setAttribute("nextArticle", nextArticle);
        req.setAttribute("prevArticle", prevArticle);
        req.setAttribute("commentList", commentList);
        
        req.setAttribute("list", list);
        req.setAttribute("listItemNo", numbers.getListItemNo());
        req.setAttribute("prevPage", numbers.getPrevPage());
        req.setAttribute("firstPage", numbers.getFirstPage());
        req.setAttribute("lastPage", numbers.getLastPage());
        req.setAttribute("nextPage", numbers.getNextPage());
        req.setAttribute("boardNm", boardNm);
        
        forward.setView("/bbs/view.jsp");
        
        return forward;
    }
}

The WriteFormAction action class works on the /bbs/write.do GET request.

WriteFormAction.java
package net.java_school.board.action;

import java.io.IOException;
import java.net.URLEncoder;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import net.java_school.action.Action;
import net.java_school.action.ActionForward;
import net.java_school.board.BoardService;
import net.java_school.user.User;

public class WriteFormAction implements Action {
    
    @Override
    public ActionForward execute(HttpServletRequest req, 
        HttpServletResponse resp) throws IOException {

        ActionForward forward = new ActionForward();
        
        HttpSession session = req.getSession();
        User user = (User) session.getAttribute(WebContants.USER_KEY);
        
        if (user == null) {
            String url = req.getRequestURI();
            String query = req.getQueryString();
            if (query != null) url += "?" + query;
            url = URLEncoder.encode(url, "UTF-8");
            forward.setView("/users/login.do?url=" + url);
            forward.setRedirect(true);
            
            return forward;
        }

        String boardCd = req.getParameter("boardCd");

        BoardService service = new BoardService();
        String boardNm = service.getBoardNm(boardCd);
        
        req.setAttribute("boardNm", boardNm);
        
        forward.setView("/bbs/write.jsp");
        
        return forward;
    }
}

The WriteAction action class works on the /bbs/write.do POST request.

WriteAction.java
package net.java_school.board.action;

import java.io.File;
import java.io.IOException;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.oreilly.servlet.MultipartRequest;
import com.oreilly.servlet.multipart.DefaultFileRenamePolicy;

import net.java_school.action.Action;
import net.java_school.action.ActionForward;
import net.java_school.board.Article;
import net.java_school.board.AttachFile;
import net.java_school.board.BoardService;
import net.java_school.commons.WebContants;
import net.java_school.exception.AuthenticationException;
import net.java_school.user.User;

public class WriteAction implements Action {
    
    @Override
    public ActionForward execute(HttpServletRequest req, 
        HttpServletResponse resp) throws IOException {

        ActionForward forward = new ActionForward();
        
        HttpSession session = req.getSession();
        User user = (User) session.getAttribute(WebContants.USER_KEY);
        
        if (user == null) {
            throw new AuthenticationException(WebContants.NOT_LOGIN);
        }
        
        ServletContext servletContext = req.getServletContext();
        String dir = servletContext.getRealPath("/upload");

        MultipartRequest multi = new MultipartRequest(
                req,
                dir,
                5*1024*1024,
                "UTF-8",
                new DefaultFileRenamePolicy());

        String title = multi.getParameter("title");
        String content = multi.getParameter("content");
        String filename = multi.getFilesystemName("attachFile");
        String filetype = multi.getContentType("attachFile");

        File f = multi.getFile("attachFile");
        long filesize = 0L;
        AttachFile attachFile = null;

        if (f != null) {
            filesize = f.length();
            attachFile = new AttachFile();
            attachFile.setFilename(filename);
            attachFile.setFiletype(filetype);
            attachFile.setFilesize(filesize);
            attachFile.setEmail(user.getEmail());
        }

        String boardCd = multi.getParameter("boardCd");

        Article article = new Article();
        article.setEmail(user.getEmail());
        article.setTitle(title);
        article.setContent(content);
        article.setBoardCd(boardCd);

        BoardService service = new BoardService();
        service.addArticle(article, attachFile);
        
        forward.setView("list.do?boardCd=" + boardCd + "&page=1");
        forward.setRedirect(true);
        
        return forward;
    }
}

The ModifyFormAction action class works on the /bbs/modify.do GET request.

ModifyFormAction.java
package net.java_school.board.action;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import net.java_school.action.Action;
import net.java_school.action.ActionForward;
import net.java_school.board.Article;
import net.java_school.board.BoardService;
import net.java_school.commons.WebContants;
import net.java_school.exception.AuthenticationException;
import net.java_school.user.User;

public class ModifyFormAction implements Action {
    
    @Override
    public ActionForward execute(HttpServletRequest req, 
        HttpServletResponse resp) throws IOException {

        ActionForward forward = new ActionForward();
        
        int articleNo = Integer.parseInt(req.getParameter("articleNo"));
        String boardCd = req.getParameter("boardCd");

        HttpSession session = req.getSession();
        User user = (User) session.getAttribute(WebContants.USER_KEY);

        BoardService service = new BoardService();
        Article article = service.getArticle(articleNo);

        if (user == null || !user.getEmail().equals(article.getEmail())) {
            throw new AuthenticationException(WebContants.AUTHENTICATION_FAILED);
        }

        String title = article.getTitle();
        String content = article.getContent();
        String boardNm = service.getBoardNm(boardCd);

        req.setAttribute("title", title);
        req.setAttribute("content", content);
        req.setAttribute("boardNm", boardNm);
        
        forward.setView("/bbs/modify.jsp");
        
        return forward;
    }
}

The ModifyAction action class works on the /bbs/modify.do POST request.

ModifyAction.java
package net.java_school.board.action;

import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.oreilly.servlet.MultipartRequest;
import com.oreilly.servlet.multipart.DefaultFileRenamePolicy;

import net.java_school.action.Action;
import net.java_school.action.ActionForward;
import net.java_school.board.Article;
import net.java_school.board.AttachFile;
import net.java_school.board.BoardService;
import net.java_school.commons.WebContants;
import net.java_school.exception.AuthenticationException;
import net.java_school.user.User;

public class ModifyAction implements Action {
    
    @Override
    public ActionForward execute(HttpServletRequest req, 
        HttpServletResponse resp) throws IOException {

        ActionForward forward = new ActionForward();
        
        HttpSession session = req.getSession();
        User user = (User) session.getAttribute(WebContants.USER_KEY);

        ServletContext servletContext = req.getServletContext();
        String dir = servletContext.getRealPath("/upload");

        MultipartRequest multi = new MultipartRequest(
                req,
                dir,
                5*1024*1024,
                "UTF-8",
                new DefaultFileRenamePolicy());

        BoardService service = new BoardService();
        int articleNo = Integer.parseInt(multi.getParameter("articleNo"));

        if (!service.getArticle(articleNo).getEmail().equals(user.getEmail())) {
            throw new AuthenticationException(WebContants.AUTHENTICATION_FAILED);
        }

        String boardCd = multi.getParameter("boardCd");
        int page = Integer.parseInt(multi.getParameter("page"));
        String searchWord = multi.getParameter("searchWord");
        searchWord = java.net.URLEncoder.encode(searchWord, "UTF-8");

        String title = multi.getParameter("title");
        String content = multi.getParameter("content");
        String filename = multi.getFilesystemName("attachFile");
        String filetype = multi.getContentType("attachFile");

        File f = multi.getFile("attachFile");
        long filesize = 0L;
        AttachFile attachFile = null;

        if (f != null) {
            filesize = f.length();
            attachFile = new AttachFile();
            attachFile.setFilename(filename);
            attachFile.setFiletype(filetype);
            attachFile.setFilesize(filesize);
            attachFile.setEmail(user.getEmail());
            attachFile.setArticleNo(articleNo);
        }

        Article article = new Article();
        article.setArticleNo(articleNo);
        article.setBoardCd(boardCd);
        article.setTitle(title);
        article.setContent(content);
        article.setEmail(user.getEmail());

        service.modifyArticle(article, attachFile);

        forward.setView("view.do?articleNo="+ articleNo + "&boardCd=" + boardCd + "&page=" + page + "&searchWord=" + searchWord);
        forward.setRedirect(true);
        
        return forward;
    }
}

The DeleteAction action class works on the /bbs/del.do POST request.

DeleteAction.java
package net.java_school.board.action;

import java.io.IOException;
import java.net.URLEncoder;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import net.java_school.action.Action;
import net.java_school.action.ActionForward;
import net.java_school.board.Article;
import net.java_school.board.BoardService;
import net.java_school.commons.WebContants;
import net.java_school.exception.AuthenticationException;
import net.java_school.user.User;

public class DeleteAction implements Action {
    
    @Override
    public ActionForward execute(HttpServletRequest req, 
        HttpServletResponse resp) throws IOException {

        ActionForward forward = new ActionForward();
        
        HttpSession session = req.getSession();
        User user = (User) session.getAttribute(WebContants.USER_KEY);

        int articleNo = Integer.parseInt(req.getParameter("articleNo"));

        BoardService service = new BoardService();
        Article article = service.getArticle(articleNo);
        
        if (user == null || !user.getEmail().equals(article.getEmail())) {
            throw new AuthenticationException(WebContants.AUTHENTICATION_FAILED);
        }

        service.removeArticle(articleNo);

        String boardCd = req.getParameter("boardCd");
        String page = req.getParameter("page");
        String searchWord = req.getParameter("searchWord");

        searchWord = URLEncoder.encode(searchWord, "UTF-8");
        
        forward.setView("list.do?boardCd=" + boardCd + "&page=" + page + "&searchWord=" + searchWord);
        forward.setRedirect(true);
        
        return forward;
    }
}

The AddCommentAction action class works on the /bbs/addComment.do POST request.

AddCommentAction.java
package net.java_school.board.action;

import java.io.IOException;
import java.net.URLEncoder;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import net.java_school.action.Action;
import net.java_school.action.ActionForward;
import net.java_school.board.BoardService;
import net.java_school.board.Comment;
import net.java_school.commons.WebContants;
import net.java_school.exception.AuthenticationException;
import net.java_school.user.User;

public class AddCommentAction implements Action {
    
    @Override
    public ActionForward execute(HttpServletRequest req, 
        HttpServletResponse resp) throws IOException {

        ActionForward forward = new ActionForward();
        
        HttpSession session = req.getSession();
        User user = (User) session.getAttribute(WebContants.USER_KEY);
        
        if (user == null) {
            throw new AuthenticationException(WebContants.NOT_LOGIN);
        }

        int articleNo = Integer.parseInt(req.getParameter("articleNo"));
        String boardCd = req.getParameter("boardCd");
        int page = Integer.parseInt(req.getParameter("page"));
        String searchWord = req.getParameter("searchWord");
        String memo = req.getParameter("memo");

        Comment comment = new Comment();
        comment.setArticleNo(articleNo);
        comment.setEmail(user.getEmail());
        comment.setMemo(memo);

        BoardService service = new BoardService();
        service.addComment(comment);

        searchWord = URLEncoder.encode(searchWord, "UTF-8");
        forward.setView("view.do?articleNo=" + articleNo + "&boardCd=" + boardCd + "&page=" + page + "&searchWord=" + searchWord);
        forward.setRedirect(true);
        
        return forward;
    }
}

The UpdateCommentAction action class works on the /bbs/updateComment.do POST request.

UpdateCommentAction.java
package net.java_school.board.action;

import java.io.IOException;
import java.net.URLEncoder;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import net.java_school.action.Action;
import net.java_school.action.ActionForward;
import net.java_school.board.BoardService;
import net.java_school.board.Comment;
import net.java_school.commons.WebContants;
import net.java_school.exception.AuthenticationException;
import net.java_school.user.User;

public class UpdateCommentAction implements Action {

    @Override
    public ActionForward execute(HttpServletRequest req,
            HttpServletResponse resp) throws IOException {

        ActionForward forward = new ActionForward();
        
        HttpSession session = req.getSession();
        User user = (User) session.getAttribute(WebContants.USER_KEY);

        int commentNo = Integer.parseInt(req.getParameter("commentNo"));

        BoardService service = new BoardService();
        Comment comment = service.getComment(commentNo);
        
        if (user == null || !user.getEmail().equals(comment.getEmail())) {
            throw new AuthenticationException(WebContants.AUTHENTICATION_FAILED);
        }

        int articleNo = Integer.parseInt(req.getParameter("articleNo"));
        String boardCd = req.getParameter("boardCd");
        int page = Integer.parseInt(req.getParameter("page"));
        String searchWord = req.getParameter("searchWord");

        String memo = req.getParameter("memo");

        comment.setCommentNo(commentNo);
        comment.setArticleNo(articleNo);
        comment.setEmail(user.getEmail());
        comment.setMemo(memo);

        service.modifyComment(comment);

        searchWord = URLEncoder.encode(searchWord, "UTF-8");
        
        forward.setView("view.do?articleNo="+ articleNo + "&boardCd=" + boardCd + "&page=" + page + "&searchWord=" + searchWord);
        forward.setRedirect(true);
        
        return forward;
    }

}

The DeleteCommentAction action class works on the /bbs/deleteComment.do POST request.

DeleteCommentAction.java
package net.java_school.board.action;

import java.io.IOException;
import java.net.URLEncoder;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import net.java_school.action.Action;
import net.java_school.action.ActionForward;
import net.java_school.board.BoardService;
import net.java_school.board.Comment;
import net.java_school.commons.WebContants;
import net.java_school.exception.AuthenticationException;
import net.java_school.user.User;

public class DeleteCommentAction implements Action {
    
    @Override
    public ActionForward execute(HttpServletRequest req, 
        HttpServletResponse resp) throws IOException {

        ActionForward forward = new ActionForward();
                
        HttpSession session = req.getSession();
        User user = (User) session.getAttribute(WebContants.USER_KEY);

        int commentNo = Integer.parseInt(req.getParameter("commentNo"));

        BoardService service = new BoardService();
        Comment comment = service.getComment(commentNo);
        if (user == null || !user.getEmail().equals(comment.getEmail())) {
            throw new AuthenticationException(WebContants.AUTHENTICATION_FAILED);
        }

        int articleNo = Integer.parseInt(req.getParameter("articleNo"));
        String boardCd = req.getParameter("boardCd");
        int page = Integer.parseInt(req.getParameter("page"));
        String searchWord = req.getParameter("searchWord");

        service.removeComment(commentNo);

        searchWord = URLEncoder.encode(searchWord, "UTF-8");
        forward.setView("view.do?articleNo=" + articleNo + "&boardCd=" + boardCd + "&page=" + page + "&searchWord=" + searchWord);
        forward.setRedirect(true);
        
        return forward;
    }
}

The DeleteAttachFileAction action class works on the /bbs/deleteAttachFile.do POST request.

DeleteAttachFileAction.java
package net.java_school.board.action;

import java.io.IOException;
import java.net.URLEncoder;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import net.java_school.action.Action;
import net.java_school.action.ActionForward;
import net.java_school.board.AttachFile;
import net.java_school.board.BoardService;
import net.java_school.commons.WebContants;
import net.java_school.exception.AuthenticationException;
import net.java_school.user.User;

public class DeleteAttachFileAction implements Action {

    @Override
    public ActionForward execute(HttpServletRequest req,
            HttpServletResponse resp) throws IOException {

        ActionForward forward = new ActionForward();
        
        HttpSession session = req.getSession();
        User user = (User) session.getAttribute(WebContants.USER_KEY);

        int attachFileNo = Integer.parseInt(req.getParameter("attachFileNo"));

        BoardService service = new BoardService();
        AttachFile attachFile = service.getAttachFile(attachFileNo);
        
        if (user == null || !user.getEmail().equals(attachFile.getEmail())) {
            throw new AuthenticationException(WebContants.AUTHENTICATION_FAILED);
        }

        int articleNo = Integer.parseInt(req.getParameter("articleNo"));
        String boardCd = req.getParameter("boardCd");
        int page = Integer.parseInt(req.getParameter("page"));
        String searchWord = req.getParameter("searchWord");

        service.removeAttachFile(attachFileNo);

        searchWord = URLEncoder.encode(searchWord, "UTF-8");
        
        forward.setView("view.do?articleNo=" + articleNo + "&boardCd=" + boardCd + "&page=" + page + "&searchWord=" + searchWord);
        forward.setRedirect(true);
        
        return forward;
    }

}

Model 2 Features

  • Model 2 consists of model, view and controller.
  • All requests are forwarded to the controller.
  • The controller delegates tasks to the model.
  • The model performs the business logic and passes the results to the view.

The view is responsible for the JSP in the project.
A model is an action class in a project and is responsible for business logic.
Business logic is the logic that processes the data needed for the business.
You can think of the business logic as the logic that produces the data to be seen in the view.
The business logic must be detached from the view and implemented in the model.
If your view has business logic, it's not good code.

Model 2 Board Final Source: https://github.com/kimjonghoon/model2