회원제 게시판(03), 파일첨부 21. 03. 22.
회원제 게시판(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 © 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>