JSP & Servlet

회원제 게시판(03), 파일첨부 21. 03. 22.

Levinni 2021. 3. 22. 13:46

회원제 게시판(03)

 

(수정) header.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 lang="ko">
<head>
	<meta charset="UTF-8">
	<title>2021. 3. 17. 오후 12:44:09</title>
	<link rel="stylesheet" href="/member_board/assets/css/common.css">
	<script src="//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
</head>
<body>
	<%
		String idsave = null;
		for(Cookie cookie : request.getCookies()) {
			if(cookie.getName().equals("idsave")) {
				idsave = cookie.getValue();
			}

		}
	%>
	<div class="wrapper">
	<header class="header">
		<h1>사이트 이름 : 제목</h1>
		<form method="post" action="<%=request.getContextPath()%>/login">
		<ul>
		<c:if test="${empty member}">
			<li><label>아이디 <input type="text" name="id" value="${cookie.idsave.value}"></label></li>
			<li><label>비밀번호 <input type="password" name="pw"></label></li>
			<li><button>로그인</button></li>
			<li>
				<label>아이디 저장
					<input type="checkbox" name="idsave" ${empty cookie.idsave.value ? '' : 'checked'}>
				</label>
			</li>
		</c:if>
		<c:if test="${!empty member}">
			<li>${member.name}님 환영합니다. <button formaction="<%=request.getContextPath()%>/logout">로그아웃</button></li>
		</c:if>
		</ul>
		</form>
		<script>
		 $("<input>").attr({type:"hidden", name:"uri", value:location.pathname+location.search}).appendTo("form");
		</script>
	</header>
		<nav class="gnb">
		
			<ul>
				<li><a href="<%=request.getContextPath() %>/board/list?category=1">자유게시판</a></li>
				<li><a href="<%=request.getContextPath() %>/board/list?category=2">공지사항</a></li>
				<li><a href="<%=request.getContextPath() %>/board/list?category=3">qna</a></li>
				<li><a href="<%=request.getContextPath() %>/board/list?category=4">자료실</a></li>
			</ul>
		</nav>

 

- gnb 만듦.

css 적용이 바로 안 되면,
1. 크롬f12 network - disable cache 체크하기
2. 서버까진 내릴 필요 없고 .jsp파일에 엔터 쳐서 저장하면 다시 컴파일 함. -> 적용됨.
3. project - clean

- root 경로로 들어가서 board라는 위치 상대경로로 들어가기 위해 gnb의 각 li에도 <%=request.getContextPath() %>를 해 줌.

 

※실행 시 톰캣 서버 시작 실패는 여러 이유가 있는데 오늘 경우는 개인 프로젝트 서블릿 @WebServlet의 주소("/")가 겹쳐서 그랬음. 수업했던 곳 어노테이션을 주석처리 해두면 됨.

 

 

(수정) BoardList.java

package board.controller;

import java.io.IOException;
import java.util.List;
import java.util.Objects;

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 board.service.BoardService;
import board.service.BoardServiceImpl;
import board.vo.Board;
import util.Common;

@WebServlet("/board/list")
public class BoardList extends HttpServlet{

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		BoardService service = new BoardServiceImpl();
		
		Integer category = Common.getDefaultValue(req.getParameter("category"));
//		System.out.println(category); // 널값인지 확인 
		List<Board>list = service.list(category);
		req.setAttribute("list", list);
		req.getRequestDispatcher("../WEB-INF/jsp/board/list.jsp").forward(req, resp);
	}
}

 

- 자유게시판 목록만 보이던 걸 service.list(category);로 바꿈.

- Common.getDefaultValue(req.getParameter("category")); 를 통해 null 처리 완료 됨.

- 코드가 Common클래스로 인해 간단해짐.

 

 

Common.java

package util;

import java.io.IOException;
import java.util.Objects;

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

import board.service.BoardService;
import board.service.BoardServiceImpl;
import board.vo.Board;
import member.vo.Member;

public class Common {
	public static int getDefaultValue(String source, int fixValue, int realValue) {
		int ret;
		int category;
		if(Objects.isNull(source) || source.equals("")) {
			ret = fixValue;
		}
		else {
			ret = Integer.valueOf(source);
		}
		return ret;
	}
	public static int getDefaultValue(String source) {
		return  getDefaultValue(source, 1, 1);
	}
	
	public static Member getSessionMember(HttpServletRequest req) {
		Object memberObj = req.getSession().getAttribute("member");
		return (Member) memberObj == null ? null : (Member) memberObj;
	}
	
	public static boolean isEmpty(String str) {
		return str == null || str.equals("");
	}
	
	public static Board getThisContent(HttpServletRequest req) {
		if(isEmpty(req.getParameter("boardno"))) {
			return null;
		}
		int boardno = Integer.parseInt(req.getParameter("boardno"));
		BoardService service = new BoardServiceImpl();
		
		Board board = service.findBy(boardno);
		System.out.println(board);
		Member member = getSessionMember(req);
		System.out.println(member);
		if(member == null || !board.getUserid().equals(member.getUserid())) {
			return null;
		}
		else return board;
	}
}

- 여러 군데에서 반복적으로 사용되는 코드들을 클래스로 묶어 둠.

 

 

list.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<jsp:include page="../../../template/header.jsp"/>
	<div class="btns">
		<c:if test="${not empty member}">
		<a href="write?category=${param.category}"><button>글쓰기</button></a>
		</c:if>
	</div>
	<table>
		<tr>
			<th>글번호</th>
			<th>제목</th>
			<th>작성자</th>
			<th>작성일</th>
			<th>조회수</th>
		</tr>
		<c:forEach items="${list}" var="board">
		<tr>
			<td>${board.boardno}</td>
			<td><a href="detail?boardno=${board.boardno}"><c:out value="${board.title}"/> </a></td>
			<td>${board.userid}</td>
			<td>${board.regdate}</td>
			<td>${board.hitcount}</td>
		</tr>
		</c:forEach>
	</table>
<jsp:include page="../../../template/footer.jsp"/>

 

- 글쓰기 버튼

 

 

write.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<jsp:include page="../../../template/header.jsp"/>
	<form method="post">
	<table>
		<tr>
			<th>제목</th>
			<td colspan="5"><input type="text" name="title" value ="${board.title}"></td>
		</tr>
		<tr>
			<th>글내용</th>
			<td colspan="5">
				<textarea rows="10" cols="30" name="content">${board.content}></textarea>
			</td>
		</tr>
	</table>
	<div class="btns">
		<button>글쓰기</button>
		<button type="button" class="do-prev">작성취소</button>
	</div>
	<input type="hidden" name="boardno" value="${param.boardno}">
	<input type="hidden" name="category" value="${param.category}">
	<%-- <input type="hidden" name="userid" value="${member.userid}"> --%>
	</form>
<jsp:include page="../../../template/footer.jsp"/>

- <input hidden>은 클라이언트가 서버에 전송할 값을 받기 위함인데, 딱히 화면에는 출력할 필요가 없어서 hidden한 것.

 

 

write.java

package board.controller;

import java.io.IOException;
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 board.service.BoardService;
import board.service.BoardServiceImpl;
import board.vo.Board;
import member.vo.Member;
import util.Common;

@WebServlet("/board/write")
public class Write extends HttpServlet{

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		req.setAttribute("title", "글쓰기");
		req.getRequestDispatcher("../WEB-INF/jsp/board/write.jsp").forward(req, resp);
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// 타이틀, 콘텐트, 카테고리, 작성자, 
		String title = req.getParameter("title");
//		System.out.println(title);
		String content = req.getParameter("content");
//		System.out.println(content);
		int category = Common.getDefaultValue(req.getParameter("category"));
		
		if(Common.getSessionMember(req) == null) { // 비로그인 상태일 때
			resp.sendRedirect("index");
			return;
		}
		// 성공
		String userid = Common.getSessionMember(req).getUserid();
		
		Board board = new Board(title, content, userid, null, category);
		System.out.println(board);
		BoardService service = new BoardServiceImpl();
		service.write(board);
		resp.sendRedirect("list?category=" + category);
	}
}

 

- 변수들 나오면 다 로그 찍어봐야 함!

 

 

list.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<jsp:include page="../../../template/header.jsp"/>
	<div class="btns">
		<c:if test="${not empty member}">
		<a href="write?category=${param.category}"><button>글쓰기</button></a>
		</c:if>
	</div>
	<table>
		<tr>
			<th>글번호</th>
			<th>제목</th>
			<th>작성자</th>
			<th>작성일</th>
			<th>조회수</th>
		</tr>
		<c:forEach items="${list}" var="board">
		<tr>
			<td>${board.boardno}</td>
			<td><a href="detail?boardno=${board.boardno}"><c:out value="${board.title}"/> </a></td>
			<td>${board.userid}</td>
			<td>${board.regdate}</td>
			<td>${board.hitcount}</td>
		</tr>
		</c:forEach>
	</table>
<jsp:include page="../../../template/footer.jsp"/>

 

- 로그인 된 상태에서만 글쓰기 버튼 보이도록. <c:if test="${not empty member}">

- <c:out> : 에스케이핑을 할 수 있음. <,>같은 걸 &코드로 바꿔줌. 제목에 스크립트 무한 alert() 거는 일 방지. (XSS)

 

 

detail.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<jsp:include page="../../../template/header.jsp"/>
	<table>
		<tr>
			<th>제목</th>
			<td colspan="5">${board.title}</td>
		</tr>
		<tr>
			<th>작성자</th>
			<td>${board.userid}</td>
			<th>작성일</th>
			<td>${board.regdate}</td>
			<th>조회수</th>
			<td>${board.hitcount}</td>
		</tr>
		<tr>
			<td colspan="6">
				${board.content}
			</td>
		</tr>
	</table>
	<div class="btns">
	<c:if test="${not empty member and member.userid eq board.userid}">
		<a href="modify?boardno=${param.boardno}"><button>글수정</button></a>
		<a href="remove?boardno=${param.boardno}"><button>글삭제</button></a>
	</c:if>
		<button class="do-prev">목록으로</button>
	</div>
<jsp:include page="../../../template/footer.jsp"/>

- 로그인이 되어 있고, 로그인 된 userid랑 글 쓴 userid가 같을 때만 특정 글에서 수정, 삭제 버튼이 보임.

 

 

(수정) footer.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
	<footer>
		<p>사이트 개요</p>
		<p>copyright &copy; 2021</p>
		<address>충남 천안시 동남구</address>
	</footer>
	</div>
	<script>
		$(".do-prev").click(function() {
			confirm("정말 뒤로 가시겠습니까?") ? history.back() : "";
		});
	</script>
</body>
</html>

- 이전 페이지로 가는 스크립트 함수는 여러 곳에서 쓰여서 footer에 박아 둠.

 

 

Modify.java

package board.controller;

import java.io.IOException;
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 board.service.BoardService;
import board.service.BoardServiceImpl;
import board.vo.Board;
import member.vo.Member;
import util.Common;

@WebServlet("/board/modify")
public class Modify extends HttpServlet{

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		if(Common.getSessionMember(req) == null || Common.isEmpty(req.getParameter("boardno"))) {
			resp.sendRedirect(req.getContextPath() + "/index");
			return;
		}
		BoardService service = new BoardServiceImpl();
		Board board = service.findBy(Integer.parseInt(req.getParameter("boardno"))); // 보류
		req.setAttribute("board", board);
		req.setAttribute("title", "글수정");
		
		req.getRequestDispatcher("../WEB-INF/jsp/board/write.jsp").forward(req, resp);
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// 타이틀, 콘텐트, 카테고리, 작성자, 
		String title = req.getParameter("title");
		String content = req.getParameter("content");
		int boardno = Common.getDefaultValue(req.getParameter("boardno"));
				
		if(Common.getSessionMember(req) == null) {
			resp.sendRedirect(req.getContextPath() + "/index");
			return;
		}		
		
//		String userid = Common.getSessionMember(req).getUserid();
		
		Board board = new Board(boardno, title, content);
		System.out.println(board);
		BoardService service = new BoardServiceImpl();
		service.modify(board);
		resp.sendRedirect("list?boardno=" + boardno);
	}
}

 

 

Remove.java

package board.controller;

import java.io.IOException;
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 board.service.BoardService;
import board.service.BoardServiceImpl;
import board.vo.Board;
import member.vo.Member;
import util.Common;

@WebServlet("/board/remove")
public class Remove extends HttpServlet{

	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// 로그인 된사용자의 아이디와 해당 글의 작성자 아이디가 일치해야 함.
		Board board = Common.getThisContent(req);
		if(board == null) {
			resp.sendRedirect(req.getContextPath() + "/index");
			return;
		}
		BoardService service = new BoardServiceImpl();
		int category = board.getCategory();
		service.remove(board.getBoardno());
		
		resp.sendRedirect("list?category=" + category);
	}
}

 

실행 테스트할 때 세션 확인 잘 하기!

 

 

파일첨부

cos 라이브러리 이용

 

uploadSample.jsp

<%@page import="java.util.Date"%>
<%@page import="java.text.SimpleDateFormat"%>
<%@page import="java.io.File"%>
<%@page import="com.oreilly.servlet.multipart.DefaultFileRenamePolicy"%>
<%@page import="com.oreilly.servlet.MultipartRequest"%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="ko">
<head>
	<meta charset="UTF-8">
	<title>2021. 3. 22. 오후 3:33:04</title>
	<script src="//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
</head>
<body>
	<form method="post" enctype="multipart/form-data">
		<input type="file" name="file1">
		<input type="file" name="file2">
		<input type="file" name="file3">
		<button>전송</button>
	</form>	
	
	<%
		if(request.getMethod().equals("POST")) {
			String uploadPath = request.getRealPath("/upload");
			String today = new SimpleDateFormat("yyMMdd").format(new Date());
			uploadPath = uploadPath + File.separator + today;
			File file = new File(uploadPath);
			if(!file.exists()){
				file.mkdirs();
			}
			// /upload/210322/
			int maxSize = 10 * 1024 * 1024;
			MultipartRequest multi = new MultipartRequest(request, uploadPath, maxSize, "utf-8", new DefaultFileRenamePolicy());
		}
	%>
</body>
</html>