


@@ Set up
1. model
package com.smhrd.model;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.ToString;
@AllArgsConstructor
@NoArgsConstructor
@RequiredArgsConstructor
@Getter
@ToString
public class Board {
private int num; // 인덱스
@NonNull private String title; // 제목
@NonNull private String writer; // 작성자
@NonNull private String filename; // 파일이름
@NonNull private String content; // 내용
private String b_date; // 업로드 시각
}
package com.smhrd.model;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import com.smhrd.db.SqlSessionManager;
public class BoardDAO {
SqlSessionFactory sqlSessionFactory = SqlSessionManager.getSqlSession();
SqlSession sqlSession = sqlSessionFactory.openSession(true);
// 게시글 작성
public int writeBoard(Board vo) {
int cnt = 0;
try {
cnt = sqlSession.insert("com.smhrd.db.BoardMapper.writeBoard", vo);
} catch (Exception e) {
// TODO: handle exception
}finally {
sqlSession.close();
}
return cnt;
}
// 게시글 전체 조회
public List<Board> allBoard(){
List<Board> boards = null;
try {
boards = sqlSession.selectList("com.smhrd.db.BoardMapper.allBoard");
} catch (Exception e) {
// TODO: handle exception
}finally {
sqlSession.close();
}
return boards;
}
// 게시글 상세 조회
public Board detailBoard(int num) {
Board board = null;
try {
board
= sqlSession.selectOne("com.smhrd.db.BoardMapper.detailBoard", num);
} catch (Exception e) {
// TODO: handle exception
}finally {
sqlSession.close();
}
return board;
}
}
package com.smhrd.db;
import java.io.InputStream;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
public class SqlSessionManager {
public static SqlSessionFactory sqlSessionFactory;
static {
try {
// mybatis 환경설정 파일 경로
String resource = "com/smhrd/db/mybatis-config.xml";
// xml파일을 읽어내기 위해 inputStream 여는 것!
InputStream inputStream = Resources.getResourceAsStream(resource);
// SqlSessionFactory : connection객체가 여러개인 Connection Pool
sqlSessionFactory =
new SqlSessionFactoryBuilder().build(inputStream);
} catch (Exception e) {
e.printStackTrace();
}
}
public static SqlSessionFactory getSqlSession() {
return sqlSessionFactory;
}
}
driver=oracle.jdbc.driver.OracleDriver
url=jdbc:oracle:thin:@localhost:1521:xe
username=service
password=12345
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 2. mybatis-config.xml만들기
: mybatis의 환경설정 담당(중요한 파일) -->
<!-- 3. db.properties 만들기
: db연결정보들을 가지고 있는 파일 -> 공백 주의할 것 -->
<properties resource="com/smhrd/db/db.properties"> </properties>
<typeAliases>
<typeAlias type="com.smhrd.model.Board" alias="Board"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/smhrd/db/BoardMapper.xml"/>
</mappers>
</configuration>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.smhrd.db.BoardMapper">
<insert id="writeBoard" parameterType="Board">
insert into web_board1
values(num_board.nextval, #{title}, #{writer}, #{filename}, #{content}, sysdate)
</insert>
<select id="allBoard" resultType="Board">
select * from web_board1
</select>
<select id="detailBoard" resultType="Board">
select * from web_board1 where num=#{num}
</select>
</mapper>
package com.smhrd.frontController;
public class ViewResolver {
// viewResolver: pojo가 반납한 viewname을 full name으로 만들어주는 역할
//BoardMain - > MVC/WEB-INF/views/BoardMain.jsp
public String makeViewName(String viewname) {
return "WEB-INF/views/"+viewname+".jsp";
}
}
package com.smhrd.frontController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public interface command {
// 인터페이스 : 틀
// 추상메소드 : 값은 없지만 메소드의 기본 값을 설정해주는 역할
public String execute(HttpServletRequest request, HttpServletResponse response);
}
package com.smhrd.frontController;
import java.util.HashMap;
import com.smhrd.controller.BoardDetailService;
import com.smhrd.controller.BoardMainPageService;
import com.smhrd.controller.BoardWritePageService;
import com.smhrd.controller.BoardWriteService;
public class HandleMapping {
// HandlerMapping: FrontController에게 어떤 POJO를 호출해야하는지 알려주는 역할
//boardList.do -> BoardListController
//boardInsert.do -> BoardInsertController
//검색이빠른 hashmap 자료구조 사용
// key: 요청이들어온주소(String)
//value: 호출할 pojo(pojo의 상위클래스인command)
private HashMap<String, command> mappings;
// 생성자 만ㄷ,ㄹ기->객체가 생성에 될 때 key, value를 등록한느 영할
public HandleMapping() {
mappings = new HashMap<String,command>();
//정부에 추가-> put메소드 사용
mappings.put("BoardWriteService.do", new BoardWriteService());
mappings.put("BoardWritePage.do", new BoardWritePageService());
mappings.put("BoardMainPage.do", new BoardMainPageService());
mappings.put("BoardDetailService.do", new BoardDetailService());
}
//pojo를 frontcontroller에게 return 해주는 메소드
public command getPOJO (String result){
return mappings.get(result);
//HashMap의get(key값): 해당 key의 value를 호출하는 메소드
}
}
package com.smhrd.frontController;
import java.io.IOException;
import javax.servlet.RequestDispatcher;
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("*.do")
public class frontcontroller extends HttpServlet {
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("[FrontContoller]");
request.setCharacterEncoding("UTF-8");
// 1. 요청 값 확인하기
String requestURI = request.getRequestURI();
String contextPath = request.getContextPath();
String result = requestURI.substring(contextPath.length()+1);
System.out.println("요청 서블릿 : " + result);
//2. HandleMapping에게 어떤 pojo를 사용
command service = null;
HandleMapping mappings = new HandleMapping();
service = mappings.getPOJO(result);
//3. 업무를 할 pojo 실행시키기 -> pojo는 viewname을 반환
String viewname = service.execute(request, response);
//5. 페이지 이동
if(viewname != null) {
System.out.println("viewname: "+ viewname);
//redirect방식: 다른controller(pojo)를 요청할 때
if(viewname.contains(":/")) {
response.sendRedirect(viewname.split(":/")[1]);
}else {
//forward방식:jsp를 요청할 때
RequestDispatcher rd = request.getRequestDispatcher(
new ViewResolver().makeViewName(viewname));
System.out.println("full name: " +new ViewResolver().makeViewName(viewname));
rd.forward(request, response);
}
}
}
}
package com.smhrd.controller;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.smhrd.frontController.command;
import com.smhrd.model.Board;
import com.smhrd.model.BoardDAO;
public class BoardMainPageService implements command {
@Override
public String execute(HttpServletRequest request, HttpServletResponse response) {
//1. DB에서 게시글 데이터 가져오기
List<Board> boards = new BoardDAO().allBoard();
// 2. view에서 해당 게시글 데이터를 불러오기 위해 request객체에 객체 바인딩
request.setAttribute("boards", boards);
//3. Boardmain.jsp로 가기 위해 viewname 반환
return "BoardMain";
}
}
package com.smhrd.controller;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.oreilly.servlet.MultipartRequest;
import com.oreilly.servlet.multipart.DefaultFileRenamePolicy;
import com.smhrd.frontController.command;
import com.smhrd.model.Board;
import com.smhrd.model.BoardDAO;
public class BoardWriteService implements command {
@Override
public String execute(HttpServletRequest request, HttpServletResponse response) {
// 파일 업로드를 위한 변수 설정
// 1. request 객체
// 2. 파일을 저장할 경로(String)
String savePath = request.getServletContext().getRealPath("./file");
System.out.println("savePath : " + savePath);
// 3. 파일 최대크기(int)
int maxSize = 1024 * 1024 * 10;
// 4. 인코딩 방식(String)
String encoding = "UTF-8";
// 5. 파일이름 중복제거
DefaultFileRenamePolicy rename = new DefaultFileRenamePolicy();
// 파일 업로드 해주는 객체 -> MultipartRequest
MultipartRequest multi;
try {
multi = new MultipartRequest(request, savePath, maxSize, encoding, rename);
// 요청 데이터 받아오기
String title = multi.getParameter("title");
String writer = multi.getParameter("writer");
String filename = multi.getFilesystemName("filename");
String content = multi.getParameter("content");
Board vo = new Board(title, writer, filename, content);
System.out.println(vo.toString());
// DB에 넣어주기
int cnt = new BoardDAO().writeBoard(vo);
if (cnt > 0) {
System.out.println("게시글 작성 성공");
} else {
System.out.println("게시글 작성 실패");
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// response.sendRedirect("BoardMain.jsp");
return "redirect:/BoardMainPage.do";
}
}
package com.smhrd.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.smhrd.frontController.command;
public class BoardWritePageService implements command {
@Override
public String execute(HttpServletRequest request, HttpServletResponse response) {
//BoardWrite.jsp로 이동시켜주는 역할
//page를 요청하는 controller이기 때문에 내부에 코드작성
return "BoardWrite";
}
}
package com.smhrd.controller;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.smhrd.frontController.command;
import com.smhrd.model.Board;
import com.smhrd.model.BoardDAO;
public class BoardDetailService implements command {
@Override
public String execute(HttpServletRequest request, HttpServletResponse response) {
//1. 게시글의 고유번호 num받아오기
int num = Integer.parseInt(request.getParameter("num"));
//2. num을 가지고 db에서 관련 데이터 가져오기
Board board = new BoardDAO().detailBoard(num);
//3. view에서 보여주기 위해거 request객체에 객체
request.setAttribute("board", board);
//3. Boardmain.jsp로 가기 위해 viewname 반환
return "BoardDetail";
}
}
--------------------------------------- BoardMain.jsp
<%@page import="com.smhrd.model.Board"%>
<%@page import="java.util.List"%>
<%@page import="com.smhrd.model.BoardDAO"%>
<%@page import="java.util.ArrayList"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" isELIgnored="false"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Forty by HTML5 UP</title>
<meta charset="utf-8" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<!--[if lte IE 8]><script src="assets/js/ie/html5shiv.js"></script><![endif]-->
<link rel="stylesheet" href="assetsBoard/css/main.css" />
<link rel="stylesheet" href="assetsBoard/css/board.css" />
</head>
<body>
<!-- Q18. 게시글 목록 세부페이지 기능(제목을 클릭하면 세부페이지 BoardDetail.jsp로 이동)-->
<div id="board">
<table id = "list">
<tr>
<td>번호</td>
<td>제목</td>
<td>작성자</td>
<td>시간</td>
</tr>
<!-- 상태변수 -->
<c:forEach var="b" items="${boards}" varStatus="s">
<tr>
<td>${s.count}</td>
<td><a href="BoardDetailService.do?num=${b.num}">${b.title}</a></td>
<td>${b.writer}</td>
<td>${b.b_date}</td>
</tr>
</c:forEach>
</table>
<a href="BoardMainPage.do"><button id="writer">홈으로가기</button></a>
<a href="BoardWritePage.do"><button id="writer">작성하러가기</button></a>
</div>
<!-- Scripts -->
<script src="assets/js/jquery.min.js"></script>
<script src="assets/js/jquery.scrolly.min.js"></script>
<script src="assets/js/jquery.scrollex.min.js"></script>
<script src="assets/js/skel.min.js"></script>
<script src="assets/js/util.js"></script>
<!--[if lte IE 8]><script src="assets/js/ie/respond.min.js"></script><![endif]-->
<script src="assets/js/main.js"></script>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Forty by HTML5 UP</title>
<meta charset="utf-8" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<!--[if lte IE 8]><script src="assets/js/ie/html5shiv.js"></script><![endif]-->
<link rel="stylesheet" href="assetsBoard/css/main.css" />
<link rel="stylesheet" href="assetsBoard/css/board.css" />
<!--[if lte IE 9]><link rel="stylesheet" href="assets/css/ie9.css" /><![endif]-->
<!--[if lte IE 8]><link rel="stylesheet" href="assets/css/ie8.css" /><![endif]-->
</head>
<body>
<!-- Q16. 게시글 작성 기능(작성된 게시글은 DB에 저장) - 파일업로드 cos.jar 사용 -->
<!-- enctype
1) application/x-www-form-urlencoded
-> form태그 안에서 보내는 요청데이터를 Key값과 Value값을 쌍으로 보냄
2) multipart/form-data
-> 사진파일과 같이 용량이 큰 데이터(파일)을 보낼 때 사용(무조건 post방식으로 보내야 함)
-->
<div id = "board">
<form action="BoardWriteService.do" method="post" enctype="multipart/form-data">
<table id="list">
<tr>
<td>제목</td>
<td><input type="text" name="title"> </td>
</tr>
<tr>
<td>작성자</td>
<td><input type="text" name="writer"> </td>
</tr>
<tr>
<td colspan="2">내용</td>
</tr>
<tr>
<td colspan="2">
<input type="file" name="filename" style="float: right;">
<textarea rows="10" name="content" style="resize: none;"></textarea>
</td>
</tr>
<tr>
<td colspan="2">
<input type="reset" value="초기화">
<input type="submit" value="작성하기">
</td>
</tr>
</table>
</form>
</div>
<!-- Scripts -->
<script src="assets/js/jquery.min.js"></script>
<script src="assets/js/jquery.scrolly.min.js"></script>
<script src="assets/js/jquery.scrollex.min.js"></script>
<script src="assets/js/skel.min.js"></script>
<script src="assets/js/util.js"></script>
<!--[if lte IE 8]><script src="assets/js/ie/respond.min.js"></script><![endif]-->
<script src="assets/js/main.js"></script>
</body>
</html>
<%@page import="com.smhrd.model.Board"%>
<%@page import="com.smhrd.model.BoardDAO"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" isELIgnored = "false"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Forty by HTML5 UP</title>
<meta charset="utf-8" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<!--[if lte IE 8]><script src="assets/js/ie/html5shiv.js"></script><![endif]-->
<link rel="stylesheet" href="assetsBoard/css/main.css" />
<link rel="stylesheet" href="assetsBoard/css/board.css" />
<!--[if lte IE 9]><link rel="stylesheet" href="assets/css/ie9.css" /><![endif]-->
<!--[if lte IE 8]><link rel="stylesheet" href="assets/css/ie8.css" /><![endif]-->
</head>
<body>
<!-- Q19. 게시글 세부내용 조회 기능 -->
<div id = "board">
<table id="list">
<tr>
<td>제목</td>
<td>${board.title}</td>
</tr>
<tr>
<td>작성자</td>
<td>${board.writer}</td>
</tr>
<tr>
<td>다운로드</td>
<td><a href="./file/${board.filename}" download>${board.filename}</a></td>
</tr>
<tr>
<td colspan="2">내용</td>
</tr>
<tr>
<td colspan="2">
<h3>${board.content}</h3>
<img alt="" src="./file/${board.filename}">
</td>
</tr>
<tr>
<td colspan="2"><a href="BoardMainPage.do"><button>뒤로가기</button></a></td>
</tr>
</table>
</div>
<!-- Scripts -->
<script src="assets/js/jquery.min.js"></script>
<script src="assets/js/jquery.scrolly.min.js"></script>
<script src="assets/js/jquery.scrollex.min.js"></script>
<script src="assets/js/skel.min.js"></script>
<script src="assets/js/util.js"></script>
<!--[if lte IE 8]><script src="assets/js/ie/respond.min.js"></script><![endif]-->
<script src="assets/js/main.js"></script>
</body>
</html>