SQL Develope 실행
create table GUEST(no number(10) primary key, name varchar2(40), regdate date, title varchar2(100), content varchar2(4000)); // create sequence guest_seq; // desc guest; // select * from guest;
📃GuestDTO.java
package xyz.itwill.dto; // /* 이름 널? 유형 ------- -------- -------------- NO NOT NULL NUMBER(10) - 글번호 : 시퀀스의 자동 증가값 NAME VARCHAR2(40) - 작성자 : 사용자 입력값 REGDATE DATE - 작성일자 : 시스템의 현재 날짜(시간) TITLE VARCHAR2(100) - 제목 : 사용자 입력값 CONTENT VARCHAR2(4000) - 내용 : 사용자 입력값 */ // public class GuestDTO { private int no; private String name; private String regdate; private String title; private String content; // public GuestDTO() { // TODO Auto-generated constructor stub } public int getNo() { return no; } public void setNo(int no) { this.no = no; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getRegdate() { return regdate; } public void setRegdate(String regdate) { this.regdate = regdate; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } }
📌 게시글을 전달받아 GUEST 테이블에 삽입하고 삽입행의 갯수를 반환하는 메소드
📃GuestDAO.java
package xyz.itwill.dao; // import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; // import xyz.itwill.dto.GuestDTO; // public class GuestDAO extends JdbcDAO { private static GuestDAO _dao; // public GuestDAO() { // TODO Auto-generated constructor stub } static { _dao=new GuestDAO(); } public static GuestDAO getDAO() { return _dao; } //게시글을 전달받아 GUEST 테이블에 삽입하고 삽입행의 갯수를 반환하는 메소드 public int insertGuest(GuestDTO guest) { Connection con=null; PreparedStatement pstmt=null; int rows=0; try { con=getConnection(); // String sql="insert into guest values(guest_seq.nextval, ?, sysdate, ?, ?)"; pstmt=con.prepareStatement(sql); pstmt.setString(1, guest.getName()); pstmt.setString(2, guest.getTitle()); pstmt.setString(3, guest.getContent()); // rows=pstmt.executeUpdate(); } catch (SQLException e) { System.out.println("[에러]insertGuest() 메소드의 SQL 오류 = "+e.getMessage()); } finally { close(con, pstmt); } return rows; } //게시글의 글번호를 전달받아 GUEST 테이블에 저장된 해당 글번호의 게시글을 삭제하고 삭제행의 갯수를 반환하는 메소드 public int deleteGuest(int no) { Connection con=null; PreparedStatement pstmt=null; int rows=0; // try { con=getConnection(); // String sql="delete from guest where no=?"; pstmt=con.prepareStatement(sql); pstmt.setInt(1, no); // rows=pstmt.executeUpdate(); } catch (SQLException e) { System.out.println("[에러]insertGuest() 메소드의 SQL 오류 = "+e.getMessage()); } finally { close(con, pstmt); } return rows; } //GUEST 테이블에 저장된 모든 게시글을 검색하여 반환하는 메소드 public List<GuestDTO> selectGuestList() { Connection con=null; PreparedStatement pstmt=null; ResultSet rs=null; List<GuestDTO> guestList=new ArrayList<>(); // try { con=getConnection(); // String sql="select * from guest order by no desc"; pstmt=con.prepareStatement(sql); // rs=pstmt.executeQuery(); // while(rs.next()) { GuestDTO guest=new GuestDTO(); guest.setNo(rs.getInt("no")); guest.setName(rs.getString("name")); guest.setRegdate(rs.getString("regdate")); guest.setTitle(rs.getString("title")); guest.setContent(rs.getString("content")); guestList.add(guest); } } catch (SQLException e) { System.out.println("[에러]insertGuest() 메소드의 SQL 오류 = "+e.getMessage()); } finally { close(con, pstmt, rs); } return guestList; } }
📌 GUEST 테이블에 저장된 모든 게시글을 검색하여 클라이언트에게 전달하는 서블릿
📃GuestSelectServlet.java
package xyz.itwill.servlet; // import java.io.IOException; import java.io.PrintWriter; import java.util.List; // 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 xyz.itwill.dao.GuestDAO; import xyz.itwill.dto.GuestDTO; // //GUEST 테이블에 저장된 모든 게시글을 검색하여 클라이언트에게 전달하는 서블릿 //→ [방명록 쓰기]를 클릭한 경우 입력페이지(insert.html)로 이동 @WebServlet("/select.itwill") public class GuestSelectServlet extends HttpServlet { private static final long serialVersionUID = 1L; // protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); PrintWriter out=response.getWriter(); // //GUEST 테이블에 저장된 모든 게시글을 검색하여 반환하는 DAO 클래스의 메소드 호출 List<GuestDTO> guestList=GuestDAO.getDAO().selectGuestList(); // //처리결과를 웹문서로 생성하여 클라이언트에게 전달 - 응답 out.println("<!DOCTYPE html PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN' 'http://www.w3.org/TR/html4/loose.dtd'>"); out.println("<html>"); out.println("<head>"); out.println("<meta http-equiv='Content-Type' content='ext/html; charset=UTF-8'>"); out.println("<title>Servelt</title>"); out.println("<link rel='stylesheet' type='text/css' href='css/common.css'>"); out.println("</head>"); out.println("<body>"); out.println("<table width='80%' align='center' border='0' cellspacing='0' cellpadding='0'>"); out.println("<tr bgcolor='#000080' valign='middle'>"); out.println("<td height='25' class='t1' align='center'>"); out.println("<b><font color='#FFFFFF'>:::방명록 읽기 :::</font></b>"); out.println("</td>"); out.println("</tr>"); // out.println("<tr>"); out.println("<td height='30' align='right' valign='bottom' class='t1'>"); out.println("<a href='insert.html'>방명록 쓰기</a></td>"); out.println("</tr>"); // if (guestList.isEmpty()) {// 검색된 게시글이 없는 경우 out.println("<tr align='center'>"); out.println("<td>방명록에 저장된 게시글이 하나도 없습니다.</td>"); out.println("</tr>"); } else {// 검색된 게시글이 있는 경우 // List 객체에 저장된 요소값(DTO 객체)를 반복적으로 제공받아 응답 처리 for (GuestDTO guest : guestList) { out.println("<tr>"); out.println("<td>"); out.println("<table width='100%' align='center' border='1' cellspacing='0' bgcolor='#f5f5f5'>"); out.println("<tr>"); out.println("<td>"); out.println("<table width='100%' align='center' border='0' cellspacing='0'>"); out.println("<tr>"); out.println("<td bgcolor='#808000' align='center' height='20' width='20%' class='t1'>"); out.println("<font color='#FFFFFF'>제 목</font></td>"); out.println("<td height='20' width='80%' class='t1'>"); out.println("<b><font color='#0000FF'> " + guest.getTitle() + "</font></b></td>"); out.println("</tr>"); out.println("</table>"); out.println("</td>"); out.println("</tr>"); // out.println("<tr>"); out.println("<td>"); out.println("<table width='100%' align='center' border='0' cellspacing='0'>"); out.println("<tr>"); out.println("<td bgcolor='#808000' align='center' height='20' width='20%' class='t1'>"); out.println("<font color='#FFFFFF'>작 성 자</font></td>"); out.println("<td align='center' height='20' width='30%' class='t1'>" + guest.getName() + "</td>"); out.println("<td bgcolor='#808000' align='center' height='20' width='20%' class='t1'>"); out.println("<font color='#FFFFFF'>작 성 일</font></td>"); out.println("<td align='center' height='20' width='30%' class='t1'>" + guest.getRegdate() + "</td>"); out.println("</tr>"); out.println("</table>"); out.println("</td>"); out.println("</tr>"); // out.println("<tr>"); out.println("<td>"); out.println("<table width='100%' align='center' border='0' cellspacing='10'>"); out.println("<tr>"); out.println("<td height='50' width='100%' class='t1'>"); out.println(guest.getContent().replace("\n", "<br>")); out.println("</td>"); out.println("</tr>"); out.println("</table>"); out.println("</td>"); out.println("</tr>"); out.println("</table>"); out.println("</td>"); out.println("</tr>"); // out.println("<tr>"); out.println("<td height='20'>"); out.println("<hr color='#000077'>"); out.println("</td>"); out.println("</tr>"); } } out.println("</table>"); out.println("</body>"); out.println("</html>"); } }
📃insert.html
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <!-- GUEST 테이블에 저장될 방명록 게시글을 사용자에게 입력받기 위한 문서 - 입력페이지 --> <!-- => [방명록 쓰기]를 클릭하면 게시글 저장페이지(insert.itwill)로 이동 - 웹프로그램 요청하여 사용자 입력값(방명록 게시글) 전달 --> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Servlet</title> <link rel="stylesheet" type="text/css" href="css/common.css"> <SCRIPT LANGUAGE="JavaScript" SRC="js/common.js"> </SCRIPT> <SCRIPT language="JavaScript"> function loading(form) { form.name.focus(); } function form_submit(form, action, method) { if(is_null_field(form)) return; form.action=action; form.method=method; form.submit(); } function is_null_field(form) { if(is_null(form.name.value) || is_space(form.name.value)) { alert("이름을 입력해요."); form.name.focus(); return true; } if(is_null(form.title.value) || is_space(form.title.value)) { alert("제목을 입력해요."); form.title.focus(); return true; } if(is_null(form.content.value) || is_space(form.content.value)) { alert("내용을 입력해요."); form.content.focus(); return true; } } </SCRIPT> </head> <body onLoad="loading(guest);"> <form name="guest"> <table width="80%" align="center" border="0" cellspacing="0" cellpadding="0"> <tr bgcolor="#556b2f" valign="middle"> <td height="25" class="t1" align="center"> <b><font color="#FFFFFF">::: 방명록 쓰기 :::</font></b> </td> </tr> <tr> <td height="20" > </td> </tr> <tr> <td> <table width="100%" align="center" border=1 cellspacing=0> <tr> <td> <table width="100%" align="center" border="0" cellspacing="0"> <tr> <td bgcolor="#808000" align="center" height="20" width="20%" class="t1"> <font color="#FFFFFF">이 름</font> </td> <td height="20" width="80%" class="t1"> <input type="text" name="name" maxlength="24" size="24" class="TXTFLD"> </td> </tr> </table> </td> </tr> <tr> <td> <table width="100%" align="center" border="0" cellspacing="0"> <tr> <td bgcolor="#808000" align="center" height="20" width="20%" class="t1"> <font color="#FFFFFF">제 목</font> </td> <td height="20" width="80%" class="t1"> <input type="text" name="title" maxlength="80" size="80" class="TXTFLD"> </td> </tr> </table> </td> </tr> <tr> <td> <table width="100%" align="center" border="0" cellspacing="10"> <tr> <td height="50" width="1000%" class="t1"> <textarea cols="98" name="content" rows="10" class="TXTFLD"></textarea> </td> </tr> </table> </td> </tr> </table> </td> </tr> <tr> <td height="50" align="center"> <input type="button" value="방명록 쓰기" class="TXTFLD" onclick="form_submit(guest,'insert.itwill','POST');"> <input type="reset" value="다시 작성하기" class="TXTFLD"> </td> </tr> </table> </form> </body> </html>
📌 입력페이지(insert.htmle)에서 전달된 게시글을 반환받아 GUEST 테이블에 삽입하고 클라이언트에게 게시글목록 출력페이지(select.itwill)로 이동하기 위한 URL 주소를 전달 - 처리페이지
📃GuestInsertServlet.java
package xyz.itwill.servlet; // import java.io.IOException; //import java.io.PrintWriter; // 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 xyz.itwill.dao.GuestDAO; import xyz.itwill.dto.GuestDTO; // //입력페이지(insert.htmle)에서 전달된 게시글을 반환받아 GUEST 테이블에 삽입하고 클라이언트에게 //게시글목록 출력페이지(select.itwill)로 이동하기 위한 URL 주소를 전달 - 처리페이지 @WebServlet("/insert.itwill") public class GuestInsertServlet extends HttpServlet { private static final long serialVersionUID = 1L; // protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //response.setContentType("text/html;charset=utf-8"); //PrintWriter out=response.getWriter();//출력페이지를 만드는게 아니라서 필요없음 //비정상적인 요청에 대한 처리 if(request.getMethod().equals("GET")) {//클라이언트가 서블릿을 [GET] 방식으로 요청한 경우 //클라이언트에게 에러코드 전달 response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);//405 에러코드 return; } //리퀘스트 메세지의 몸체부에 저장되어 전달되는 값(POST)에 대한 캐릭터셋 변경 request.setCharacterEncoding("utf-8"); // //전달값(게시글)을 반환받아 저장 //→ String.trim() 메소드를 호출하여 전달값의 앞 또는 뒤에 존재하는 모든 공백 제거 //→ String.replace() 메소드를 호출하여 XSS 공격에 대한 방어를 위해 태그 관련 기호를 회피문자(Escape Charter)로 변환 //XSS(Cross Site Scripting) : 입력태그에 악의적인 스트립트를 입력하여 출력페이지를 파괴시키거나 개인정보를 특정 사이트로 유출하는 웹사이트 공격 방법 String name=request.getParameter("name").trim().replace("<", "<").replace(">", ">"); String title=request.getParameter("title").trim().replace("<", "<").replace(">", ">"); String content=request.getParameter("content").trim().replace("<", "<").replace(">", ">"); // //DTO 객체를 생성하여 전달값으로 필드값 변경 GuestDTO guest=new GuestDTO(); guest.setName(name); guest.setTitle(title); guest.setContent(content); // //게시글(GuestDTO 객체)을 전달받아 GUEST 테이블에 삽입하는 DAO 클래스의 메소드 호출 GuestDAO.getDAO().insertGuest(guest); // //클라이언트에게 301 상태코드와 URL 주소 전달 response.sendRedirect("select.itwill");//리다이렉트 이동 } }
📌 게시글목록 출력페이지(select.itwill)에서 전달된 글번호를 반환받아 GUEST 테이블에 저장된 해당 글번호의 게시글을 삭제하고 게시글목록 출력페이지(select.itwill)로 이동하기 위한 URL 주소 전달하는 서블릿 - 글번호 전달
📃GuestDeleteServlet.java
package xyz.itwill.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 xyz.itwill.dao.GuestDAO; // //게시글목록 출력페이지(select.itwill)에서 전달된 글번호를 반환받아 GUEST 테이블에 저장된 해당 //글번호의 게시글을 삭제하고 게시글목록 출력페이지(select.itwill)로 이동하기 위한 URL 주소 전달하는 서블릿 - 글번호 전달 @WebServlet("/delete.itwill") public class GuestDeleteServlet extends HttpServlet { private static final long serialVersionUID = 1L; // protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //비정상적인 요청에 대한 처리 if(request.getParameter("no")==null) {//전달값이 없는 경우 response.sendError(HttpServletResponse.SC_BAD_REQUEST);//400 에러코드 return; } // //전달값(글번호)을 반환받아 저장 - 문자열 >> 정수값 int no=Integer.parseInt(request.getParameter("no")); // //글번호를 전달받아 GUEST 테이블에 저장된 해당 글번호의 게시글을 삭제하는 DAO 클래스의 메소드 호출 int rows=GuestDAO.getDAO().deleteGuest(no); // if(rows>0) {//삭제행이 있는 경우 response.sendRedirect("select.itwill"); } else {//삭제행이 없는 경우 - 비정상적인 요청 response.sendError(HttpServletResponse.SC_BAD_REQUEST); } } }