넓고얕은지식사전

JSP & Servlet 게시판 구현하기(게시글 쓰기) 본문

IT/JSP & Servlet

JSP & Servlet 게시판 구현하기(게시글 쓰기)

맛난이 2023. 1. 14. 22:04
반응형

 

지난번에 암호변경 기능을 구현 하였다.

https://nullgoyatten.tistory.com/21

 

JSP & Servlet 게시판 구현하기(암호 변경)

지난번에 로그아웃 기능을 구현 하였다. https://nullgoyatten.tistory.com/20 JSP & Servlet 게시판 구현하기(로그아웃) 지난번에 로그인 기능을 구현 하였다. https://nullgoyatten.tistory.com/19 그렇다면 이번에는

nullgoyatten.tistory.com

 

이제 본격적으로 게시글을 작성하는 기능을 구현해 보도록 하자.

 

1.패키지 생성 (패키지명 : article.model)

 

2. Writer작성(작성자의 정보(아이디 및 이름)를 담는다.)

경로 : article.model > Writer.java

package article.model;

public class Writer {

	private String id;
	private String name;

	public Writer(String id, String name) {
		this.id = id;
		this.name = name;
	}

	public String getId() {
		return id;
	}

	public String getName() {
		return name;
	}

}

 

3. Article 작성 (게시글의 정보를 담는다.)

경로 : article.model > Article.java

package article.model;

import java.util.Date;

public class Article {

	private Integer number;
	private Writer writer;
	private String title;
	private Date regDate;
	private Date modifiedDate;
	private int readCount;

	public Article(Integer number, Writer writer, String title, 
			Date regDate, Date modifiedDate, int readCount) {
		this.number = number;
		this.writer = writer;
		this.title = title;
		this.regDate = regDate;
		this.modifiedDate = modifiedDate;
		this.readCount = readCount;
	}

	public Integer getNumber() {
		return number;
	}

	public Writer getWriter() {
		return writer;
	}

	public String getTitle() {
		return title;
	}

	public Date getRegDate() {
		return regDate;
	}

	public Date getModifiedDate() {
		return modifiedDate;
	}

	public int getReadCount() {
		return readCount;
	}

}

4. ArticleContent 작성 (게시글의 내용을 담는다.)

경로 : article.model > ArticleContent.java

package article.model;

public class ArticleContent {

	private Integer number;
	private String content;

	public ArticleContent(Integer number, String content) {
		this.number = number;
		this.content = content;
	}

	public Integer getNumber() {
		return number;
	}

	public String getContent() {
		return content;
	}

}

 

5. 패키지 생성 (패키지명 : article.dao)

 

6. ArticleDao 작성 (article 테이블에 데이터를 삽입하는 기능 제공)

경로 : article.dao> ArticleDao.java

package article.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.util.Date;

import article.model.Article;
import jdbc.JdbcUtil;

public class ArticleDao {

	public Article insert(Connection conn, Article article) throws SQLException {
		PreparedStatement pstmt = null;
		Statement stmt = null;
		ResultSet rs = null;
		try {
			pstmt = conn.prepareStatement("insert into article "
					+ "(writer_id, writer_name, title, regdate, moddate, read_cnt) "
					+ "values (?,?,?,?,?,0)");
			pstmt.setString(1, article.getWriter().getId());
			pstmt.setString(2, article.getWriter().getName());
			pstmt.setString(3, article.getTitle());
			pstmt.setTimestamp(4, toTimestamp(article.getRegDate()));
			pstmt.setTimestamp(5, toTimestamp(article.getModifiedDate()));
			int insertedCount = pstmt.executeUpdate();

			if (insertedCount > 0) {
				stmt = conn.createStatement();
				rs = stmt.executeQuery("select last_insert_id() from article");
				if (rs.next()) {
					Integer newNo = rs.getInt(1);
					return new Article(newNo,
							article.getWriter(),
							article.getTitle(),
							article.getRegDate(),
							article.getModifiedDate(),
							0);
				}
			}
			return null;
		} finally {
			JdbcUtil.close(rs);
			JdbcUtil.close(stmt);
			JdbcUtil.close(pstmt);
		}
	}

	private Timestamp toTimestamp(Date date) {
		return new Timestamp(date.getTime());
	}
}

 

 

7. ArticleContentDao 작성 (article_content 테이블에 데이터를 삽입하는 기능 제공)

경로 : article.dao> ArticleContentDao.java

 

package article.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

import article.model.ArticleContent;
import jdbc.JdbcUtil;

public class ArticleContentDao {

	public ArticleContent insert(Connection conn, ArticleContent content) 
	throws SQLException {
		PreparedStatement pstmt = null;
		try {
			pstmt = conn.prepareStatement(
					"insert into article_content " + 
					"(article_no, content) values (?,?)");
			pstmt.setLong(1, content.getNumber());
			pstmt.setString(2, content.getContent());
			int insertedCount = pstmt.executeUpdate();
			if (insertedCount > 0) {
				return content;
			} else {
				return null;
			}
		} finally {
			JdbcUtil.close(pstmt);
		}
	}
}

 

8. 패키지 생성 (패키지명 : article.service)

 

 

9. WriteRequest작성 (게시글 쓰기에 필요한 데이터 제공)

경로 : article.service > WriteRequest.java

package article.service;

import java.util.Map;

import article.model.Writer;

public class WriteRequest {

	private Writer writer;
	private String title;
	private String content;

	public WriteRequest(Writer writer, String title, String content) {
		this.writer = writer;
		this.title = title;
		this.content = content;
	}

	public Writer getWriter() {
		return writer;
	}

	public String getTitle() {
		return title;
	}

	public String getContent() {
		return content;
	}

	public void validate(Map<String, Boolean> errors) {
		if (title == null || title.trim().isEmpty()) {
			errors.put("title", Boolean.TRUE);
		}
	}
}

 

 

10. WriteArticleService 작성 (게시글 쓰기 기능 제공)

경로 : article.service > WriteArticleService.java

package article.service;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.Date;

import article.dao.ArticleContentDao;
import article.dao.ArticleDao;
import article.model.Article;
import article.model.ArticleContent;
import jdbc.JdbcUtil;
import jdbc.connection.ConnectionProvider;

public class WriteArticleService {

	private ArticleDao articleDao = new ArticleDao();
	private ArticleContentDao contentDao = new ArticleContentDao();

	public Integer write(WriteRequest req) {
		Connection conn = null;
		try {
			conn = ConnectionProvider.getConnection();
			conn.setAutoCommit(false);

			Article article = toArticle(req);
			Article savedArticle = articleDao.insert(conn, article);
			if (savedArticle == null) {
				throw new RuntimeException("fail to insert article");
			}
			ArticleContent content = new ArticleContent(
					savedArticle.getNumber(),
					req.getContent());
			ArticleContent savedContent = contentDao.insert(conn, content);
			if (savedContent == null) {
				throw new RuntimeException("fail to insert article_content");
			}

			conn.commit();

			return savedArticle.getNumber();
		} catch (SQLException e) {
			JdbcUtil.rollback(conn);
			throw new RuntimeException(e);
		} catch (RuntimeException e) {
			JdbcUtil.rollback(conn);
			throw e;
		} finally {
			JdbcUtil.close(conn);
		}
	}

	private Article toArticle(WriteRequest req) {
		Date now = new Date();
		return new Article(null, req.getWriter(), req.getTitle(), now, now, 0);
	}
}

11. 패키지 생성 (패키지명 : article.command)

 

12. WriteArticleHandler 작성 (게시글 쓰기 기능 제공)

경로 : article.command> WriteArticleHandler.java

package article.command;

import java.util.HashMap;
import java.util.Map;

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

import article.model.Writer;
import article.service.WriteArticleService;
import article.service.WriteRequest;
import auth.service.User;
import mvc.command.CommandHandler;

public class WriteArticleHandler implements CommandHandler {
	private static final String FORM_VIEW = "/WEB-INF/view/newArticleForm.jsp";
	private WriteArticleService writeService = new WriteArticleService();
	
	@Override
	public String process(HttpServletRequest req, HttpServletResponse res) {
		if (req.getMethod().equalsIgnoreCase("GET")) {
			return processForm(req, res);
		} else if (req.getMethod().equalsIgnoreCase("POST")) {
			return processSubmit(req, res);
		} else {
			res.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
			return null;
		}
	}

	private String processForm(HttpServletRequest req, HttpServletResponse res) {
		return FORM_VIEW;
	}
	
	private String processSubmit(HttpServletRequest req, HttpServletResponse res) {
		Map<String, Boolean> errors = new HashMap<>();
		req.setAttribute("errors", errors);

		User user = (User)req.getSession(false).getAttribute("authUser");
		WriteRequest writeReq = createWriteRequest(user, req);
		writeReq.validate(errors);
		
		if (!errors.isEmpty()) {
			return FORM_VIEW;
		}
		
		int newArticleNo = writeService.write(writeReq);
		req.setAttribute("newArticleNo", newArticleNo);
		
		return "/WEB-INF/view/newArticleSuccess.jsp";
	}

	private WriteRequest createWriteRequest(User user, HttpServletRequest req) {
		return new WriteRequest(
				new Writer(user.getId(), user.getName()),
				req.getParameter("title"),
				req.getParameter("content"));
	}
}

 

13. commandHandlerURI.properties 수정. WriteArticleHandler가 /article/write.do 요청을 처리하도록 매핑 설정에 추가한다. 

/join.do=member.command.JoinHandler
/login.do=auth.command.LoginHandler
/logout.do=auth.command.LogoutHandler
/changePwd.do=member.command.ChangePasswordHandler
/article/write.do=article.command.WriteArticleHandler

 

14. newArticleForm.jsp 작성

경로 :  WebContent > WEB-INF > view > newArticleForm.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>게시글 쓰기</title>
</head>
<body>
<form action="write.do" method="post">
<p>
	제목:<br/><input type="text" name="title" value="${param.title}">
	<c:if test="${errors.title}">제목을 입력하세요.</c:if>
</p>
<p>
	내용:<br/>
	<textarea name="content" rows="5" cols="30">${param.title}</textarea>
</p>
<input type="submit" value="새 글 등록">
</form>
</body>
</html>

 

15. newArticleSuccess.jsp 작성

경로 :  WebContent > WEB-INF > view > newArticleSuccess.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>게시글 등록</title>
</head>
<body>

게시글을 등록했습니다.
<br>
${ctxPath = pageContext.request.contextPath ; ''}
<a href="${ctxPath}/article/list.do">[게시글목록보기]</a>
<a href="${ctxPath}/article/read.do?no=${newArticleNo}">[게시글내용보기]</a>
</body>
</html>

 

16. web.xml 수정

web.xml(경로 : WebContent > WEB-INF)에 LoginCheckFilter 설정(write.do)을 추가해줘야 한다.

<!-- LoginCheckFilter관련 설정 -->
	<filter>
		<filter-name>LoginCheckFilter</filter-name>
		<filter-class>filter.LoginCheckFilter</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>LoginCheckFilter</filter-name>
		<url-pattern>/changePwd.do</url-pattern>
		<url-pattern>/article/write.do</url-pattern>
	</filter-mapping>
<!-- LoginCheckFilter관련 설정 -->

 

17. 테스트

로그인이 안되었으면 로그인으로 넘어간다.

아직 게시글 목록과 내용 보기 기능은 구현되지 않았으므로 에러가 뜰것이다.

 

다음글 : 게시글 목록 조회 구현

https://nullgoyatten.tistory.com/25

 

JSP & Servlet 게시판 구현하기(게시글 목록 조회)

지난번에 게시글 쓰기 기능을 구현 하였다. https://nullgoyatten.tistory.com/22 JSP & Servlet 게시판 구현하기(게시글 쓰기) 지난번에 암호변경 기능을 구현 하였다. https://nullgoyatten.tistory.com/21 JSP & Servlet 게

nullgoyatten.tistory.com

 

반응형
Comments