Servlet 실습 : CURD 게시판 만들기
부트캠프(END)/-Web 실습2022. 7. 14. 16:17
get을 보내면 get으로 받아야 하고
post를 보내면 post로 받아야 한다!
유일하게 번호가 안 넘어가는 것 = 검색/찾기 기능
회원가입, 회원탈퇴, 장바구니 추가/제거, 글 수정/삭제 다 번호가 넘어 간다.
MyBatis가 SQL과 자바 파일을 분리할 수 있도록 해줌.
나중에 자바코드는 servlet, html은 jsp에서 하도록 분리할 것임.
우선 게시판 VO를 만들어 준다.
→ 게시글 번호, 조회수, 작성자이름, 제목, 내용, 비밀번호, 작성일
BoardVO.java (Class)
package doodoo.vo;
import java.util.*;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class BoardVO {
private int no, hit;
private String name, subject, content, pwd;
private Date regdate;
데이터베이스에 연결해서 CURD 기능을 구현하는 DAO를 생성한다.
BoardDAO.java (Class)
package doodoo.dao;
import java.sql.*;
import java.util.*;
import doodoo.vo.*;
public class BoardDAO {
private Connection conn;
private PreparedStatement ps;
private final String URL = "jdbc:oracle:thin:@localhost:1521:XE";
public BoardDAO() {
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
} catch (Exception ex) {}
}
public void getConnection() {
try {
conn = DriverManager.getConnection(URL, "user", "0000");
} catch (Exception ex) {
System.out.println("getConnection() 에러");
ex.printStackTrace();
}
}
public void disConnection() {
try {
if (ps != null) ps.close();
if (conn != null) conn.close();
} catch (Exception ex) {
System.out.println("disConnection() 에러");
ex.printStackTrace();
}
}
public List < BoardVO > boardListData(int page) {
List < BoardVO > list = new ArrayList < BoardVO > ();
try {
getConnection();
//inline view
//뒤에서부터(최신것부터) 차례로 10개씩 가져온다.
String sql = "SELECT no, subject, name, regdate, hit, num " +
"FROM (SELECT no, subject, name, regdate, hit, rownum as num " +
"FROM (SELECT /*+ INDEX_DESC(freeboard fb_no_pk)*/no,
subject, name, regdate, hit " +
"FROM freeboard)) " +
"WHERE num BETWEEN ? AND ?";
ps = conn.prepareStatement(sql);
int rowSize = 10;
int start = (page * rowSize) - (rowSize - 1);
int end = page * rowSize;
ps.setInt(1, start);
ps.setInt(2, end);
ResultSet rs = ps.executeQuery();
while (rs.next()) {
BoardVO vo = new BoardVO();
vo.setNo(rs.getInt(1));
vo.setSubject(rs.getString(2));
vo.setName(rs.getString(3));
vo.setRegdate(rs.getDate(4));
vo.setHit(rs.getInt(5));
list.add(vo);
}
rs.close();
} catch (Exception ex) {
} finally {
disConnection();
}
return list;
}
public int boardTotal() {
int total = 0;
try {
getConnection();
String sql = "SELECT CEIL(COUNT(*)/10.0) FROM freeboard";
ResultSet rs = ps.executeQuery();
rs.next();
total = rs.getInt(1);
rs.close();
} catch (Exception ex) {
System.out.println("boardTotal() 에러");
ex.printStackTrace();
} finally {
disConnection();
}
return total;
}
//상세보기
public BoardVO boardDetail(int no, int type) {
BoardVO vo = new BoardVO();
try {
getConnection();
//조회시 => 조회수 증가
if (type == 1) {
String sql = "UPDATE freeboard SET " +
"hit = hit+1 " +
"WHERE no=?";
ps = conn.prepareStatement(sql);
ps.setInt(1, no);
ps.executeUpdate();
}
//수정시 => 조회수 증가하지 않음
//실제 데이터 읽기 => UPDATE, DETAIL에서 다 씀
String sql = "SELECT no, name, subject, content, regdate, hit " +
"FROM freeboard " +
"WHERE no = ?";
ps = conn.prepareStatement(sql);
ps.setInt(1, no);
ResultSet rs = ps.executeQuery();
rs.next();
vo.setNo(rs.getInt(1));
vo.setName(rs.getString(2));
vo.setSubject(rs.getString(3));
vo.setContent(rs.getString(4));
vo.setRegdate(rs.getDate(5));
vo.setHit(rs.getInt(6));
rs.close();
} catch (Exception ex) {
System.out.println("boardDetail() 에러");
ex.printStackTrace();
} finally {
disConnection();
}
return vo;
}
//수정, 삭제
public void boardUpdate(BoardVO vo) {
try {
getConnection();
String sql = "UPDATE freeboard SET " +
"name=?, subject=?, content=? " +
"WHERE no=?";
ps = conn.prepareStatement(sql);
ps.setString(1, vo.getName());
ps.setString(2, vo.getSubject());
ps.setString(3, vo.getContent());
ps.setInt(4, vo.getNo());
ps.executeUpdate();
} catch (Exception ex) {
System.out.println("boardUpdate() 에러");
ex.printStackTrace();
} finally {
disConnection();
}
}
public void boardDelete(int no) {
try {
getConnection();
String sql = "DELETE FROM freeboard " +
"WHERE no=?";
ps = conn.prepareStatement(sql);
ps.setInt(1, no);
ps.executeUpdate();
} catch (Exception ex) {
System.out.println("boardUpdate() 에러");
ex.printStackTrace();
} finally {
disConnection();
}
}
//새글
public void boardInsert(BoardVO vo) {
try {
getConnection();
String sql = "INSERT INTO freeboard(no, name, subject, content, pwd) " +
"VALUES((SELECT NVL(MAX(no)+1,1) FROM freeboard), ?,?,?,?)";
ps = conn.prepareStatement(sql);
ps.setString(1, vo.getName());
ps.setString(2, vo.getSubject());
ps.setString(3, vo.getContent());
ps.setString(4, vo.getPwd());
ps.executeUpdate();
} catch (Exception ex) {
System.out.println("boardInsert() 에러");
ex.printStackTrace();
} finally {
disConnection();
}
}
}
}
DAO를 통해 데이터를 읽어 오고, 그 데이터를 html코드와 함께 뿌려 주는 Servlet
BoardServlet.java (Servlet)
package doodoo.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.*;
import doodoo.dao.*;
import doodoo.vo.*;
@WebServlet("/BoardServlet")
public class BoardServlet extends HttpServlet {
private static final long serialVersionUID = 1 L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1. 변환(전송방법 선택) => HTML, XML, JSON
response.setContentType("text/html; charset=UTF-8"); //HTML, 한글포함 텍스트로 보내겠습니다
//2. 각 사용자별로 서버가 뿌려주고, 브라우저에서 읽어갈 위치의 메모리를 설정
PrintWriter out = response.getWriter();
//3. 데이터 읽기
BoardDAO dao = new BoardDAO();
List < BoardVO > list = dao.boardListData(1);
//out 안에 HTML을 작성해 주면 된다
out.println("<html>");
out.println("<head>");
//style
out.println("<style type=text/css>");
out.println("div{width:100%}");
out.println("h1{margin-top:50px; text-align:center}");
out.println("table{margin:0px auto;}"); //브라우저 가운데에 출력해라
out.println("</style>");
out.println("<link rel=stylesheet href=table.css"); //외부 css파일 불러오기
out.println("</head>");
//body
out.println("<body>");
out.println("<div>");
out.println("<h1>자유게시판</h1>");
out.println("<table width=700 class=table_content>");
out.println("<tr>");
out.println("<td><a href=BoardInsert>새 글</a></td>");
out.println("</tr>");
out.println("</table>");
out.println("<table width=700 class=table_content>");
out.println("<tr>");
out.println("<th width=10%>번호</th>");
out.println("<th width=45%>제목</th>");
out.println("<th width=15%>이름</th>");
out.println("<th width=20%>작성일</th>");
out.println("<th width=10%>조회수</th>");
out.println("</tr>");
//4. 데이터 출력
for (BoardVO vo: list) {
out.println("<tr class=dataTr>");
out.println("<td width=10%>" + vo.getNo() + "</td>");
out.println("<td width=45%><a href=BoardDetail?no=" +
vo.getNo() + ">" + vo.getSubject() + "</a></td>");
//상세보기를 들어갈 때 게시물 번호를 넘겨 주어야 한다.
//? 앞에 있는 BoardDetail이 no라는 값을 받아감.
out.println("<td width=15%>" + vo.getName() + "</td>");
out.println("<td width=20%>" + vo.getRegdate().toString() + "</td>");
out.println("<td width=10%>" + vo.getHit() + "</td>");
out.println("</tr>");
}
out.println("</table>");
out.println("</div>");
out.println("</body>");
out.println("</html>");
}
}
form 태그 내에 있는 데이터를 post 방식으로 전송하여 데이터베이스에 추가하는 Servlet
BoardInsert.java (Servlet)
package doodoo.servlet;
import java.io.*;
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 doodoo.dao.BoardDAO;
import doodoo.vo.BoardVO;
@WebServlet("/BoardInsert")
public class BoardInsert extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1. 변환(전송방법 선택) => HTML, XML, JSON
response.setContentType("text/html; charset=UTF-8"); //HTML, 한글포함 텍스트로 보내겠습니다
//2. 각 사용자별로 서버가 뿌려주고, 브라우저에서 읽어갈 위치의 메모리를 설정
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head>");
//style
out.println("<style type=text/css>");
out.println("div{width:100%}");
out.println("h1{margin-top:50px; text-align:center}");
out.println("table{margin:0px auto;}");//브라우저 가운데에 출력해라
out.println("</style>");
out.println("<link rel=stylesheet href=table.css"); //외부 css파일 불러오기
out.println("</head>");
//body
out.println("<body>");
out.println("<div>");
out.println("<h1>글쓰기</h1>");
out.println("<form method=post action=BoardInsert>");
//아래 내용을 한 번에 모아서 원하는 곳으로 전송할 수 있는 form태그
out.println("<table width=700 class=table_content>");
out.println("<tr>");
out.println("<th align=right width=15%>이름</th>");
out.println("<td width=85%><input type=text name=name size=15></td>");
out.println("</tr>");
out.println("<tr>");
out.println("<th align=right width=15%>제목</th>");
out.println("<td width=85%><input type=text name=subject size=45></td>");
out.println("</tr>");
out.println("<tr>");
out.println("<th align=right width=15%>내용</th>");
out.println("<td width=85%><textarea rows=10 cols=50 name=content></textarea></td>");
out.println("</tr>");
out.println("<tr>");
out.println("<th align=right width=15%>비밀번호</th>");
out.println("<td width=85%><input type=password name=pwd size=10></td>");
out.println("</tr>");
out.println("<tr>");
out.println("<td colspan=2 align-center>");
out.println("<input type=submit value=글쓰기>");
out.println("<input type=button value=취소 onclick=\"javascript:history.back()\">");
out.println("</td>");
out.println("</tr>");
out.println("</table>");
out.println("</form>");
out.println("</div>");
out.println("</body>");
out.println("</html>");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//post방식으로 보낼 때 필요한 부분
try {
//한글이 깨질 수 있음. 변환 필요->디코딩
req.setCharacterEncoding("UTF-8"); //POST 방식
//get방식은 server.xml 63행 변경필요
//전송할땐 byte[]로 인코딩, 받아올 땐 디코딩
}catch(Exception ex){
}
//name을 notnull로 설정해 두었기 때문에 입력되지 않은채로 전송하려 하면 오류가 난다.
//-> 그래서 유효성 검사를 하는 것
String name=req.getParameter("name");
String subject=req.getParameter("subject");
String content=req.getParameter("content");
String pwd=req.getParameter("pwd");
BoardVO vo = new BoardVO();
vo.setName(name);
vo.setSubject(subject);
vo.setContent(content);
vo.setPwd(pwd);
//DAO와 연결!
BoardDAO dao = new BoardDAO();
dao.boardInsert(vo);
//화면 이동 -> BoardServlet
resp.sendRedirect("BoardServlet");
}
}
게시글 번호를 받아 해당 게시물의 상세 내용을 조회하는 Servlet
BoardDetail.java (Servlet)
package doodoo.servlet;
import java.io.*;
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 doodoo.dao.*;
import doodoo.vo.*;
@WebServlet("/BoardDetail")
//post방식은 form, ajax, axios 에서 많이 쓰인다.
public class BoardDetail extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1. 변환(전송방법 선택) => HTML, XML, JSON
response.setContentType("text/html; charset=UTF-8"); //서버에서 실행결과를 HTML, 한글포함 텍스트로 보내겠습니다
//2. 각 사용자별로 서버가 뿌려주고, 브라우저에서 읽어갈 위치의 메모리를 설정(HTML 여기 저장할테니까 여기서 읽어 가라)
PrintWriter out = response.getWriter();
//3. 사용자가 보내준 데이터를 받는다 ?no=88
//모든 데이터는 문자열로 받는다!!! getParameter는 리턴형이 String임.
String no = request.getParameter("no");
BoardDAO dao = new BoardDAO();
BoardVO vo = dao.boardDetail(Integer.parseInt(no),1); //no는 String이었으니까 int로 바꾼다.
out.println("<html>");
out.println("<head>");
//style
out.println("<style type=text/css>");
out.println("div{width:100%}");
out.println("h1{margin-top:50px; text-align:center}");
out.println("table{margin:0px auto;}");//브라우저 가운데에 출력해라
out.println("</style>");
out.println("<link rel=stylesheet href=table.css"); //외부 css파일 불러오기
out.println("</head>");
//body
out.println("<body>");
out.println("<div>");
out.println("<h1>내용보기</h1>");
out.println("<form method=post action=BoardInsert>");//아래 내용을 한 번에 모아서 원하는 곳으로 전송할 수 있는 form태그
out.println("<table width=700 class=table_content>");
out.println("<tr>");
out.println("<th width=25%>번호</th>");
out.println("<td width=30% align=center>"+vo.getNo()+"</td>");
out.println("<th width=25%>작성일</th>");
out.println("<td width=30% align=center>"+vo.getRegdate().toString()+"</td>");
out.println("</tr>");
out.println("<tr>");
out.println("<th width=25%>이름</th>");
out.println("<td width=30% align=center>"+vo.getName()+"</td>");
out.println("<th width=25%>조회수</th>");
out.println("<td width=30% align=center>"+vo.getHit()+"</td>");
out.println("</tr>");
out.println("<tr>");
out.println("<th width=25%>제목</th>");
out.println("<td colspan=3>"+vo.getSubject()+"</td>");
out.println("</tr>");
out.println("<tr>");
out.println("<td colspan=4 align=left valign=top style=\"height=200\">"+vo.getContent()+"</td>");
out.println("</tr>");
out.println("<tr>");
out.println("<td colspan=4 align=right >");
out.println("<a href=BoardUpdate?no="+vo.getNo()+">수정</a>");
out.println("<a href=BoardDelete?no="+vo.getNo()+">삭제</a>");
out.println("<a href=BoardServlet>목록</a>");
out.println("</td>");
out.println("</tr>");
out.println("</table>");
out.println("</body>");
out.println("</html>");
}
}
게시글 번호를 받아 내용을 불러와 미리 화면에 띄우고, 수정한 내용을 반영하는 Servlet
BoardUpdate.java (Servlet)
package doodoo.servlet;
import java.io.*;
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 doodoo.dao.*;
import doodoo.vo.*;
@WebServlet("/BoardUpdate")
public class BoardUpdate extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1. 변환(전송방법 선택) => HTML, XML, JSON
response.setContentType("text/html; charset=UTF-8");
//HTML, 한글포함 텍스트로 보내겠습니다
//2. 각 사용자별로 서버가 뿌려주고, 브라우저에서 읽어갈 위치의 메모리를 설정
PrintWriter out = response.getWriter();
//수정할 데이터를 읽어 온다.
String no = request.getParameter("no");
BoardDAO dao = new BoardDAO();
BoardVO vo = dao.boardDetail(Integer.parseInt(no), 2);
out.println("<html>");
out.println("<head>");
//style
out.println("<style type=text/css>");
out.println("div{width:100%}");
out.println("h1{margin-top:50px; text-align:center}");
out.println("table{margin:0px auto;}");//브라우저 가운데에 출력해라
out.println("</style>");
out.println("<link rel=stylesheet href=table.css"); //외부 css파일 불러오기
out.println("</head>");
//body
out.println("<body>");
out.println("<div>");
out.println("<h1>수정</h1>");
out.println("<form method=post action=BoardUpdate>");
//아래 내용을 한 번에 모아서 원하는 곳으로 전송할 수 있는 form태그
out.println("<table width=700 class=table_content>");
out.println("<tr>");
out.println("<th align=right width=15%>이름</th>");
//수정을 위한 데이터는 input 내에 들어가야 하므로,
//tag 사이가 아니라 value로 주어야 한다.
//단, value로 값을 줄 때는 공백을 포함한 글을 불러올 경우 꼭 따옴표(")로 감싸 주어야 한다.
out.println("<td width=85%><input type=text name=name size=15 value="+vo.getName()+">");
out.println("<input type=hidden name=no value="+vo.getNo()+">");//게시글 번호를 넘겨주는 부분(hidden!)
out.println("</td>");
out.println("</tr>");
out.println("<tr>");
out.println("<th align=right width=15%>제목</th>");
out.println("<td width=85%><input type=text name=subject size=45 value=\""+vo.getSubject()+"\"></td>");
out.println("</tr>");
out.println("<tr>");
out.println("<th align=right width=15%>내용</th>");
//textarea 태그의 경우에는 태그 사이에 넣어 준다.
out.println("<td width=85%><textarea rows=10 cols=50 name=content>"+vo.getContent()+"</textarea></td>");
out.println("</tr>");
out.println("<tr>");
out.println("<th align=right width=15%>비밀번호</th>");
out.println("<td width=85%><input type=password name=pwd size=10></td>");
out.println("</tr>");
out.println("<tr>");
out.println("<td colspan=2 align=center>");
out.println("<input type=submit value=수정>");
out.println("<input type=button value=취소 onclick=\"javascript:history.back()\">");
out.println("</td>");
out.println("</tr>");
out.println("</table>");
out.println("</form>");
out.println("</div>");
out.println("</body>");
out.println("</html>");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//post -> 요청 처리
//submit으로 데이터를 전송할 경우 input창에서 입력된 데이터를 넘겨 준다.
try {
request.setCharacterEncoding("UTF-8"); // 한글깨짐방지
}catch(Exception ex) {
ex.printStackTrace();
}
//하지만, input창에서의 정보만으로는 몇 번 게시글을 수정해야하는지 정보를 받아오지 못하므로
//게시글 번호를 따로 넘겨주어야 한다. -> hidden 타입 input태그를 하나 추가하여 거기서 게시글 번호를 넘겨 준다.
String no = request.getParameter("no");
String name=request.getParameter("name");
String subject=request.getParameter("subject");
String content=request.getParameter("content");
String pwd=request.getParameter("pwd");
BoardVO vo = new BoardVO();
vo.setNo(Integer.parseInt(no));
vo.setName(name);
vo.setSubject(subject);
vo.setContent(content);
vo.setPwd(pwd);
//Oracle에 연결
BoardDAO dao = new BoardDAO();
dao.boardUpdate(vo);
//화면 이동 -> BoardDetail
response.sendRedirect("BoardDetail?no="+Integer.parseInt(no));
}
}
게시물 번호를 받아 해당 번호를 가진 게시물을 삭제하는 Servlet
BoardDelete.java (Servlet)
package doodoo.servlet;
import java.io.*;
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 doodoo.dao.*;
import doodoo.vo.*;
@WebServlet("/BoardDelete")
public class BoardDelete extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String no = request.getParameter("no");
BoardDAO dao = new BoardDAO();
dao.boardDelete(Integer.parseInt(no));
//삭제 후 화면 이동
response.sendRedirect("BoardServlet");
}
}
table.css
@charset "UTF-8";/*안넣어주면 한글깨짐*/
.table_content{
border-collapse: collapse;/*테이블 테두리를 통합*/
border-top-width: 2px;
border-top-style: solid;/*라인 선의 종류. solid:일반 선, dot:점선, dash:쇄선...*/
border-bottom-width: 1px;
border-bottom-style: solid;
border-top-color: #0080ff;
border-bottom-color: #0080ff;
}
.table_content th{
background-color: #999;
color:white;
height:33px;
}
.table_content td{
height:33px;
border-bottom-style:dotted;
border-bottom-width:1px;
border-bottom-color:#333;
}
.table_content th,td{
font-family: "맑은 고딕";
font-size: 9px;
}
.table_content .dataTr:hover{
background-color: FC6;
cursor: pointer;
}
a { /*a태그 파란색/줄처리 삭제*/
text-decoration: none;
color: black;
}
a:hover {
text-decoration: underline;
color: cyan;
}
input[type=button]
, input[type=submit]{
border-radius : 50x;
background-color: cyan;
}
'부트캠프(END) > -Web 실습' 카테고리의 다른 글
JSP 실습 : 묻고 답하기 게시판 만들기 (0) | 2022.07.26 |
---|---|
JSP 실습 : 파일 첨부 게시판 만들기 (0) | 2022.07.19 |
Jsoup 실습 : 크롤링해서 로컬DB에 넣기 (0) | 2022.07.11 |
댓글()