서버 프로그램 구현 - 개인 프로젝트
회원제 게시판
첨부파일, 페이지네이션, 게시판별 카테고리
인증(이메일), 댓글(비동기), 회원기능 구현
메세지 처리 페이지
> 로그인 실패 및 성공시 메시지
배피 프로그램 처리
Oauth
외부 RestAPI 연동(지도, 좌표)
점점 머리에 한계가 온다 이야아아아아아아아아아아앙
utils > FileDownload.java
package utils;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/download")
public class FileDownloader extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String origin = req.getParameter("origin");
String uuid = req.getParameter("uuid");
String path = req.getParameter("path");
String saveDir = "D:\\upload";
File file = new File(new File(saveDir, path), uuid);
String mime = getServletContext().getMimeType(file.toString());
if(mime == null) {
mime = "application/octet-stream";
}
String fileName = new String(origin.getBytes("utf-8"), "iso-8859-1"); // utf-8을 iso-8859-1로 재해석한 것
resp.setContentType(mime);
resp.setHeader("Content-Disposition", "attachment; filename=" + fileName);
FileInputStream fis = new FileInputStream(file);
OutputStream os = resp.getOutputStream();
int b;
byte[] bytes = new byte[8192];
while((b = fis.read(bytes, 0, bytes.length)) != -1) {
os.write(bytes, 0, b);
}
fis.close();
os.close();
}
}
get.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html lang="ko">
<head>
<%@ include file="../common/head.jsp" %>
</head>
<body class="sb-nav-fixed">
<%@ include file="../common/nav.jsp" %>
<main class="mt-5 pt-5">
<div class="container-fluid px-4">
<h1 class="mt-4">Board</h1>
<h2>${board.attachs}</h2>
<div class="card mb-4">
<div class="card-body">
<form>
<div class="mb-3 mt-3">
<label for="bno" class="form-label"><i class="fas fa-list-ol"></i> bno</label>
<input type="text" class="form-control" id="bno" name="bno" value="${board.bno}" disabled>
</div>
<div class="mb-3">
<label for="title" class="form-label"><i class="fab fa-battle-net"></i> title</label>
<input type="text" class="form-control" id="title" name="title" value="${board.title}" disabled>
</div>
<div class="mb-3">
<label for="content" class="form-label"><i class="fab fa-battle-net"></i> content</label>
<textarea class="form-control" id="content" name="content" disabled>${board.content}</textarea>
</div>
<div class="mb-3">
<label for="regDate" class="form-label"><i class="fas fa-calendar"></i> regDate</label>
<input type="text" class="form-control" id="regDate" name="regDate" value="${board.regDate}" disabled>
</div>
<div class="mb-3">
<label for="writer" class="form-label"><i class="fas fa-feather-alt"></i> writer</label>
<input type="text" class="form-control" id="writer" name="writer" value="${board.writer}" disabled>
</div>
<div class="mb-3">
<label for="attach" class="form-label"><i class="fas fa-file-archive"></i> attach</label>
<ul class="list-group">
<c:forEach items="${board.attachs}" var="attach">
<li class="list-group-item list-group-item-info"><i class="fas fa-download"></i> <a href="${pageContext.request.contextPath}/download${attach.params}">${attach.origin}</a></li>
</c:forEach>
</ul>
</div>
<a href="list${cri.params2}" class="btn btn-outline-secondary">list</a>
<c:if test="${not empty member && member.id == board.writer}">
<a href="modify${cri.params2}&bno=${board.bno}" class="btn btn-outline-warning">modify</a>
<a href="remove${cri.params2}&bno=${board.bno}" class="btn btn-outline-danger" onclick="return confirm('삭제하시겠습니까?')">remove</a>
</c:if>
</form>
</div>
</div>
</div>
</main>
<%@ include file="../common/footer.jsp" %>
</body>
</html>
domain > Board.java
package domain;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data @NoArgsConstructor @AllArgsConstructor
public class Board {
// int(기본형), Integer(참조형) : null 처리 가능여부
private Long bno ; // PK
private String title;
private String content;
private int hitcount; // 0
private String regDate;
private int category;
private String writer; // FK
// 아이디, 조회수, 작성시각
private List<Attach> attachs = new ArrayList<>();
public Board(String title, String content, String writer) {
this.title = title;
this.content = content;
this.writer = writer;
}
public Board(String title, String content, String writer, int category) {
this.title = title;
this.content = content;
this.writer = writer;
this.category = category;
}
public Board(Long bno, String title, String content, int category) {
super();
this.bno = bno;
this.title = title;
this.content = content;
this.category = category;
}
public Board(Long bno, String title, String content, int hitcount, String regDate, int category, String writer) {
super();
this.bno = bno;
this.title = title;
this.content = content;
this.hitcount = hitcount;
this.regDate = regDate;
this.category = category;
this.writer = writer;
}
}
domain > Attach.java
package domain;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data @NoArgsConstructor @AllArgsConstructor
public class Attach {
private String uuid;
private String origin;
private String path;
private boolean image;
private int ord;
private Long bno;
public String getParams() {
return "?uuid=" + uuid + "&path=" + path + "&origin=" + origin;
}
}
AttachDao.java
package dao;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jdt.internal.compiler.batch.Main;
import domain.Attach;
import domain.Board;
import domain.Criteria;
import utils.DBConn;
public class AttachDao {
private static AttachDao attachDao = new AttachDao();
public static AttachDao getInstance() {
return attachDao;
}
private AttachDao() {
}
public List<Attach> list(Long bno) {
List<Attach> list = new ArrayList<>();
try {
Connection conn = DBConn.getConnection();
// 문장 생성
String sql = "SELECT /*+ INDEX(TBL_ATTACH IDX_ATTACH_UUID_BNO) */ * FROM TBL_ATTACH WHERE BNO = ?";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setLong(1, bno);
// 결과집합 생성
ResultSet rs = pstmt.executeQuery();
// 결과집합 순회 후 데이터 바인딩
while(rs.next()) {
int idx = 1;
Attach attach = new Attach(
rs.getString(idx++),
rs.getString(idx++),
rs.getString(idx++),
rs.getBoolean(idx++),
rs.getInt(idx++),
bno);
list.add(attach);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return list;
}
public void insert(Attach attach) {
try {
Connection conn = DBConn.getConnection();
// 문장 생성
String sql = "INSERT INTO TBL_Attach "
+ "VALUES (?, ?, ?, ?, ?, ?)";
PreparedStatement pstmt = conn.prepareStatement(sql);
// 파라미터 바인딩
int idx = 1;
pstmt.setString(idx++, attach.getUuid());
pstmt.setString(idx++, attach.getOrigin());
pstmt.setString(idx++, attach.getPath());
pstmt.setBoolean(idx++, attach.isImage());
pstmt.setInt(idx++, attach.getOrd());
pstmt.setLong(idx++, attach.getBno());
// 문장 실행(반영)
pstmt.executeUpdate();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void modify(Board board) {
try {
Connection conn = DBConn.getConnection();
// 문장 생성
String sql = "UPDATE TBL_BOARD SET\r\n" +
"TITLE = ?,\r\n" +
"CONTENT = ?,\r\n" +
"REGDATE = SYSDATE\r\n" +
"WHERE BNO = ?";
PreparedStatement pstmt = conn.prepareStatement(sql);
// 파라미터 바인딩
pstmt.setString(1, board.getTitle());
pstmt.setString(2, board.getContent());
pstmt.setLong(3, board.getBno());
// 문장 실행(반영)
pstmt.executeUpdate();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void remove(Long bno) {
try {
Connection conn = DBConn.getConnection();
// 문장 생성
String sql = "DELETE TBL_BOARD\r\n" +
"WHERE BNO = ?";
PreparedStatement pstmt = conn.prepareStatement(sql);
// 파라미터 바인딩
pstmt.setLong(1, bno);
// 문장 실행(반영)
pstmt.executeUpdate();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public Board get(Long bno) {
Board board = null;
try {
Connection conn = DBConn.getConnection();
String sql = "UPDATE TBL_BOARD SET\r\n" +
"HITCOUNT = HITCOUNT + 1\r\n" +
"WHERE BNO = ?";
PreparedStatement pstmt = conn.prepareStatement(sql);
// 파라미터 바인딩
pstmt.setLong(1, bno);
// 문장 실행(반영)
pstmt.executeUpdate();
// 문장 생성
sql = "SELECT BNO, TITLE, CONTENT, HITCOUNT, \r\n" +
"CASE\r\n" +
" WHEN SYSDATE - REGDATE > 1 THEN TO_CHAR(REGDATE, 'YY/MM/DD')\r\n" +
" ELSE TO_CHAR(REGDATE, 'HH24:MI:SS')\r\n" +
"END REGDATE,\r\n" +
"CATEGORY, WRITER FROM TBL_BOARD WHERE BNO = ?";
pstmt = conn.prepareStatement(sql);
pstmt.setLong(1, bno);
// 결과집합 생성
ResultSet rs = pstmt.executeQuery();
// 결과집합 순회 후 데이터 바인딩
while(rs.next()) {
int idx = 1;
board = new Board(rs.getLong(idx++), rs.getString(idx++), rs.getString(idx++),
rs.getInt(idx++), rs.getString(idx++), rs.getInt(idx++),rs.getString(idx++));
}
} catch (Exception e) {
e.printStackTrace();
}
return board;
}
public int count(Criteria cri) {
int count = 0;
try {
Connection conn = DBConn.getConnection();
// 문장 생성
String sql = "SELECT COUNT(BNO) FROM TBL_BOARD WHERE CATEGORY = ?";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, cri.getCategory());
// 결과집합 생성
ResultSet rs = pstmt.executeQuery();
// 결과집합 순회 후 데이터 바인딩
if(rs.next()) {
count = rs.getInt(1 );
}
} catch (Exception e) {
e.printStackTrace();
}
return count;
}
}
controller.board > Register.java
package controller.board;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.UUID;
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 org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import domain.Attach;
import domain.Board;
import domain.Criteria;
import domain.Member;
import javafx.scene.input.Mnemonic;
import service.BoardService;
import service.MemberService;
@WebServlet("/board/register")
public class Register extends HttpServlet{
private BoardService boardService = BoardService.getInstance();
private MemberService memberService = MemberService.getInstance();
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 세션 고정값 지정
req.getSession().setAttribute("member", memberService.login(new Member("javaman", "5678", null)));
if(req.getSession().getAttribute("member") == null) {
resp.sendRedirect(req.getContextPath() + "/member/login");
return;
}
Criteria criteria = new Criteria();
if(req.getParameter("pageNum") != null) {
criteria.setPageNum(Integer.parseInt(req.getParameter("pageNum")));
}
if(req.getParameter("amount") != null) {
criteria.setAmount(Integer.parseInt(req.getParameter("amount")));
}
if(req.getParameter("category") != null) {
criteria.setCategory(Integer.parseInt(req.getParameter("category")));
}
req.setAttribute("cri", criteria);
req.getRequestDispatcher("/WEB-INF/jsp/board/register.jsp").forward(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Criteria criteria = new Criteria();
Board board = upload(req, criteria);
System.out.println(board);
boardService.register(board);
resp.sendRedirect("list" + criteria.getParams2());
}
private Board upload(HttpServletRequest req, Criteria cri) {
Board board = new Board();
String saveDir = "D:\\upload";
int size = 10 * 1024 * 1024;
File currentDir = new File(saveDir);
DiskFileItemFactory factory = new DiskFileItemFactory();
factory.setRepository(currentDir);
factory.setSizeThreshold(size);
ServletFileUpload upload = new ServletFileUpload(factory);
try {
List<FileItem> items = upload.parseRequest(req);
for(FileItem fi : items) {
if(fi.isFormField()) {
if(fi.getFieldName().equals("title")) {
board.setTitle(fi.getString("utf-8"));
}
if(fi.getFieldName().equals("content")) {
board.setContent(fi.getString("utf-8"));
}
if(fi.getFieldName().equals("writer")) {
board.setWriter(fi.getString("utf-8"));
}
if(fi.getFieldName().equals("amount")) {
cri.setAmount(Integer.parseInt(fi.getString("utf-8")));
}
if(fi.getFieldName().equals("category")) {
board.setCategory(cri.getCategory());;
}
}
else {
if(fi.getSize() == 0) {
continue;
}
String origin = fi.getName();
int idxDot = origin.lastIndexOf(".");
String ext = "";
if(idxDot != -1) {
ext = origin.substring(idxDot);
}
UUID uuid = UUID.randomUUID();
String name = uuid + ext;
File upPath = new File(currentDir + "\\" + getTodayStr());
if(!upPath.exists()) {
upPath.mkdirs();
}
fi.write(new File(upPath, name));
Attach attach = new Attach(name, origin, getTodayStr(), fi.getContentType().contains("image"), 1, null);
board.getAttachs().add(attach);
}
}
} catch (Exception e){
// TODO: handle exception
e.printStackTrace();
}
return board;
}
private String getTodayStr() {
return new SimpleDateFormat("yyyy/MM/dd").format(System.currentTimeMillis());
}
}
register.jsp
<input type = "hidden" name = "amount" value = "${cri.amount}">
<input type = "hidden" name = "category" value = "${cri.category}">
<input type = "hidden" name = "pageNum" value = "${cri.pageNum}">
<a href="list" class="btn btn-outline-secondary">list</a>
<button class="btn btn-outline-primary">register</button>
Modify.java
package controller.board;
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 domain.Board;
import domain.Criteria;
import domain.Member;
import service.BoardService;
@WebServlet("/board/modify")
public class Modify extends HttpServlet{
private BoardService boardService = BoardService.getInstance();
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Long bno = Long.parseLong(req.getParameter("bno"));
Member member = (Member) req.getSession().getAttribute("member");
if(member == null || !member.getId().equals(boardService.get(bno).getWriter())) {
resp.sendRedirect(req.getContextPath() + "/board/list");
return;
}
Criteria criteria = new Criteria();
if(req.getParameter("pageNum") != null) {
criteria.setPageNum(Integer.parseInt(req.getParameter("pageNum")));
}
if(req.getParameter("amount") != null) {
criteria.setAmount(Integer.parseInt(req.getParameter("amount")));
}
if(req.getParameter("category") != null) {
criteria.setCategory(Integer.parseInt(req.getParameter("category")));
}
req.setAttribute("cri", criteria);
req.setAttribute("board", boardService.get(bno));
req.getRequestDispatcher("/WEB-INF/jsp/board/modify.jsp").forward(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
String title = req.getParameter("title");
String content = req.getParameter("content");
String bno = req.getParameter("bno");
Criteria criteria = new Criteria();
criteria.setPageNum(Integer.parseInt(req.getParameter("pageNum")));
criteria.setAmount(Integer.parseInt(req.getParameter("amount")));
criteria.setCategory(Integer.parseInt(req.getParameter("category")));
Board board = new Board(Long.parseLong(bno), title, content, criteria.getCategory());
boardService.modify(board);
resp.sendRedirect("list" + criteria.getParams2());
}
}
SQL
-- TBL_ATTACH 첨부파일
-- 물리적 파일이름 문자50글자, 원본 파일 이름 문자 500, 경로, 글번호 숫자, 이미지 여부 불린(문자) 1
DROP TABLE TBL_ATTACH;
CREATE TABLE TBL_ATTACH(
UUID VARCHAR2(50) CONSTRAINT PK_ATTACH PRIMARY KEY,
ORIGIN VARCHAR2(500) NOT NULL,
PATH CHAR(10),
IMAGE CHAR(1) DEFAULT '0',
ORD NUMBER DEFAULT 1,
BNO CONSTRAINT FK_ATTACH_BNO REFERENCES TBL_BOARD(BNO)
);
CREATE UNIQUE INDEX IDX_ATTACH_UUID_BNO ON TBL_ATTACH(UUID, BNO DESC);
-- 목록
SELECT /*+ INDEX(TBL_ATTACH IDX_ATTACH_UUID_BNO) */ * FROM TBL_ATTACH WHERE BNO = 190;
-- 상제
SELECT * FROM TBL_ATTACH WHERE UUID = '1';
SELECT * FROM TBL_ATTACH;
'자바 풀스택 공부' 카테고리의 다른 글
Day 55. [Java/JavaScript/jQuery] Ajax, jQuery, 메일 보내기 (0) | 2022.03.24 |
---|---|
Day 54. [Html/JavaScript] Modal (0) | 2022.03.24 |
Day 52. [JSP/Servlet] 페이지네이션, 게시판별 카테고리 (0) | 2022.03.21 |
Day 51. [JSP/Servlet] 오픈소스 - 업로드 (0) | 2022.03.18 |
Day 50. [JSP/Servlet] 커스텀 태그 (0) | 2022.03.18 |
댓글