본문 바로가기
학원/servlet jsp

11.22일 (mvc패턴 News기사 게시판 생성 완성 파일)

by 쿠룽지 2023. 11. 23.
728x90
반응형

 

완성본 파일 업로드

 

유의해야할 점

이미지 첨부파일이 있기 때문에 register, modify에서 신경써야할게 조금 있음

 

 

전체 구성

 

 

src/main/java

kr.controller - Action / DispatcherServlet.java

kr.util - DBUtil / FileUtil / PagingUtil.java 제외

 

+파일 업로드 위해

webapp-upload(folder) 생성

 

 

더보기

혼자 다시 복습하면서 순서 정리해봤음..! (아닐수도)

Servlet + Action.interface + web.xml설정 + css + .jar 파일 다 있는 project 라는 가정 하에

 

1)  index.jsp 

2)  ListAction.java - list.jsp - ActionMap.properties (첫화면 목록)

3)  sql로 테이블 생성

4) DAO, VO 생성

5) 그외 create, modify, delete 도 2와 같은 순으로 생성

<글작성>

DAO 수정 - WriteFormAction.java - writeForm.jsp - ActionMap.properties

DAO 수정 -  WriteAction.java - write.jsp - ActionMap.properties

 

<글상세>

DAO 수정 - DetailAction.java - detail.jsp - ActionMap.properties

 

<글수정>

DAO 수정 - ModifyFormAction.java - modifyForm.jsp  - ActionMap.properties

DAO 수정 - ModifyAction.java - modify.jsp - ActionMap.properties

 

<글삭제>

DAO 수정 - DeleteFormAction.java - deleteForm.jsp - ActionMap.properties

DAO 수정 - DeleteAction.java - delete.jsp - ActionMap.properties

 


 

 

kr.news.vo

NewsVO.java

package kr.news.vo;

import java.sql.Date;

public class NewsVO {
	private int num;		//뉴스 번호
	private String title;	//뉴스 제목
	private String writer;	//작성자
	private String passwd;	//비밀번호
	private String email;	//이메일
	private String article; //기사 내용
	private String filename;//이미지명
	private Date reg_date;	//작성일
	
	//비밀번호 일치 여부 체크
	public boolean isCheckedPassword(String userPasswd) {
		if(passwd.equals(userPasswd)) {
			return true;
		}
		return false;
	}
	
	public int getNum() {
		return num;
	}
	public void setNum(int num) {
		this.num = num;
	}
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	public String getWriter() {
		return writer;
	}
	public void setWriter(String writer) {
		this.writer = writer;
	}
	public String getPasswd() {
		return passwd;
	}
	public void setPasswd(String passwd) {
		this.passwd = passwd;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public String getArticle() {
		return article;
	}
	public void setArticle(String article) {
		this.article = article;
	}
	public String getFilename() {
		return filename;
	}
	public void setFilename(String filename) {
		this.filename = filename;
	}
	public Date getReg_date() {
		return reg_date;
	}
	public void setReg_date(Date reg_date) {
		this.reg_date = reg_date;
	}
}

 

 

 

 

 

kr.news.dao

NewsDAO

package kr.news.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

import kr.news.vo.NewsVO;
import kr.util.DBUtil;

public class NewsDAO {
	//싱글턴 패턴
	private static NewsDAO instance = new NewsDAO();
	public static NewsDAO getInstance() {
		return instance;
	}
	private NewsDAO() {}
	
	
	//뉴스 등록
	public void registerNews(NewsVO vo)throws Exception{
		Connection conn = null;
		PreparedStatement pstmt = null;
		String sql = null;
		
		try {
			//커넥션 풀로부터 커넥션 할당
			conn = DBUtil.getConnection();
			//SQL문 작성
			sql="INSERT INTO dailynews (num,title,writer,passwd,email,article,filename) 
            values (dailynews_seq.nextval,?,?,?,?,?,?)";
			//PreparedStatement 객체 생성
			pstmt = conn.prepareStatement(sql);
			//?에 데이터 바인딩
			pstmt.setString(1, vo.getTitle());
			pstmt.setString(2, vo.getWriter());
			pstmt.setString(3, vo.getPasswd());
			pstmt.setString(4, vo.getEmail());
			pstmt.setString(5, vo.getArticle());
			pstmt.setString(6, vo.getFilename());
			//SQL문 실행
			pstmt.executeUpdate();
		}catch(Exception e) {
			throw new Exception(e);
		}finally {
			DBUtil.executeClose(null, pstmt, conn);
		}
	}

	//뉴스의 총 개수
	public int getCount()throws Exception{
		Connection conn = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		int count = 0;
		String sql = null;
		try {
			//커넥션풀로부터 커넥션을 할당
			conn = DBUtil.getConnection();
			//SQL문 작성
			sql = "SELECT COUNT(*) FROM dailynews";
			//PreparedStatement 객체 생성
			pstmt = conn.prepareStatement(sql);
			//SQL문을 실행
			rs = pstmt.executeQuery();
			if(rs.next()) {
				count = rs.getInt(1);
			}
		}catch(Exception e) {
			throw new Exception(e);
		}finally {
			//자원정리
			DBUtil.executeClose(rs, pstmt, conn);
		}
		return count;
	}
	
	//목록
	public List<NewsVO> getList(int startRow, int endRow)throws Exception{
		Connection conn = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		List<NewsVO> list = null;
		String sql = null;

		try {
			conn = DBUtil.getConnection();
			sql = "SELECT * FROM (SELECT a.*,rownum rnum "
					+ "FROM (SELECT * FROM dailynews ORDER BY "
					+ "num DESC)a) WHERE rnum>=? AND rnum<=?";
			pstmt = conn.prepareStatement(sql);
			//?에 데이터 바인딩
			pstmt.setInt(1, startRow);
			pstmt.setInt(2, endRow);
			rs = pstmt.executeQuery();

			list = new ArrayList<NewsVO>();
			while(rs.next()) {
				NewsVO vo = new NewsVO();

				vo.setNum(rs.getInt("num")); 
				vo.setTitle(rs.getString("title"));
				vo.setWriter(rs.getString("writer"));
				vo.setReg_date(rs.getDate("reg_date"));

				list.add(vo);
			}

		}catch(Exception e) {
			throw new Exception(e);
		}finally {
			DBUtil.executeClose(rs, pstmt, conn);
		}

		return list;
	}

	
	//뉴스 상세 정보
	public NewsVO getNews(int num)throws Exception{
		Connection conn = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		NewsVO newsVO = null;
		String sql = null;
		
		try {
			conn = DBUtil.getConnection();
			sql = "SELECT * FROM dailynews WHERE num=?";
			pstmt = conn.prepareStatement(sql);
			pstmt.setInt(1, num);
			rs = pstmt.executeQuery();
			if(rs.next()) {
				newsVO = new NewsVO();
				newsVO.setNum(rs.getInt("num"));
				newsVO.setTitle(rs.getString("title"));
				newsVO.setWriter(rs.getString("writer"));
				newsVO.setPasswd(rs.getString("passwd"));
				newsVO.setEmail(rs.getString("email"));
				newsVO.setArticle(rs.getString("article"));
				newsVO.setFilename(rs.getString("filename"));
				newsVO.setReg_date(rs.getDate("reg_date"));
			}
		}catch(Exception e) {
			throw new Exception(e);
		}finally {
			DBUtil.executeClose(rs, pstmt, conn);
		}
		return newsVO;
	}
	
	
	//뉴스 수정
	public void updateNews(NewsVO vo)throws Exception{
		Connection conn = null;
		PreparedStatement pstmt = null;
		String sql = null;
		String sub_sql = ""; // 상황에 따라 동적으로 처리하기 위해 sql과 분리해서 sub를 만듦	
		int cnt = 0;
		
		try {
			//커넥션풀로부터 커넥션 할당
			conn = DBUtil.getConnection();
			
			if(vo.getFilename()!=null) { //파일이 업로드 된 경우
				sub_sql += ",filename=?";
			}
			
			sql = "UPDATE dailynews SET title=?, writer=?, email=?, article=?"
					+ sub_sql + " WHERE num=?";
			//PreparedStatement 객체 생성
			pstmt = conn.prepareStatement(sql);
			
			//?에 데이터 바인딩 (물음표 번호가 달라지기 때문에 cnt로 자동으로 일치시켜줌)
			pstmt.setString(++cnt, vo.getTitle());
			pstmt.setString(++cnt, vo.getWriter());
			pstmt.setString(++cnt, vo.getEmail());
			pstmt.setString(++cnt, vo.getArticle());
			
			if(vo.getFilename()!=null) {
				pstmt.setString(++cnt, vo.getFilename());
			}
			pstmt.setInt(++cnt, vo.getNum());
			//SQL문 실행
			pstmt.executeUpdate();
		}catch(Exception e) {
			throw new Exception(e);
		}finally {
			DBUtil.executeClose(null, pstmt, conn);
		}
	}
	
	
	
	//뉴스 삭제
	public void deleteNews(int num)throws Exception{
		Connection conn = null;
		PreparedStatement pstmt = null;
		String sql = null;
		
		try {
			//커넥션풀로부터 커넥션 할당
			conn = DBUtil.getConnection();
			//SQL문 작성
			sql = "DELETE FROM dailynews WHERE num=?";
			//PreparedStatement 객체 생성
			pstmt = conn.prepareStatement(sql);
			//?에 데이터 바인딩
			pstmt.setInt(1, num);
			//SQL문 실행
			pstmt.executeUpdate();
		}catch(Exception e) {
			throw new Exception(e);
		}finally {
			DBUtil.executeClose(null, pstmt, conn);
		}
	}
	
}

DAO 에서는 filename도 그냥 String 처리함

 

  • registerNews(NewsVO vo) 뉴스등록 

  • getCount() 뉴스의 총 개수
    rs.next()가 true라면 count = rs.getInt(1)

  • getList(int startRow, int endRow) 목록
    데이터를 자바빈에 넣고 자바빈을 list하나로 묶은 후 return list;

  • getNews(int num) 뉴스 상세 정보

  • updateNews(NewsVO vo) 뉴스 수정
    + vo.getFilename()!=null 이라면 sub_sql += ",filename=?"
    filename이 null값이 아니라면 sub_sql에 filename=? 값 주기
    + vo.getFilename()!=null 이라면 pstmt.setString(++cnt, vo.getFilename()); 
    filename이 null값이 아니라면 sub_sql(++cnt)에 데이터 바인딩

  • deleteNews 뉴스 삭제

 


 

 

 

기사 보드 첫 화면 만들기 (목록)

 

kr.news.action

ListAction.java

package kr.news.action;

import java.util.List;

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

import kr.controller.Action;
import kr.news.dao.NewsDAO;
import kr.news.vo.NewsVO;
import kr.util.PagingUtil;

public class ListAction implements Action{

	@Override
	public String execute(HttpServletRequest request, HttpServletResponse response)
    												throws Exception {
		String pageNum = request.getParameter("pageNum");
		if(pageNum==null) pageNum = "1";
		
		NewsDAO dao = NewsDAO.getInstance();
		int count = dao.getCount();
		
		//페이지 처리
		PagingUtil page = new PagingUtil(Integer.parseInt(pageNum),
                count,20,10,"list.do");
		List<NewsVO> list = null;
		if(count>0) {
			list = dao.getList(page.getStartRow(), page.getEndRow());
		}
		
		request.setAttribute("count", count);
		request.setAttribute("list", list);
		request.setAttribute("page", page.getPage());
		
		//JSP 경로 반환
		return "/WEB-INF/views/list.jsp";
	}
}
  • pageNum==null 일 경우에 pageNum = "1"로 줌
    첫 화면은 당연히 null값이기 때문에 기본값으로 1을 줌

  • NewsDAO객체 생성 후 뉴스의 총 개수를 count로 가져옴(getCount() )

  • 페이지 처리 시 한 페이지에 20개/ 10페이지를 list.do에 보이게 함

 

 

 

views

list.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>
<html>
<head>
<meta charset="UTF-8">
<title>뉴스 목록</title>
<link rel="stylesheet" href="${pageContext.request.contextPath}/css/style.css" type="text/css">
</head>
<body>
<div class="page-main">
	<h2>뉴스 목록</h2>
	<div class="align-right">
		<input type="button" value="등록" onclick="location.href='registerForm.do'">
	</div>
	<c:if test="${count == 0}">
	<div class="result-display">
		표시할 게시물이 없습니다.
	</div>
	</c:if>
	<c:if test="${count > 0}">
	<table>
		<tr>
			<th>번호</th>
			<th>제목</th>
			<th>작성자</th>
			<th>등록일</th>
		</tr>
		<c:forEach var="news" items="${list}">
		<tr>
			<td>${news.num}</td>
			<td><a href="detail.do?num=${news.num}">${news.title}</a></td>
			<td>${news.writer}</td>
			<td class="align-center">${news.reg_date}</td>
		</tr>
		</c:forEach>
	</table>
	<div class="align-center">
		${page}
	</div>
	</c:if>
</div>
</body>
</html>
  • 등록 button > location.href='registerForm.do'

  • <c:forEach var="news" items="${list}"> news == 식별자

 

 

++ActionMap.properties에 기입 (글 맨 아래 첨부)

 

 


 

 

 

뉴스 등록

registerFormAction.java

package kr.news.action;

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

import kr.controller.Action;

public class RegisterFormAction implements Action{

	@Override
	public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception {

		//JSP 경로 반환
		return "/WEB-INF/views/registerForm.jsp";
	}
}

 

 

 

 

views

registerForm.jsp (뉴스 등록 화면)

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>뉴스 등록</title>
<link rel="stylesheet" href="${pageContext.request.contextPath}/css/style.css">
<script type="text/javascript">
window.onload=function(){
	let myForm = document.getElementById('register_form');
	myForm.onsubmit=function(){
		let items = document.querySelectorAll('.input-check');
		for(let i=0;i<items.length;i++){
			if(items[i].value.trim()==''){
				let label = document.querySelector('label[for="'+items[i].id+'"]');
				alert(label.textContent + ' 항목은 필수 입력');
				items[i].value = '';
				items[i].focus();
				return false;
			}
		}
	};
};
</script>
</head>
<body>
<div class="page-main">
	<h2>뉴스 등록</h2>
	<form id="register_form" action="register.do" method="post"
	                               enctype="multipart/form-data">
		<ul>
			<li>
				<label for="title">제목</label>
				<input type="text" name="title" id="title"
				  size="30" maxlength="50" class="input-check">
			</li>
			<li>
				<label for="writer">작성자</label>
				<input type="text" name="writer" id="writer"
				  size="10" maxlength="10" class="input-check">
			</li>
			<li>
				<label for="passwd">비밀번호</label>
				<input type="password" name="passwd" id="passwd"
				  size="12" maxlength="12" class="input-check">
			</li>
			<li>
				<label for="email">이메일</label>
				<input type="email" name="email" id="email"
				  size="30" maxlength="50" class="input-check">
			</li>
			<li>
				<label for="article">내용</label>
				<textarea rows="5" cols="40" name="article" 
				   id="article" class="input-check"></textarea>
			</li>
			<li>
				<label for="filename">이미지</label>
				<input type="file" name="filename" id="filename"
				             class="input-check"
				             accept="image/gif,image/png,image/jpeg">
			</li>
		</ul> 
		<div class="align-center">
			<input type="submit" value="등록">
			<input type="button" value="목록"
			                     onclick="location.href='list.do'">
		</div>                              
	</form>
</div>
</body>
</html>
  • class="input-check"를 줘서 querySelectorAll 입력 시 더 편하게 기입 가능

  • 이미지 첨부파일이 있기 때문에
    1) method="post"
    2) enctype="multipart/form-data"
    3) type="file" / accept="image/gif, image/png, image/jpeg" 기입

 

 

 

kr.news.action

RegisterAction.java (뉴스 등록)

package kr.news.action;

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

import com.oreilly.servlet.MultipartRequest;

import kr.controller.Action;
import kr.news.dao.NewsDAO;
import kr.news.vo.NewsVO;
import kr.util.FileUtil;

public class RegisterAction implements Action{

	@Override
	public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
		
		MultipartRequest multi = FileUtil.createFile(request);
		NewsVO vo = new NewsVO();
		vo.setTitle(multi.getParameter("title"));
		vo.setWriter(multi.getParameter("writer"));
		vo.setPasswd(multi.getParameter("passwd"));
		vo.setEmail(multi.getParameter("email"));
		vo.setArticle(multi.getParameter("article"));
		vo.setFilename(multi.getFilesystemName("filename"));
		
		NewsDAO dao = NewsDAO.getInstance();
		dao.registerNews(vo);
		
		return "/WEB-INF/views/register.jsp";
	}
}
  • MultipartRequest multi = FileUtil.createFile(request); 를 줬기 때문에 title, writer 등 모든 데이터를 request가 아닌 multi에서 불러옴

  • Filename은 multi.getFilesystemName으로 불러옴
    getParameter: 우리가 입력한 데이터 읽어오기
    getFilesystemName: 전송돼서 저장된 파일명 읽어오기

 

 

 

views

register.jsp (등록완료 화면)

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>뉴스 등록 완료</title>
<link rel="stylesheet" href="${pageContext.request.contextPath}/css/style.css">
</head>
<body>
<div class="page-main">
	<h2>뉴스 등록 완료</h2>
	<div class="result-display">
		<div class="align-center">
			뉴스 등록을 완료했습니다.<br>
			<button onclick="location.href='list.do'">목록</button>
		</div>
	</div>
</div>
</body>
</html>

 

 


 

 

상세정보 보기

kr.news.action

DetailAction.java

package kr.news.action;

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

import kr.controller.Action;
import kr.news.dao.NewsDAO;
import kr.news.vo.NewsVO;

public class DetailAction implements Action{

	@Override
	public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
		int num = Integer.parseInt(request.getParameter("num"));
		NewsDAO dao = NewsDAO.getInstance();
		NewsVO newsVO = dao.getNews(num);
		
		request.setAttribute("newsVO", newsVO);
		
		return "/WEB-INF/views/detail.jsp";
	}

}
  • request에서 num값을 읽어와서 그에 맞는 상세정보 detail.jsp 에 보임

  • request.setAttribute("newsVO", newsVO); 라고 request에 data set
    detail.jsp에는 따로 명시하는 부분이 없고 newsVO가 식별자가 됨

 

 

 

 

views

detail.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>    
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>뉴스 상세 정보</title>
<link rel="stylesheet" href="${pageContext.request.contextPath}/css/style.css"></head>
<body>
<div class="page-main">
	<h2>${newsVO.title}</h2>
	<p>
		뉴스번호 : ${newsVO.num}<br>
		작성자 : ${newsVO.writer}<br>
		이메일 : ${newsVO.email}<br>
		등록일 : ${newsVO.reg_date}
	</p>
	<hr size="1" width="100%" noshade="noshade">
	<div class="align-center">
		<img src="${pageContext.request.contextPath}/upload/${newsVO.filename}"
		                    style="max-width: 500px">
	</div>
	<p>
		${newsVO.article}
	</p>
	<hr size="1" width="100%" noshade="noshade">
	<div class="align-right">
		<input type="button" value="수정"
		       onclick="location.href='modifyForm.do?num=${newsVO.num}'">
		<input type="button" value="삭제"
		       onclick="location.href='deleteForm.do?num=${newsVO.num}'">
		<input type="button" value="목록"
		       onclick="location.href='list.do'">
	</div>
</div>
</body>
</html>
  • DetailAction에서 지정한 식별자로 값을 읽어옴 (newsVO)

  • img 파일을 불러올 때에 위치
    src="${pageContext.request.contextPath}/upload/${newsVO.filename}"

 


 

 

글 수정

kr.news.action

ModifyFormAction.java

package kr.news.action;

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

import kr.controller.Action;
import kr.news.dao.NewsDAO;
import kr.news.vo.NewsVO;

public class ModifyFormAction implements Action{

	@Override
	public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
		
		int num = Integer.parseInt(request.getParameter("num"));
		NewsDAO dao = NewsDAO.getInstance();
		NewsVO newsVO = dao.getNews(num);
		
		request.setAttribute("newsVO", newsVO);
		
		//JSP 경로 반환
		return "/WEB-INF/views/modifyForm.jsp";
	}

}
  • request의 뉴스 num을 불러와서 수정

  • request.setAttribute("newsVO", newsVO);
    뉴스 상세 정보 보기에서 그랬던 것처럼 (DetailAction - detail) 데이터 식별자를 미리 지정 (newsVO)

 

 

 

 

views

modifyForm (기사 수정 화면)

<%@ 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>
<html>
<head>
<meta charset="UTF-8">
<title>뉴스 등록</title>
<link rel="stylesheet" href="${pageContext.request.contextPath}/css/style.css" type="text/css">
<script type="text/javascript">
window.onload=function(){
	const myForm = document.getElementById('modify_form');
	myForm.onsubmit=function(){
		let items = document.querySelectorAll('.input-check');
		for(let i=0;i<items.length;i++){
			if(items[i].value.trim()==''){
				let label = document.querySelector('label[for="'+items[i].id+'"]');
				alert(label.textContent + ' 항목은 필수 입력');
				items[i].value = '';
				items[i].focus();
				return false;
			}	
		}
	};
};
</script>                     
</head>
<body>
<div class="page-main">
    <h2>뉴스 수정</h2>
	<form id="modify_form" action="modify.do" method="post" enctype="multipart/form-data">
		<input type="hidden" name="num" value="${newsVO.num}">
    	<ul>
    		<li>
    			<label for="title">제목</label>
    			<input type="text" name="title"
    			       id="title" size="30" value="${newsVO.title}"
    			       maxlength="50" class="input-check">
    		</li>
    		<li>
    			<label for="writer">작성자</label>
    			<input type="text" name="writer"
    			       id="writer" size="10" value="${newsVO.writer}"
    			       maxlength="10" class="input-check">
    		</li>
    		<li>
    			<label for="passwd">비밀번호</label>
    			<input type="password" name="passwd"
    			       id="passwd" size="12"
    			       maxlength="12" class="input-check">
    		</li>
    		<li>
    			<label for="email">이메일</label>
    			<input type="email" name="email"
    			       id="email" size="30" value="${newsVO.email}"
    			       maxlength="50" class="input-check">
    		</li>
    		<li>
    			<label for="article">내용</label>
    			<textarea rows="5" cols="40" name="article"
    			       id="article" class="input-check">${newsVO.article}</textarea>
    		</li>
    		<li>
    			<label for="filename">이미지</label>
    			<input type="file" name="filename" id="filename"
    			 accept="image/gif,image/png,image/jpeg">
    			<br>
    			<img src="${pageContext.request.contextPath}/upload/${newsVO.filename}"
		                    width="100" style="margin-left:100px;"> 
    		</li>
    	</ul> 
    	<div class="align-center">
    		<input type="submit" value="수정">
    		<input type="button" value="목록"
    		    onclick="location.href='list.do'">
    	</div>                           
	</form>
</div>
</body>
</html>
  • ModifyFormAction에서 지정한 식별자 사용

  • 수정 항목에 이미지도 있기 때문에
    1) method="post"
    2) enctype="multipart/form-data"
    3) type="file" accept="image/gif, image/png, image/jpeg"

  • num항목은 보이지 않게 가리고 전송해야하기 때문에 hidden type으로 설정

 

 

 

 

kr.news.action

ModifyAction.java (기사 수정)

 package kr.news.action;

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

import com.oreilly.servlet.MultipartRequest;

import kr.controller.Action;
import kr.news.dao.NewsDAO;
import kr.news.vo.NewsVO;
import kr.util.FileUtil;

public class ModifyAction implements Action{

   @Override
   public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
      request.setCharacterEncoding("utf-8");
      
      MultipartRequest multi = FileUtil.createFile(request);
      NewsVO vo = new NewsVO();
      vo.setNum(Integer.parseInt(multi.getParameter("num")));
      vo.setTitle(multi.getParameter("title"));
      vo.setWriter(multi.getParameter("writer"));
      vo.setPasswd(multi.getParameter("passwd"));
      vo.setEmail(multi.getParameter("email"));
      vo.setArticle(multi.getParameter("article"));
      vo.setFilename(multi.getFilesystemName("filename"));
      
      NewsDAO dao = NewsDAO.getInstance();
      //비밀번호 인증을 위해 한 건의 레코드를 자바빈에 담아서 반환
      NewsVO db_news = dao.getNews(vo.getNum());
      boolean check = false;
      if(db_news!=null) {
    	  //비밀번호 일치 여부 체크
         check = db_news.isCheckedPassword(vo.getPasswd());
      }
      if(check) {
         dao.updateNews(vo);
         if(vo.getFilename()!=null) {  // 전송되는 파일이 있을 경우에
        	//새 파일로 교체할 원래 파일 제거 (이전파일-db_news에 있음)
        	//utility class에 remove file도 있기 때문에 그걸 쓰면됨
        	 FileUtil.removeFile(request,db_news.getFilename());
         }
         //상세페이지로 이동하기 위해 글번호 저장
         request.setAttribute("num", vo.getNum());
      }else {
    	  if(vo.getFilename()!=null) {
    		  //인증 오류일 경우 업로드된 파일 삭제
    		  FileUtil.removeFile(request, vo.getFilename());
    	  }
      }
      
      //UI처리를 위해 check 저장
      request.setAttribute("check", check);
      
      //JSP 경로 반환
      return "/WEB-INF/views/modify.jsp";
   }

}
  • 수정이기 때문에 인코딩 처리 + RegisterAction과 동일하게 multi 사용

  • 조건 체크문
    1) db_news(수정한 내용) 이 null이 아닐 경우에 비밀번호 일치 여부 체크
    2) 비밀번호 일치여부 = true // dao.updateNews(vo);
    2-2) true Filename!=null인 경우 기존 파일 삭제 (새 파일로 교체 시 쓰레기 파일을 지우기 위함)
    FileUtil.removeFile(request, db_news.getFilename(); // 파일 삭제
    request.setAttribute("num", vo.getNum()); // 다시 상세 페이지로 돌아가기 위해 num 저장
    2-3) false Filename=null인 경우 업로드 된 파일 삭제
    3) UI 처리를 위해 check 저장

 

 

 

 

views

modify.jsp (수정 완료 화면)

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>    
<c:if test="${check}">
	<script>
		alert('뉴스 수정을 완료했습니다.');
		location.href='detail.do?num=${num}';
	</script>
</c:if>
<c:if test="${!check}">
	<script>
		alert('비밀번호 불일치');
		history.go(-1);
	</script>
</c:if>
  • check == true (ModifyAction 의 비밀번호 일치 여부)
    alert -> 자동으로 상세 페이지 이동

    check == false
    alert -> history.go(-1);

 


 

 

글 삭제

kr.news.action

DeleteFormAction.java 

package kr.news.action;

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

import kr.controller.Action;

public class DeleteFormAction implements Action{

	@Override
	public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
		// 전송된 데이터 받기
		int num = Integer.parseInt(request.getParameter("num"));
		request.setAttribute("num", num);
		
		//JSP 경로 반환
		return "/WEB-INF/views/deleteForm.jsp";
	}

}

 

 

 

 

 

 

views

deleteForm.jsp (삭제 화면/ 비밀번호 일치 체크)

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>기사 삭제</title>
<link rel="stylesheet" href="${pageContext.request.contextPath}/css/style.css">
<script type="text/javascript">
window.onload=function(){
	let myForm = document.getElementById('delete_form');
	myForm.onsubmit = function(){
		let passwd = document.getElementById('passwd');
		if(passwd.value.trim()==''){
			alert('비밀번호를 입력하세요');
			passwd.value='';
			passwd.focus();
			return false;
		}
	};
};
</script>
</head>
<body>
<div class="page-main">
	<h2>뉴스 삭제</h2>
	<form id="delete_form" action="delete.do" method="post">
		<input type="hidden" name="num" value="${num}">
		<ul>
			<li>
				<label for="passwd">비밀번호</label>
				<input type="password" name="passwd" id="passwd" size="12" maxlength="12">
			</li>
		</ul>
		<div class="align-center">
			<input type="submit" value="글 삭제">
			<input type="button" value="목록" onclick="location.href='list.do'">
		</div>
	</form>
</div>
</body>
</html>
  • deleteForm을 포함한 모든 폼의 유효성 검사는 trim()밖에 입력하지 않음
    불일치하거나 등의 조건은 다 model class에서 시행

  • num값을 hidden으로 전송

 

 

 

 

 

kr.news.action

DeleteAction.jsp (삭제)

package kr.news.action;

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

import kr.controller.Action;
import kr.news.dao.NewsDAO;
import kr.news.vo.NewsVO;
import kr.util.FileUtil;

public class DeleteAction implements Action{

	@Override
	public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
		// 전송된 데이터 인코딩 처리
		request.setCharacterEncoding("utf-8");
		
		//전송된 데이터 반환
		int num = Integer.parseInt(request.getParameter("num"));
		String passwd = request.getParameter("passwd");
		
		NewsDAO dao = NewsDAO.getInstance();
		NewsVO db_news = dao.getNews(num);
		boolean check = false;
		
		if(db_news!=null) {
			//비밀번호 일치 여부 체크
			check=db_news.isCheckedPassword(passwd);
		}
		if(check) {
			//글 삭제
			dao.deleteNews(num);
			//쓰레기 파일 삭제 (쌓이는걸 방지하기 위함)
			FileUtil.removeFile(request, db_news.getFilename());
		}
		//UI처리를 위해 check 저장
		request.setAttribute("check", check);
		//JSP 경로 반환
		return "/WEB-INF/views/delete.jsp";
	}

}
  • db_news = getNews(뉴스 상세정보)
    if db_news!=null > 비밀번호 일치 여부 체크

 

 

 

 

 

views

delete.jsp (삭제 완료 화면)

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:if test="${check}">
	<script>
		alert('뉴스 삭제를 완료했습니다.');
		location.href='list.do';
	</script>
</c:if>
<c:if test="${!check}">
	<script>
		alert('비밀번호 불일치');
		history.go(-1);
	</script>
</c:if>

 


 

webapp

ActionMap.properties (꼭 처리해야함..!!!!)

# key       value
# 요청URL    모델클래스
/list.do=kr.news.action.ListAction
/registerForm.do=kr.news.action.RegisterFormAction
/register.do=kr.news.action.RegisterAction
/detail.do=kr.news.action.DetailAction
/modifyForm.do=kr.news.action.ModifyFormAction
/modify.do=kr.news.action.ModifyAction
/deleteForm.do=kr.news.action.DeleteFormAction
/delete.do=kr.news.action.DeleteAction

 

728x90
반응형