아직 JSP와 서블릿에 익숙하지 않고, 구조를 잘 몰라서 해맸다. 시작부터 /webapp/WEB-INF/guestbook/guestbooks.jsp를 실행하려했는데 404에러가 났다. 다른 프로젝트들을 살펴보니 webapp이 아니아닌 WebContent여서 엉뚱한 곳에 문제가 있는건 아닐지 고민하기도 했다.
전체적인 흐름은 제일 처음 사용자가 localhost:8080/guestbooks를 입력하면 (만약 기존에 연습하던 프로젝트에 부르면 localhost:8080/guestbook/guestbooks 에서 실행될 것이다) GuestbookListServlet이 실행된다. 거기서 jsp파일을 부르는 방식이다.
<%@ page contentType="text/html; charset=utf-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<html>
<head>
<title>방명록</title>
<style>
.guestbook {
padding: 5px 0px 5px 5px;
margin-bottom: 5px;
border-bottom: 1px solid #efefef;
font-size: 12px;
}
</style>
</head>
<body>
<div class="guestbooks"></div>
<c:forEach var="guestbook" items="${list}">
<div class="guestbook">
<div> <label>id : </label> ${guestbook.id}</div>
<div> <label>name : </label> ${guestbook.name}</div>
<div> <p>${guestbook.content}</p></div>
<div> <label>regdate : </label> ${guestbook.regdate}</div>
</div>
</c:forEach>
</div>
<br><br><br>
<form method="post" action="guestbooks/write">
이름 : <input type="text" name="name"><br>
내용 :
<textarea name="content" cols="50" rows="5"></textarea><br>
<input type="submit" value="확인">
</form>
</body>
</html>
jstl을 이용해서 list에 있는 아이템을 반복문을 통해 쭉 출력하고 있음을 알 수 있다. 또한 post를 사용해서 이름과 내용을 'guestbooks/write'에 보내고 있다.
CREATE TABLE `guestbook` (
`id` INT(11) NOT NULL AUTO_INCREMENT COMMENT 'guestbook id',
`content` TEXT NOT NULL COMMENT 'guestbook content',
`regdate` DATETIME NULL DEFAULT NULL COMMENT '등록일',
PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;
주어진 sql 코드를 이용해서 테이블을 생성한다. 하지만 문제의 오류인지, 의도인지는 모르겠지만 name 컬럼이 빠져있다. 그래서 추가해줘야한다.
ALTER TABLE guestbook ADD COLUMN name varchar(20) NOT NULL;
데이터베이스에서 Guestbook list를 가져오고 그것을 request에 setAttribute로 저장한다. 여기서 RequestDispatcher를 이용해서 지정한 경로에 있는 guestbooks.jsp 파일로 보낸다.
forward() 메소드 : 클라이언트에서 수행 요청을 받는 Servlet에서 다른 Servlet, JSP 또는 HTML파일등으로 수행 권한을 넘겨서 다른 자원의 수행 결과가 대신 클라이언트로 응답하는 기능 지원
package org.edwith.webbe.guestbook.servlet;
import org.edwith.webbe.guestbook.dao.GuestbookDao;
import org.edwith.webbe.guestbook.dto.Guestbook;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/guestbooks")
public class GuestbookListServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 코드를 작성하세요.
response.setContentType("text/html; charset = UTF-8;");
GuestbookDao guestBookDao = new GuestbookDao();
List<Guestbook> list = guestBookDao.getGuestbooks();
request.setAttribute("list", list);
RequestDispatcher requestDispatcher = getServletContext().getRequestDispatcher("/WEB-INF/guestbook/guestbooks.jsp");
requestDispatcher.forward(request, response);
}
}
package org.edwith.webbe.guestbook.dao;
import org.edwith.webbe.guestbook.dto.Guestbook;
import org.edwith.webbe.guestbook.util.DBUtil;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class GuestbookDao {
private static String dburl = "jdbc:mysql://localhost:3306/connectdb?useUnicode=true&characterEncoding=utf8&useSSL=false";
private static String dbUser = "connectuser";
private static String dbPasswd = "connect123!@#";
public List<Guestbook> getGuestbooks(){
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
List<Guestbook> list = new ArrayList<>();
String sql = "SELECT * FROM guestbook ORDER BY regdate";
try (Connection conn = DBUtil.getConnection(dburl, dbUser, dbPasswd);
PreparedStatement ps = conn.prepareStatement(sql)) {
try (ResultSet rs = ps.executeQuery()) {
while (rs.next()) {
Long id = rs.getLong("id");
String content = rs.getString("content");
Date date = rs.getDate("regdate");
String name = rs.getString("name");
Guestbook guestBook = new Guestbook(id, name, content, date);
list.add(guestBook);
}
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception ex) {
ex.printStackTrace();
}
return list;
}
public void addGuestbook(Guestbook guestbook){
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
String sql = "INSERT INTO guestbook (id, content, regdate, name) VALUES (id, ?, now(), ?)";
try (Connection conn = DriverManager.getConnection(dburl, dbUser, dbPasswd);
PreparedStatement ps = conn.prepareStatement(sql)) {
ps.setString(1, guestbook.getContent());
ps.setString(2, guestbook.getName());
ps.executeUpdate();
ps.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
JDBC 실습과 크게 다른 내용은 없다.
guestbooks.jsp에서 post 방식으로 넘어온 이름과 내용을 데이터베이스에 등록해야한다.
package org.edwith.webbe.guestbook.servlet;
import org.edwith.webbe.guestbook.dao.GuestbookDao;
import org.edwith.webbe.guestbook.dto.Guestbook;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet("/guestbooks/write")
public class GuestbookWriteServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String name = request.getParameter("name");
String content = request.getParameter("content");
Guestbook guestbook = new Guestbook(name, content);
GuestbookDao guestbookDao = new GuestbookDao();
guestbookDao.addGuestbook(guestbook);
response.sendRedirect("http://localhost:8080/guestbook/guestbooks");
}
}
getParameter를 이용해서 넘어온 데이터들을 받고, dao를 이용해서 데이터베이스에 등록한다. 그리고 다시 '/guestbooks'로 redirect 한다.
MySQL 한글 깨짐 문제.
해결 방법
여러 블로그들이 시키는대로하고, 서비스를 껐다가 켜보고, status를 mysql에서 쳤을 때, 인코딩 문제가 없어보이지만 계속 깨진다. 다음에 시간이 나면 해결하려한다.