- 게시판 글 쓸때 Editor를 사용
- [국내 - WEB EDITOR]
- 1. Daum Editor(Kakao)
- 2. Naver Editor
- 3. Namo Editor
- [국외 - WEB EDITOR]
- 1. CKEditor
- 2. Toast Editor - React전용
- 3. DEXTUpload Editor
- 4. Quill Editor - Vue전용
- WEB EDITOR의 글은 코드 형식으로 DB에 저장!
CKEditor
- 버전, 다운로드
- LTS는 유료임 작동X
- CKEditor4 > Full Package > Easy Image 체크하지않고 다운해서 적용하기
- 압축 풀어서 ckeditor 아래사진 항목만 사용 why? 다른 파일 넣으면 보안 쓰레기됨
- 이미지 미리보기에 주저리주저리 지우기 셋팅
- ./ckeditor/plugins/image/dialogs/image.js 에서 Lorem ipsum검색
- 해당 따옴표 안을 모두 비우기
- 버전 보안 빨간 알림창 지우기
- ./ckeditor/config.js 파일의 함수 안에
- config.versionCheck = false; 넣기
- 에디터 상단 기능을 핸들링 (필요한 기능만 쓰기, 물음표,버전 안보이게하기)
- 에디터 홈페이지 > Customize > Online Builder > 필요한건 넣고 필요없는건 빼기
> 최하단 Download CKEditor (OS) 다운해서 config.js파일만 덮어쓰기함 - 거기에 알람지우는 config.versionCheck = false; 만 추가하기
- 에디터 홈페이지 > Customize > Online Builder > 필요한건 넣고 필요없는건 빼기
- 이놈은 textarea 마냥 resize가 됨 줄었다 늘었다.. 그거 세팅
- config.js파일에 config.resize_enable = false; 추가
DB 설계시 주의사항
html에는 없지만 넣어야하는 것들
아이디가 없지만 아이디를 히든으로 해서 HTML에 넣어줘야함
DB에 같이 넣어줘야함
+ "아이디" 넣어야함 !
+ "작성 날짜, 시간"도 넣어야함 !
+ "조회수"도 넣어야함 !
+ 추천이있는 게시판이라면 추천수도 !
=> 게시판은 항상 리스트를 같이 봐야함 !
첨부파일 처리시
사용자 첨부파일 => 123.xlsx => Server => 20250306_123.xlsx
이렇게 해야 덮어쓰기되지 않음 !
사용자가 게시판 첨부파일 확인시
123.xlsx => 20250306_123.xlsx
DB엔 "파일 이름", "파일 경로" 를 넣으며 null 속성을 넣어줌 ! 파일 첨부 안할수도 있으니까
notice_write.html
글쓰기 페이지
+ notice_write.js
게시물 등록시 체크
↓
notice_writeok.java (servlet)
html에서 넘어온 정보와 기타 정보들을 합쳐서 DB에 저장하는 Controller
+ m_notice.java (class)
첨부파일이 있을 경우 DB에 저장하는 Model
↓
게시판 먼저 출력할때 notice_list.do
notice_list.java (servlet)
게시판 리스트를 출력하기 위해 DB의 모든 게시물 데이터들을 가져오는 Controller
+ m_noticelist.java (class)
DB에 있는 모든 데이터를 가져오는 Model
↓
notice_list.jsp
게시판을 출력, 게시물 클릭시 해당 게시물로 이동
↓
notice_view.java (servlet)
게시물 출력을 위한 Controller
+ m_noticeview.java (class)
Database에 Table 사항 중 where 및 조회수 증가 Model
↓
notice_view.jsp
게시물을 출력
글 수정, 글 삭제 버튼 (미구현)
notice_write.html
글쓰기 페이지
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>공지사항 글등록 페이지</title>
<script src="./ckeditor/ckeditor.js?v=6"></script>
</head>
<body>
<form id="frm" method="post" action="./notice_writeok.do" enctype="multipart/form-data">
제목 : <input type="text" name="subject"><br>
글쓴이 : <input type="text" name="writer"><br>
비밀번호 : <input type="password" name="pw"><br>
내용 : <textarea name="texts" id="editor"></textarea><br>
첨부파일 : <input type="file" name="nfile"><br>
<input type="button" value="글등록" onclick="writeck()">
</form>
</body>
<script>
//window.onload : 현재 페이지가 실행됐을때
//이건 꼭 하단 스크립트에 적어야함!
window.onload = function() {
var ck = CKEDITOR.replace("editor", {
width : 900,
height : 400,
versionCheck : false
});
}
</script>
<script src="./notice_write.js?v=1"></script>
</html>
- 첨부파일 핸들링시 필수사항
- 1. post로 전송
- 2. enctype 속성
- 3. @MultipartConfig (servlet)
- window.onload : 현재 페이지가 실행됐을때
- 이건 꼭 하단 스크립트에 적어야함!
- 에디터 핸들링
- window.onload 함수에 editor 올리기
notice_write.js
게시물 등록시 체크
//게시물 등록시 체크하는 함수
//여기에 texts 게시판 내용을 체크하면 망가짐 => 내용을 넣어도 안넣었다고 인식 ! 주의
function writeck(){
if(frm.subject.value==""){
alert("제목을 입력하셔야 합니다.");
frm.subject.focus();
}else if(frm.writer.value==""){
alert("글쓴이를 입력하셔야 합니다.");
frm.writer.focus();
}else if(frm.pw.value==""){
alert("비밀번호를 입력하셔야 합니다.");
frm.pw.focus();
}else {
//CKEDITOR.instances.HTML의 id명.getData() : ckeditor를 로드
var txt = CKEDITOR.instances.editor.getData();
if(txt == ""){
alert("내용을 입력하셔야합니다.")
}else if(txt.length < 40){ //엔터바바박 방지
alert("최소 40자 이상 입력되어야 합니다.");
}else{
frm.submit();
}
}
}
- 에디터의 내용을 확인할 때
- input 태그의 name으로 핸들링 불가능!
- ckeditor를 로드해서 확인해야 함
notice_writeok.java (servlet)
html에서 넘어온 정보와 기타 정보들을 합쳐서 DB에 저장하는 Controller
package notice;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.PreparedStatement;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import shop.m_dbinfo;
import shop.m_md5;
//원래는 컨트롤러에 10줄도 안씀! 다 모델로 만들어야함 !!!
//실무에서 이렇게 만들면 욕을 바가지로 먹는다 !!!
//파일첨부시 필수 !
@MultipartConfig(
fileSizeThreshold = 1024 * 1024 * 5, //파일하나 5MB
maxFileSize = 1024 * 1024 * 50, //파일들의 총 용량 50MB
maxRequestSize = 1024 * 1024 * 500 //파일이 여러개 날아올때만 필요한 라인 //파일 하나만 날아올땐 필요없음
)
public class notice_writeok extends HttpServlet {
private static final long serialVersionUID = 1L;
Connection con = null;
//ResultSet 필요없음! 쓰기 할거니까
PreparedStatement ps = null;
PrintWriter pw = null;
//Model
m_dbinfo db = new m_dbinfo(); //DB 접속 정보
m_md5 md5 = new m_md5(); //md5 암호화
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
this.pw = response.getWriter();
//첨부파일이 있고, 없고 따라서 SQL 저장방식이 변경됨
Part nfile = request.getPart("nfile");
long filesize = nfile.getSize(); //getSize()는 long값으로 return해줌
try {
this.con = this.db.getConnection(); //DB 연결
String subject = request.getParameter("subject");
String writer = request.getParameter("writer");
String pw = request.getParameter("pw");
String texts = request.getParameter("texts");
//패스워드를 암호화
pw = this.md5.md5_code(pw);
String sql = ""; //DB Query문
int result = 0; //DB에서 저장된 결과를 받는 변수 (저장되면 1) select에는 필요없음 i,u,d에만 필요
if(filesize == 0) { //첨부파일이 없을 경우
sql = "insert into notice (nidx,subject,writer,pw,texts,ndate)"
+ "values ('0',?,?,?,?,now())";
this.ps = this.con.prepareStatement(sql);
this.ps.setString(1, subject);
this.ps.setString(2 , writer);
this.ps.setString(3, pw);
this.ps.setString(4, texts);
//System.out.println(sql);
result = this.ps.executeUpdate(); //DB에 저장
if(result > 0) { //저장이 된 경우
this.pw.write("<script>"
+ "alert('게시물이 올바르게 등록되었습니다.');"
+ "location.href = './notice_list.jsp';"
+ "</script>");
}else { //저장이 안된 경우
}
}else { //첨부파일이 있을 경우
//Model을 이용하여 첨부파일을 저장하는 방식
m_notice nt = new m_notice(nfile,subject,writer,pw,texts,request);
//return 메소드가 private이므로 전역변수의 값을 직접 로드
String msg = nt.msg; //모델의 필드에 올라온 변수는 이렇게 처리 가능
//리턴 받으려고 굳이굳이 public사용하지 않아도됨 !! 필드 사용하기
if(msg.equals("ok")) {
this.pw.write("<script>"
+ "alert('올바르게 공지사항이 등록되었습니다.');"
+ "location.href = './notice_list.jsp';"
+ "</script>");
}else {
this.pw.write("<script>"
+ "alert('데이터베이스 및 첨부파일 오류 발생');"
+ "history.go(-1);"
+ "</script>");
}
}
}catch (Exception e) {
this.pw.write("<script>"
+ "alert('데이터베이스 문제로 인하여 저장되지 않았습니다.');"
+ "history.go(-1);"
+ "</script>");
}finally {
try {
this.ps.close();
this.con.close();
this.pw.close();
}catch (Exception e) {
}
}
}
}
- 저장이 잘 되었을 경우 notice_list.jsp로 이동
- 저장이 안된 경우 에러메세지 출력 후 이전페이지로 이동
m_notice.java (class)
위 서블릿파일에서 사용
첨부파일이 있을 경우 DB에 저장하는 Model
package notice;
import java.sql.Connection;
import java.sql.PreparedStatement;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.Part;
import shop.m_dbinfo;
//공지사항 게시판 파일을 저장하는 Model
//원래 DTO도 써야됨 !!
public class m_notice extends HttpServlet{
Connection con = null;
PreparedStatement ps = null;
m_dbinfo db = new m_dbinfo();
String sql = ""; //DB 쿼리문
int result = 0; //DB 저장 결과값
String msg = ""; //Model에서 처리된 값을 Controller로 결과값을 반환
String subject,writer,pw,texts; //ArrayList로 만들어도됨
//즉시실행메소드에서는 첨부파일을 저장하는 역할만 수행 => 다른메소드에서 DB로 연결
public m_notice(Part nfile,String subject,String writer,String pw,String texts,HttpServletRequest request) throws Exception{
//DTO를 안만들어서 이모양으로 해야함
this.subject = subject;
this.writer = writer;
this.pw = pw;
this.texts = texts;
long filesize = nfile.getSize(); //파일 용량
String filenm = nfile.getSubmittedFileName(); //파일명
// System.out.println(request.getServletContext().getRealPath("")); //파일 저장 경로 확인
String url = request.getServletContext().getRealPath("/notice_file/"); //첨부파일 저장될 Web Directory 설정
try {//io니까 트캐 넣기
nfile.write(url + filenm); //웹에 저장
this.fileok(filenm); //정상적으로 저장되었을 경우
}catch (Exception e) {
this.fileok("error"); //비정상적으로 해당 디렉토리에 파일이 저장되지 않을 경우
}
}
//DB로 저장 및 Controller로 결과값을 return하는 메소드
private String fileok(String data) throws Exception{
if(data.equals("error")) {
this.msg = "error";
}else { //파일이 정상적으로 저장되었을 경우
try {
this.con = this.db.getConnection();
this.sql = "insert into notice (nidx,subject,writer,pw,texts,filenm,nfile,ndate)"
+ "values ('0',?,?,?,?,?,?,now())";
this.ps = this.con.prepareStatement(sql);
this.ps.setString(1, this.subject);
this.ps.setString(2, this.writer);
this.ps.setString(3, this.pw);
this.ps.setString(4, this.texts);
this.ps.setString(5, data);
this.ps.setString(6, data);
//물음표개수랑 setString개수 다르면 에러남 !
this.result = this.ps.executeUpdate();
if(result > 0) { //저장이 된 경우
this.msg = "ok";
}else { //저장이 안된 경우
this.msg = "error";
}
}catch (Exception e) {
this.msg = "error";
}finally {
//원래 여기에 트캐 넣어야하는데 throws사용 => 즉시실행 메소드에도 throws 사용
//서블릿에서는 post메소드 스스로 만들어져있어서 못썼었지만 모델에서는 가능
this.ps.close();
this.con.close();
}
}
return this.msg; //Controller로 보내는 값
}
}
notice_list.java (servlet)
게시판 리스트를 출력하기 위해 DB의 모든 게시물 데이터들을 가져오는 Controller
package notice;
import java.io.IOException;
import java.util.ArrayList;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class notice_list extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//사용자가 페이지 번호를 클릭시 해당 값을 받는 역할
String pageno = request.getParameter("pageno");
//페이지번호 인티저로 받으면 null일때 parseInt에서 오류남
//String으로 받고 조건 확인하고 parseInt로 넘기기
if(pageno == null || pageno.equals("1")) { //게시판 최초 접속 or 1번 페이지일때 페이지 배열번호 0으로 처리
pageno = "0";
}
//list를 출력하기 위한 Database Table을 로드하는 Model
m_noticelist nl = new m_noticelist(Integer.parseInt(pageno));
//2차 클래스배열로 저장된 Table에 모든 데이터를 셋팅함
ArrayList<ArrayList<String>> result = nl.db_data();
//JSP로 2차 클래스 배열 값을 전달(View)
request.setAttribute("result", result);
request.setAttribute("pageno", pageno);
// System.out.println(result);
RequestDispatcher rd = request.getRequestDispatcher("./notice_list.jsp");
rd.forward(request,response);
}
}
- 페이징
- pageno : 페이지 번호
- View에서 넘어오는 경우 => 자료형 String
- 숫자라고 int로 받은 경우 null 처리 불가능
- null 값을 받는다고 Integer로 설정시 View에서는 String으로 넘어오는데 Integer.parseInt()가 null을 처리불가능
- => String으로 받고 조건문으로 처리 후 다른곳으로 넘길 때 Integer로 변환하여 넘기기
- 최초접속 or 1번째 페이지 선택시 => pageno = 0
- 리스트를 출력해주는 Model에 페이지 번호를 인수값으로 넣어 전달
m_noticelist.java (class)
위 서블릿파일에서 사용
DB에 있는 모든 데이터를 가져오는 Model
package notice;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import shop.m_dbinfo;
//DB에 있는 모든 데이터를 가져오는 역할(Model)
public class m_noticelist {
Connection con = null;
PreparedStatement ps = null;
ResultSet rs = null;
String sql; //sql Query
m_dbinfo db = new m_dbinfo();
ArrayList<String> data = null; //1차배열 각 컬럼별 값을 저장
ArrayList<ArrayList<String>> alldata = null; //Database 전체 데이터를 저장
int spage = 0; //첫번째 배열값
int ea = 3; //페이지당 출력할 게시물 수
public m_noticelist(int s) {
if(s > 0){ //1번 페이징 번호 외의 번호를 클릭했을 경우
//(페이지번호 -1) * 한 페이지당 출력할 갯수
this.spage = (s - 1) * ea;
}else {
this.spage = s; //sql query문의 limit를 사용하기 위함
}
}
public ArrayList<ArrayList<String>> db_data(){
try {
this.con = db.getConnection();
//필요한 컬럼만 지정하여 select 문법으로 데이터를 가져오는 코드
this.sql = "select nidx,subject,writer,nview,ndate,(select count(*) from notice) as total from notice order by nidx desc limit ?,?"; //nidx도 가져와야함!!
this.ps = this.con.prepareStatement(this.sql);
this.ps.setInt(1, this.spage);
this.ps.setInt(2, this.ea);
this.rs = this.ps.executeQuery(); //select여서 executeQuery쓴거임
//반복문으로 Table에 있는 컬럼을 1차 배열로 이관 후 2차배열에 담는 코드
this.alldata = new ArrayList<>();
while(this.rs.next()) {
this.data = new ArrayList<>();
this.data.add(this.rs.getString("nidx"));
this.data.add(this.rs.getString("subject"));
this.data.add(this.rs.getString("writer"));
this.data.add(this.rs.getString("nview"));
this.data.add(this.rs.getString("ndate"));
this.data.add(this.rs.getString("total")); //게시물 전체 갯수 저장한 값
this.alldata.add(this.data);
}
// System.out.println(this.alldata);
}catch (Exception e) {
this.alldata = null;
}finally {
try {
this.ps.close();
this.con.close();
}catch (Exception e) {
this.alldata = null;
}
}
//Model에서 Controller로 데이터를 회신함
return this.alldata;
}
}
- 페이징
- spage : limit 시작 인덱스 (첫번째 배열값)
- 0일때 : Controller에서 넘어온 pageno 그대로 사용 (0)
- 0이 아닐때 : (pageno -1) * 한페이지출력개수
- spage : limit 시작 인덱스 (첫번째 배열값)
- 즉시실행 메소드 실행 : 모델의 페이지번호 설정
- 설정해둔 페이지번호를 이용해 해당 페이지의 데이터 가져옴
notice_list.jsp
게시판을 출력, 게시물 클릭시 해당 게시물로 이동
<%@page import="java.util.ArrayList"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
ArrayList<ArrayList<String>> notice = (ArrayList<ArrayList<String>>)request.getAttribute("result");
//페이지 번호 생성
/*
페이징 생성방법
1. 한 페이지당 몇개씩 데이터를 출력할 것인지를 설정합니다.
2. 데이터베이스에 있는 데이터의 총 갯수 / 한페이지당 갯수 (소수점)
3. Math.ceil 사용하는 이유는 1.1 1.6 => 올림으로 페이지가 추가 되도록 합니다.
*/
String total_page = notice.get(0).get(5);
int pg = 1;
if(total_page != null || !total_page.equals(null)){
float pg2 = Integer.parseInt(total_page) / 3f;
pg = (int)Math.ceil(pg2);
}
/*
get page번호를 가져오는 방식
최초 공지사항 리스트 페이지에 접근시 페이지 번호가 없을 수 있음 또는
페이지번호가 1을 클릭했을 경우
*/
String pno = request.getParameter("pageno");
if(pno == null || pno.equals("1")){
pno = "1";
}
%>
<!-- View -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>공지사항 리스트</title>
</head>
<body>
<p>현재 등록된 게시물 : <%=notice.get(0).get(5)%></p>
<table border="1" cellpadding="0" cellspacing="0">
<thead>
<tr>
<th width="50">번호</th>
<th width="500">제목</th>
<th width="100">글쓴이</th>
<th width="100">조회</th>
<th width="150">등록일</th>
</tr>
</thead>
<tbody>
<%
int f;
//리스트 출력 번호를 총 데이터 갯수로 처리
//총 데이터 갯수 - ((페이지번호 - 1) * 한페이지당 출력갯수)
int total = Integer.parseInt(total_page) - ((Integer.parseInt(pno)-1) * 3);
for(f=0; f<notice.size(); f++){
%>
<tr height="30" align="center">
<td><%=total%></td>
<td align="left" onclick="notice_view('<%=notice.get(f).get(0)%>')"><%=notice.get(f).get(1)%></td>
<td><%=notice.get(f).get(2)%></td>
<td><%=notice.get(f).get(3)%></td>
<td><%=notice.get(f).get(4).substring(0,10)%></td>
</tr>
<%
total--;
}
%>
</tbody>
</table>
<br><br><br>
<table border="1">
<tr>
<%
int w = 1;
while(w <= pg){
%>
<td width=20 height=20 align="center"><a href="./notice_list.do?pageno=<%=w%>"><%=w%></a></td>
<%
w++;
}
%>
</tr>
</table>
</body>
<script>
function notice_view(no){
//해당 게시물의 내용 및 첨부파일을 확인 할 수 있는 view 페이지
location.href='./notice_view.do?nidx='+no;
}
</script>
</html>
- 상단에서 이전 servlet에서 받아온 DB의 모든 게시판 데이터를 로드
- 게시물 수 : 배열의 크기
- 테이블에 반복문 적용
- 배열의 크기(게시물의 수)만큼 반복
- 게시물의 정보를 출력
- 제목 클릭시 해당 게시물 페이지로 이동
- 날짜는 DB에 시간까지 적용되어있음 => substring() 이용하여 "년월일" 만 출력
- 페이징
- total_page : Controller에서 넘어온 notice 배열의 total => 게시물의 총 개수
- pno : total_page가 null이 아닐때 한페이지출력개수만큼 나눈것을 올림 => 페이지 번호
- total_page : Controller에서 넘어온 notice 배열의 total => 게시물의 총 개수
- 게시물 번호
- total : 총데이터개수 - ( (페이지번호 -1) * 한페이지당출력개수 )
- 반복문 돌리며 total--;
notice_view.java (servlet)
게시물 출력을 위한 Controller
package notice;
import java.io.IOException;
import java.util.ArrayList;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class notice_view extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
int nidx = Integer.parseInt(request.getParameter("nidx"));
// System.out.println(nidx);
//조회수 +1 증가 및 데이터를 출력
m_noticeview mv = new m_noticeview();
mv.viewcount(nidx);
//게시물 1개의 데이터 내용을 JSP로 전달
ArrayList<String> notice_v = mv.db_data;
// System.out.println(notice_v);
request.setAttribute("notice_v", notice_v);
RequestDispatcher rd = request.getRequestDispatcher("./notice_view.jsp");
rd.forward(request, response);
}
}
m_noticeview.java (class)
위 서블릿파일에서 사용
Database에 Table 사항 중 where 및 조회수 증가 Model
package notice;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import shop.m_dbinfo;
//Database에 Table 사항 중 where 및 조회수 증가
//Query : select, update
public class m_noticeview {
Connection con = null;
PreparedStatement ps = null;
ResultSet rs = null;
String sql = ""; //Query문법
m_dbinfo db = new m_dbinfo(); //Database 정보
ArrayList<String> db_data = null; //한개의 데이터 그룹만 저장시킴
public void viewcount(int nidx) {
try {
this.con = this.db.getConnection();
//해당 컬럼에 값을 +1씩 증가시키는 Query문
this.sql = "update notice set nview= nview+1 where nidx=?";
this.ps = this.con.prepareStatement(this.sql);
this.ps.setInt(1, nidx); //nidx는 숫자니까 setInt
this.ps.executeUpdate(); //Query문을 실행!@!
//해당 테이블에 맞는 컬럼 값을 select 함
this.sql = "select * from notice where nidx=? order by nidx desc";
this.ps = this.con.prepareStatement(this.sql);
this.ps.setInt(1, nidx);
this.rs = this.ps.executeQuery();
if(this.rs.next() == true) { //해당 조건에 맞는 데이터가 있을 경우
this.db_data = new ArrayList<>();
this.db_data.add(this.rs.getString("nidx"));
this.db_data.add(this.rs.getString("subject"));
this.db_data.add(this.rs.getString("writer"));
this.db_data.add(this.rs.getString("pw"));
this.db_data.add(this.rs.getString("texts"));
this.db_data.add(this.rs.getString("filenm"));
this.db_data.add(this.rs.getString("nfile"));
this.db_data.add(this.rs.getString("nview"));
this.db_data.add(this.rs.getString("ndate"));
}
}catch (Exception e) {
}finally {
try {
this.ps.close();
this.con.close();
}catch (Exception e) {
}
}
}
}
notice_view.jsp
게시물을 출력
글 수정, 글 삭제 버튼
<%@page import="java.util.ArrayList"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
//Controller에서 1차 클래스 배열값을 JSP애서 받아서 출력하는 방식
ArrayList<String> views = (ArrayList<String>)request.getAttribute("notice_v");
if(views == null){ //데이터가 없을 경우 script 발동 후 리스트 페이지로 이동
out.print("<script>alert('올바른 접근이 아닙니다'); location.href='./notice_list.do';</script>");
}else{ //null이 아닐 경우 HTML을 활성화
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>공지사항 내용확인</title>
<style>
.data1{
width:400px;
height:30px;
line-height:30px;
border-bottom: 1px solid gray;
}
.n{
display:flex;
flex-direction: row;
justify-content: flex-start;
align-content: center;
}
.data2{
border:1px solid gray;
width:800px;
height:400px;
overflow-y:auto;
}
</style>
</head>
<body>
<span class="n">등록일 : <div class="data1"><%= views.get(8)%></div></span><br>
<span class="n">제목 : <div class="data1"><%= views.get(1)%></div></span><br>
<span class="n">글쓴이 : <div class="data1"><%= views.get(2)%></div></span><br>
<span class="n">조회수 : <div class="data1"><%= views.get(7)%></div></span><br>
<span class="n">내용 : <div class="data2"><%= views.get(4)%> </div></span><br>
<%
if(views.get(5) != null){ //첨부파일이 있을 경우만 해당 태그가 작동되도록 설정함
%>
<span class="n">첨부파일 : <div class="data1">
<a href="../notice_file/<%= views.get(5)%>" target="_blank"><%= views.get(5)%></a>
</div></span><br>
<%
}
%>
<br><br>
<!-- 패스워드 확인 후 데이터 삭제 -->
<form id="frm" method="post" action="./notice_delete.do">
<!-- 자동증가값을 hidden에 적용하여 form 전송 -->
<input type="hidden" name="nidx" value="<%= views.get(0)%>">
<!-- DB에 저장된 MD5 암호화 패스워드 -->
<input type="hidden" name="ori_pw" value="<%= views.get(3)%>">
<!-- 사용자가 해당 게시물에 패스워드를 입력한 값 -->
패스워드 : <input type="password" name="npw">
</form>
<br><br>
<input type="button" value="글목록" onclick="notice_info(1)">
<input type="button" value="글수정" onclick="notice_info(2)">
<input type="button" value="글삭제" onclick="notice_info(3)">
</body>
<script>
function notice_info(p){
switch(p){
case 1:
location.href='./notice_list.do';
break;
case 2:
location.href='./notice_modify.do';
break;
case 3:
if(confirm("해당 게시물을 삭제시 복구되지 않습니다.")){
if(frm.npw.value==""){
alert("게시물 삭제시 패스워드를 입력하셔야 합니다.");
}else{
frm.submit();
}
}
break;
}
}
</script>
</html>
<%
}
%>
notice_delete.java (servlet)
게시물을 삭제하는 Controller
package notice;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.PreparedStatement;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//Database 게시물 삭제 처리 Controller
import shop.m_dbinfo;
import shop.m_md5;
public class notice_delete extends HttpServlet {
private static final long serialVersionUID = 1L;
Connection con = null;
PreparedStatement ps= null;
String sql = null;
int result = 0;
m_dbinfo db = new m_dbinfo(); //DB 정보
m_md5 md5 = new m_md5(); //MD5 암호화
PrintWriter pw = null;
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
String nidx = request.getParameter("nidx");
String ori_pw = request.getParameter("ori_pw");
String npw = request.getParameter("npw");
this.pw = response.getWriter();
try {
//사용자가 입력한 패스워드와 자동 증가값이 올바르게 (post전송)전달되지 않을 경우 작동 해제시킴
if(nidx.equals(null)||npw.equals(null)) {
this.pw.write("<script>"
+ "alert('올바른 접근이 아닙니다.');"
+ "history.go(-1);"
+ "</script>");
}else {
npw = md5.md5_code(npw); //사용자가 입력한 패스워드를 md5로 변환후 DB의 패스워드와 비교
if(npw.equals(ori_pw)) {
this.con = this.db.getConnection(); //DB연결
this.sql = "delete from notice where nidx=?";
this.ps = this.con.prepareStatement(this.sql);
this.ps.setString(1, nidx);
this.result = this.ps.executeUpdate();
System.out.println(this.result);
if(this.result > 0) {
this.pw.write("<script>"
+ "alert('게시물을 삭제하였습니다.');"
+ "location.href='./notice_list.do';"
+ "</script>");
}
}else {
this.pw.write("<script>"
+ "alert('패스워드가 틀립니다.');"
+ "history.go(-1);"
+ "</script>");
}
}
} catch (Exception e) {
this.pw.write("<script>"
+ "alert('Database삭제 오류 발생!!');"
+ "history.go(-1);"
+ "</script>");
}finally {
try {
this.ps.close();
this.con.close();
this.pw.close();
} catch (Exception e2) {
System.out.println("DB 접속에 따른 해제권한 오류 발생!!");
}
}
}
}