컴포넌트 | 기능 |
---|---|
컨트롤러 | 폼 액션이나 링크 클릭등을 통하여 사용자가 요청하는 액션을 받아들여서 모델과 뷰를 통해서 요청을 처리한 후 응답한다. |
모델 | 모델은 뷰가 렌더링하는데 필요한 데이터이다. 예를 들면 게시판 리스트에 출력하기 위한 게시물 목록이 모델에 해당한다. |
뷰 | 실제로 유저에게 보여주기위한 화면이며 모델을 이용하여 렌더링을 한다. JSP, XML, JSON, PDF 등으로 웹 페이지를 표현한다. |
mvc.fx/dispatcher-servlet.properties
/pilot/form = pilot.controller.FormController
/pilot/process = pilot.controller.ProcessController
/game/ready = game.controller.ReadyController
/game/result = game.controller.ResultController
mvc.fx/dispatcherServlet.java
package mvc.fx;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
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;
import pilot.controller.FormController;
import pilot.controller.ProcessController;
import game.controller.ReadyController;
import game.controller.ResultController;
@WebServlet(
urlPatterns = {"/pilot/*",
"/game/*"
},
loadOnStartup = 10)
public class DispatcherServlet extends HttpServlet {
private Map<String, AbstractController> controllerMap = new HashMap<>();
@Override
public void init() throws ServletException {
Properties prop = new Properties();
try {
prop.load(new FileInputStream(this.getClass().getResource("dispatcher-servlet.properties").getPath()));
for(Object oKey : prop.keySet()) {
String key = ((String)oKey).trim();
Class<?> className = null;
try {
className = Class.forName(prop.getProperty(key).trim());
controllerMap.put(key, (AbstractController) className.getConstructor().newInstance());
System.out.println("🧡 loaded : " + className + " 🧡");
} catch (Exception e) {
e.printStackTrace();
System.out.println("💔 error : " + className + " 💔");
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String requestURI = request.getRequestURI();
System.out.println(requestURI);
String contextPath = request.getContextPath();
System.out.println(contextPath);
String action = requestURI.substring(contextPath.length());
// AbstractController controller = null;
// ModelAndView mav = null;
// if(action.equals("/pilot/form")) {
// controller = new FormController();
// mav = controller.handleRequestInternal(request, response);
// } else if (action.equals("/pilot/process")) {
// controller = new ProcessController();
// mav = controller.handleRequestInternal(request, response);
// }
/*
String action = requestURI.substring(contextPath.length());
*/
AbstractController controller = controllerMap.get(action);
ModelAndView mav = controller.handleRequestInternal(request, response);
if (mav != null) {
String viewName = mav.getViewName();
if (viewName.startsWith("redirect:")) {
response.sendRedirect(viewName.substring(9));
} else {
Map<String, Object> model = mav.getModel();
for(String key : model.keySet()) {
request.setAttribute(key, model.get(key));
}
RequestDispatcher dispatcher = request.getRequestDispatcher(viewName);
dispatcher.forward(request, response);
}
} else {
System.out.println("RequestDispatcher에서 길을 잃었다네~");
}
}
}
ReadyController.java
package game.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import mvc.fx.AbstractController;
import mvc.fx.ModelAndView;
public class ReadyController extends AbstractController {
@Override
public ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) {
// TODO Auto-generated method stub
return new ModelAndView("/WEB-INF/game/ready.jsp");
}
}
ready.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="result" method="post">
<h1>가위, 바위, 보</h1>
<select name="you">
<option value="1">가위</option>
<option value="2">바위</option>
<option value="3">보</option>
</select>
<button type="submit">확인</button>
</form>
</body>
</html>
ResultController.java
package game.controller;
import java.util.Random;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import mvc.fx.AbstractController;
import mvc.fx.ModelAndView;
public class ResultController extends AbstractController {
@Override
public ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) {
// Get user's choice
int you = Integer.parseInt(request.getParameter("you"));
// Generate a random choice for the computer
int com = new Random().nextInt(3) + 1;
// Determine the winner
String result = determineWinner(you, com);
// Set the result and choices as attributes
ModelAndView mav = new ModelAndView();
mav.setViewName("/WEB-INF/game/result.jsp");
mav.addObject("you", getChoiceString(you));
mav.addObject("com", getChoiceString(com));
mav.addObject("result", result);
return mav;
}
private String determineWinner(int you, int com) {
if (you == com) {
return "비겼습니다!";
} else if ((you == 1 && com == 3) || (you == 2 && com == 1) || (you == 3 && com == 2)) {
return "당신이 이겼습니다!";
} else {
return "컴퓨터가 이겼습니다!";
}
}
private String getChoiceString(int choice) {
switch (choice) {
case 1:
return "가위";
case 2:
return "바위";
case 3:
return "보";
default:
return "";
}
}
}
result.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>결과</h1>
<p>당신의 선택: ${you}</p>
<p>컴퓨터의 선택: ${com}</p>
<p>${result}</p>
</body>
</html>
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>mvc</h1>
<a href="pilot/form">form</a><br/>
<a href="game/ready">ready</a><br/>
<%-- <h1>Hello Servlet/JSP</h1>
<%
out.println("Hello World");
%> --%>
</body>
</html>
action
log4j.properties
#DEBUG, INFO, WARN, ERROR, FATAL
log4j.rootCategory=DEBUG, console, filelog
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%-5p,%d{yyyy/MM/dd HH:mm:ss.SSS},%-5X{APP}, %-8X{TSC}, %m %n
log4j.appender.filelog=org.apache.log4j.DailyRollingFileAppender
log4j.appender.filelog.Append=true
log4j.appender.filelog.DatePattern='.'yyyy-MM-dd-HH
log4j.appender.filelog.File=/Users/jeong-yoon/dev/logs/devlog.txt
log4j.appender.filelog.layout=org.apache.log4j.PatternLayout
log4j.appender.filelog.layout.ConversionPattern=%-5p,%d{yyyy/MM/dd HH:mm:ss.SSS},%-5X{APP}, %-8X{TSC}, %m %n
dispatcher-servlet.properties
### Test
/pilot/form = pilot.controller.FormController
/pilot/process = pilot.controller.ProcessController
/game/ready = game.controller.ReadyController
/game/result = game.controller.ResultController
### Article
/article/insert=article.controller.ArticleInsert
/article/insertAction=article.controller.ArticleInsertAction
/article/list=article.controller.ArticleList
DispatcherServlet.java
package mvc.fx;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
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;
import pilot.controller.FormController;
import pilot.controller.ProcessController;
import game.controller.ReadyController;
import game.controller.ResultController;
@WebServlet(
urlPatterns = {"/pilot/*",
"/game/*",
"/article/*"
},
loadOnStartup = 10)
public class DispatcherServlet extends HttpServlet {
private Map<String, AbstractController> controllerMap = new HashMap<>();
@Override
public void init() throws ServletException {
Properties prop = new Properties();
try {
prop.load(new FileInputStream(this.getClass().getResource("dispatcher-servlet.properties").getPath()));
for(Object oKey : prop.keySet()) {
String key = ((String)oKey).trim();
Class<?> className = null;
try {
className = Class.forName(prop.getProperty(key).trim());
controllerMap.put(key, (AbstractController) className.getConstructor().newInstance());
System.out.println("🧡 loaded : " + className + " 🧡");
} catch (Exception e) {
e.printStackTrace();
System.out.println("💔 error : " + className + " 💔");
}
}
} catch (Exception e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
}
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String requestURI = request.getRequestURI();
System.out.println(requestURI);
String contextPath = request.getContextPath();
System.out.println(contextPath);
String action = requestURI.substring(contextPath.length());
// AbstractController controller = null;
// ModelAndView mav = null;
// if(action.equals("/pilot/form")) {
// controller = new FormController();
// mav = controller.handleRequestInternal(request, response);
// } else if (action.equals("/pilot/process")) {
// controller = new ProcessController();
// mav = controller.handleRequestInternal(request, response);
// }
/*
String action = requestURI.substring(contextPath.length());
*/
AbstractController controller = controllerMap.get(action);
if (controller == null) throw new RuntimeException("controller 찾지 못함");
ModelAndView mav = controller.handleRequestInternal(request, response);
if (mav == null) throw new RuntimeException("controller 찾지 못함");
if (mav != null) {
String viewName = mav.getViewName();
if (viewName.startsWith("redirect:")) {
response.sendRedirect(viewName.substring(9));
} else {
Map<String, Object> model = mav.getModel();
for(String key : model.keySet()) {
request.setAttribute(key, model.get(key));
}
RequestDispatcher dispatcher = request.getRequestDispatcher(viewName);
dispatcher.forward(request, response);
}
} else {
System.out.println("RequestDispatcher에서 길을 잃었다네~");
}
}
}
ArticleInsert.java
package article.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import mvc.fx.AbstractController;
import mvc.fx.ModelAndView;
public class ArticleInsert extends AbstractController {
@Override
public ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) {
return new ModelAndView("/WEB-INF/article/insert.jsp");
}
}
insert.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link rel="icon" type="image/png" sizes="16x16" href="/webdev/kitty.png">
<title>Insert title here</title>
</head>
<body>
<form name="myform" method="post" action="insertAction">
<table>
<caption>게시물 글쓰기</caption>
<tr>
<th>제목</th>
<td><input type="text" name="title" autofocus required /></td>
</tr>
<tr>
<th>이름</th>
<td><input type="text" name="name" required /></td>
</tr>
<tr>
<th>비밀번호</th>
<td><input type="password" name="password" required /></td>
</tr>
<tr>
<th>내용</th>
<td><textarea name="content" rows="5" cols="40"></textarea></td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="submit" value="완료" />
</td>
</tr>
</table>
</form>
</body>
</html>
ArticleInsertAction.java
package article.controller;
import java.sql.SQLException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import article.dto.ArticleDTO;
import article.service.ArticleService;
import lombok.extern.java.Log;
import lombok.extern.log4j.Log4j;
import mvc.fx.AbstractController;
import mvc.fx.ModelAndView;
//@Log4j
@Log
public class ArticleInsertAction extends AbstractController {
private static final Logger log = LoggerFactory.getLogger(ArticleService.class);
ArticleService service = new ArticleService();
@Override
public ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) {
String name = request.getParameter("name");
String title = request.getParameter("title");
String password = request.getParameter("password");
String content = request.getParameter("content");
ArticleDTO articleDTO = new ArticleDTO();
articleDTO.setName(name);
articleDTO.setTitle(title);
articleDTO.setPassword(password);
articleDTO.setContent(content);
// log.info(articleDTO);
try {
service.insertArticle(articleDTO);
return new ModelAndView("redirect:list");
} catch(Exception e){
// log.info(e.getMessage());
ModelAndView mav = new ModelAndView("/WEB-INF/article/result.jsp");
mav.addObject("msg", "게시물 입력 실패\\n입력 폼으로 되돌아갑니다.");
mav.addObject("url", "javascript:history.back();");
return mav;
}
// System.out.println(articleDTO);
// return null;
}
}
ArticleDTO.java
package article.dto;
import java.io.Serializable;
import java.util.Date;
import org.apache.commons.codec.digest.DigestUtils;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
//@Getter
//@Setter
//@ToString
public class ArticleDTO implements Serializable {
public long getNo() {
return no;
}
public void setNo(long no) {
this.no = no;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = DigestUtils.sha512Hex(password);
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Date getRegdate() {
return regdate;
}
public void setRegdate(Date regdate) {
this.regdate = regdate;
}
public int getReadcount() {
return readcount;
}
public void setReadcount(int readcount) {
this.readcount = readcount;
}
private long no;
private String title;
private String name;
private String password;
private String content;
private Date regdate;
private int readcount;
// public void setPassword(String password) {
// this.password = DigestUtils.sha512Hex(password);
// }
}
ArticleService.java
package article.service;
import java.sql.SQLException;
import java.util.List;
import article.dao.ArticleDAO;
import article.dto.ArticleDTO;
import lombok.extern.java.Log;
import lombok.extern.log4j.Log4j;
@Log4j
public class ArticleService {
//private static final Logger log = LoggerFactory.getLogger(ArticleService.class);
private static ArticleService service = new ArticleService();
private ArticleDAO dao = ArticleDAO.getInstance();
private ArticleService() {}
public static ArticleService getInstance() {
return service;
}
public void insertArticle(ArticleDTO articleDTO) throws SQLException {
try {
dao.insertArticle(articleDTO);
} catch (SQLException e) {
// log.info(e.getMessage());
throw e;
}
}
public List<ArticleDTO> getArticleList() throws Exception {
try {
return dao.getArticleList();
} catch (Exception e) {
// log.info(e.getMessage());
throw e;
}
}
}
ArticleDAO.java
package article.dao;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import article.dto.ArticleDTO;
import lombok.extern.java.Log;
@Log
public class ArticleDAO {
private static ArticleDAO dao = new ArticleDAO();
private ArticleDAO() {
try {
Class.forName("net.sf.log4jdbc.DriverSpy");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static ArticleDAO getInstance() {
return dao;
}
private Connection getConnection() throws SQLException {
return DriverManager.getConnection(
"jdbc:log4jdbc:oracle:thin:@localhost:1521/xepdb1", "ace","ace");
}
public void insertArticle(ArticleDTO articleDTO) throws SQLException {
String sql =
"""
insert into article(no, title, name, content, password)
values(seq_article.nextval, ?, ?, ?, ?)
""";
try(Connection conn = getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setString(1, articleDTO.getTitle());
pstmt.setString(2, articleDTO.getName());
pstmt.setString(3, articleDTO.getContent());
pstmt.setString(4, articleDTO.getPassword());
pstmt.executeQuery();
}
}
public List<ArticleDTO> getArticleList() throws SQLException {
String sql =
"""
SELECT
no,
title,
name,
regdate,
readcount
FROM
article
ORDER BY no DESC
""";
List<ArticleDTO> list = new ArrayList<>();
try(Connection conn = getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql);
ResultSet rs = pstmt.executeQuery()) {
while(rs.next()) {
ArticleDTO dto = new ArticleDTO();
dto.setNo(rs.getLong("no"));
dto.setTitle(rs.getString("title"));
dto.setName(rs.getString("name"));
dto.setRegdate(rs.getDate("regdate"));
dto.setReadcount(rs.getInt("readcount"));
list.add(dto);
}
return list;
}
}
}
ArticleList.java
package article.controller;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import article.dto.ArticleDTO;
import article.service.ArticleService;
import lombok.extern.log4j.Log4j;
import mvc.fx.AbstractController;
import mvc.fx.ModelAndView;
@Log4j
public class ArticleList extends AbstractController {
ArticleService service = ArticleService.getInstance();
@Override
public ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) {
try {
List<ArticleDTO> list = service.getArticleList();
return new ModelAndView("/WEB-INF/article/list.jsp", "list", list);
} catch (Exception e) {
ModelAndView mav = new ModelAndView("/WEB-INF/article/result.jsp");
mav.addObject("msg", "게시물 리스트 출력 실패");
mav.addObject("url", "../");
return mav;
}
}
}
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" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- 구글 폰트 -->
<link href="https://fonts.googleapis.com/css?family=Noto+Sans+KR" rel="stylesheet">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<link rel="stylesheet" href="../css/site.css">
<link rel="icon" type="image/png" sizes="16x16" href="/webdev/kitty.png">
<title>Insert title here</title>
</head>
<body>
<br/>
<div class="container">
<div class="jumbotron"><h1>게시물 리스트</h1></div>
<div style="text-align: right">1/1000</div>
<table border="1" class="table">
<thead class="thead-dark">
<tr>
<th scope="col">번호</th>
<th scope="col">제목</th>
<th scope="col">작성자</th>
<th scope="col">작성일</th>
<th scope="col">조회수</th>
</tr>
</thead>
<c:forEach items="${list}" var="article">
<tr>
<th scope="row">${article.no}</th>
<td>${article.title}</td>
<td>${article.name}</td>
<td>${article.regdate}</td>
<td>${article.readcount}</td>
</tr>
</c:forEach>
</table>
<br/>
<button type="button" class="btn btn-primary" onclick="javascript:location.href='insert'">글쓰기</button>
</div>
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
</body>
</html>
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>mvc</h1>
<a href="pilot/form">form</a><br/>
<a href="game/ready">ready</a><br/>
<a href="article/insert">insert</a><br/>
<%-- <h1>Hello Servlet/JSP</h1>
<%
out.println("Hello World");
%> --%>
</body>
</html>
즐겁게 읽었습니다. 유용한 정보 감사합니다.