서블릿 MVC 패턴 모델 2
해당 코드 이용해서 List, View, write 핸들러 생성해서 실습 하기
package command;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import config.AppCtx;
public class ControllerUsingURI extends HttpServlet {
// 어디서든 사용할 수 있게 설정
//public static ApplicationContext ctx;
// @Autowired
// BoardService boardService;
ApplicationContext ctx;
// <커맨드, 핸들러인스턴스> 매핑 정보 저장
private Map<String, String> commandHandlerMap =
new HashMap<>();
// 서블릿 초기화 메서드
public void init() throws ServletException {
ctx = new AnnotationConfigApplicationContext(AppCtx.class);
// configFile 초기화 파라미터를 읽어온다.
// 이 값을 이용해서 설정 파일 경로를 구한다.
String configFile = getInitParameter("configFile");
System.out.println(configFile);
Properties prop = new Properties();
String configFilePath = getServletContext().getRealPath(configFile);
System.out.println(configFilePath);
// 설정 파일로부터 매핑 정보를 읽어와 Properties 객체에 저장한다.
// Properties는 (이름, 값) 목록을 갖는 클래스로서,
// 이 경우에는 프로퍼티 이름을 커맨드 이름으로 사용하고
// 값을 클래스 이름으로 사용한다.
try (FileReader fis = new FileReader(configFilePath)) { // 파일 읽기
// 설정 파일을 읽어서 Properties 객체에 로드 ( 맵에 보관 )
prop.load(fis);
} catch (IOException e) {
throw new ServletException(e);
}
// Properties에 저장된 각 프로퍼티의 키에 대해 다음 작업을 반복한다.
Iterator keyIter = prop.keySet().iterator();
while (keyIter.hasNext()) {
// 1. 프로퍼티 이름을 커맨드 이름으로 사용한다.
String command = (String) keyIter.next();
// 2. 커맨드 이름에 해당하는 핸들러 클래스 이름을 Properties에서 구한다.
String handlerClassName = prop.getProperty(command);
commandHandlerMap.put(command, handlerClassName);
// try {
// // 3. 핸들러 클래스 이름을 이용해서 Class 객체를 구한다.
// Class<?> handlerClass = Class.forName(handlerClassName);
// // 4. Class로부터 핸들러 객체를 생성한다.
// CommandHandler handlerInstance =
// (CommandHandler) handlerClass.newInstance();
// // 5. commandHandlerMap에 (커맨드, 핸들러 객체)에 대한 매핑 정보를 저장한다.
// commandHandlerMap.put(command, handlerInstance);
// } catch (ClassNotFoundException | InstantiationException
// | IllegalAccessException e) {
// throw new ServletException(e);
// }
}
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
process(request, response);
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
process(request, response);
}
// 클라이언트로부터 들어오는 HTTP 요청에 대해 처리를 수행
// 그에 맞는 핸들러를 호출하여 요청을 처리하고 결과를 뷰 페이지에 전달
private void process(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// 클라이언트가 요청한 URI를 가져온다.
String command = request.getRequestURI();
// 요청된 URI가 웹 어플리케이션의 Context Path(컨텍스트 경로)로 시작한다면,
// Context Path 부분을 제거하여 실제로 처리할 명령어를 추출
// 예)/hello.do 추출
if (command.indexOf(request.getContextPath()) == 0) {
command = command.substring(request.getContextPath().length());
}
System.out.println(command);
// 추출된 명령어를 사용하여 commandHandlerMap에서 해당 커맨드에 대응하는 핸들러를 가져온다.
// commandHandlerMap은 init() 메서드에서 설정 파일로부터 읽어온 커맨드와 핸들러 클래스를 매핑한 맵
// CommandHandler handler = commandHandlerMap.get(command);
// // 만약 해당 명령어에 대응하는 핸들러가 없다면, 기본적으로 NullHandler를 사용
// if (handler == null) {
// handler = new NullHandler();
// }
// 찾아낸 핸들러를 사용하여 실제 요청 처리를 수행
// 핸들러의 process() 메서드를 호출하여 요청 처리 결과로 뷰 페이지의 경로를 가져온다.
// 최종적으로 클라이언트에게 보여질 JSP 페이지의 위치를 나타낸다.
String handler = commandHandlerMap.get(command);
System.out.println(handler);
// 인터페이스 다형성
CommandHandler helloHandler = ctx.getBean(handler, CommandHandler.class);
String viewPage = null;
try {
viewPage = helloHandler.process(request, response);
} catch (Throwable e) {
throw new ServletException(e);
}
// 만약 뷰 페이지 경로가 존재한다면, RequestDispatcher를 사용하여 해당 뷰 페이지로 포워딩
// 즉, 요청된 작업의 처리 결과를 클라이언트에게 보여줄 JSP 페이지로 이동하게 된다.
if (viewPage != null) {
RequestDispatcher dispatcher = request.getRequestDispatcher(viewPage);
dispatcher.forward(request, response);
}
}
}
Service
package service;
import java.util.ArrayList;
import dao.BoardDto;
public interface BoardService {
ArrayList<BoardDto> findAll();
BoardDto findOne(Long num, boolean incHits);
void saveOne(BoardDto dto);
void modifyOne(BoardDto dto);
void cancelOne(Long num);
boolean hasArticle(Long num);
}
package service;
import java.util.ArrayList;
import dao.BoardDao;
import dao.BoardDto;
public class BoardServiceImpl implements BoardService {
// 스프링 설정 클래스에서 생성자 생성했으니 생성자 생성 필요 없음
BoardDao boardDao;
// 세터
public void setBoardDao(BoardDao boardDao) {
this.boardDao = boardDao;
}
// 생성자방식 ( 의존 객체 주입 )
public BoardServiceImpl(BoardDao boardDao) {
super();
// 주입 받은 객체를 필드에 할당
this.boardDao = boardDao;
}
@Override
public ArrayList<BoardDto> findAll() {
return boardDao.selectList();
}
@Override
public BoardDto findOne(Long num, boolean incHits) {
if (incHits) {
boardDao.updateHits(num);
}
return boardDao.selectOne(num, incHits);
}
@Override
public void saveOne(BoardDto dto) {
boardDao.insertOne(dto);
}
@Override
public void modifyOne(BoardDto dto) {
boardDao.updateOne(dto);
}
@Override
public void cancelOne(Long num) {
boardDao.deleteOne(num);
}
@Override
// 게시물 번호를 매개변수로 받아서 해당 번호에 해당하는 게시물이 데이터베이스에 존재하는지 확인
public boolean hasArticle(Long num) {
// 주어진 게시물 번호를 가진 게시물을 데이터베이스에서 검색하고 그 결과를 Dto로 반환
// false로 조회 시 조회수를 증가시키지않게 설정
BoardDto dto = boardDao.selectOne(num, false);
if(dto == null) {
return false;
}
//조회 결과(Dto)가 null이 아니라면 해당 게시물이 데이터베이스에 존재하는 것을 의미
return true;
}
}
1. 핸들러 만들기
1) ListHandler
package command;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import service.BoardService;
public class ListHandler implements CommandHandler {
@Autowired
BoardService boardService;
@Override
public String process(HttpServletRequest req, HttpServletResponse res) throws Exception {
// @Autowired 설정 시 밑에 추가 안해줘도 됨
// BoardService boardService =
// ControllerUsingURI.ctx.getBean("boardservice", BoardService.class);
// public static ApplicationContext ctx; 호출
req.setAttribute("list", boardService.findAll());
return "/WEB-INF/view/list.jsp";
}
}
중요한 포인트
@Autowired
BoardService boardService;
설정 시 밑에 추가 안해줘도 됨
BoardService boardService =
ControllerUsingURI.ctx.getBean("boardservice", BoardService.class);
public static ApplicationContext ctx; 호출
2) ViewHandler
package command;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import dao.BoardDto;
import service.BoardService;
public class ViewHandler implements CommandHandler {
@Autowired
BoardService boardService;
@Override
public String process(HttpServletRequest req, HttpServletResponse res) throws Exception {
long num = Long.parseLong(req.getParameter("num"));
// 방법 1
BoardDto dto = boardService.findOne(num, true);
req.setAttribute("dto", dto);
req.setAttribute("num", num);
// 방법 2
// req.setAttribute("dto", boardService.findOne(num,true));
return "/WEB-INF/view/view.jsp";
}
}
3) WriteHandler
package command;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import service.BoardService;
public class WriteHandler implements CommandHandler {
@Autowired
BoardService boardService;
@Autowired
InsertHandler insertHandler;
@Override
public String process(HttpServletRequest req, HttpServletResponse res) throws Exception {
req.setAttribute("action", "/insert.do");
return "/WEB-INF/view/write.jsp";
}
}
2. @Bean 등록
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import command.GitHandler;
import command.HelloHandler;
import command.InsertHandler;
import command.ListHandler;
import command.ViewHandler;
import command.WriteHandler;
import dao.BoardDao;
import service.BoardServiceImpl;
@Configuration
public class AppCtx {
@Bean
public BoardDao boardDao() {
return new BoardDao();
}
@Bean // 생성자 방식
public BoardServiceImpl boardservice() {
BoardServiceImpl boardservice = new BoardServiceImpl(boardDao());
return boardservice;
}
@Bean
public ListHandler listHandler() {
return new ListHandler();
}
@Bean
public ViewHandler viewHandler() {
return new ViewHandler();
}
@Bean
public WriteHandler writeHandler() {
return new WriteHandler();
}
3. properties 등록 ( @Bean 메서드 변수 이름으로 등록 )
/hello.do=helloHandler
/git.do=gitHandler
/list.do=listHandler
/view.do=viewHandler
/write.do=writeHandler
/insert.do=insertHandler
/login.do=command.LoginHandler
/welcome.do=command.LoginHandler
4. JSP 생성
1. list.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>
<head>
<meta charset="UTF-8">
<style>
table { width:680px; text-align:center; }
th { background-color:cyan; }
.num { width: 80px; }
.title { width:230px; }
.writer { width:100px; }
.regtime { width:180px; }
a:link { text-decoration:none; color:blue; }
a:visited { text-decoration:none; color:gray; }
a:hover { text-decoration:none; color:red; }
</style>
</head>
<body>
<div id="result"></div>
<table>
<tr>
<th class="num" >번호 </th>
<th class="title" >제목 </th>
<th class="writer" >작성자 </th>
<th class="regtime">작성일시</th>
<th >조회수 </th>
</tr>
<c:forEach var="dto" items="${list}">
<tr>
<td>${dto.num}</td>
<td style="text-align:left;">
<!-- <a href="#" onclick="ajax(${dto.num})"> -->
<a href="${pageContext.request.contextPath}/view.do?num=${dto.num}">
${dto.title}
</a>
</td>
<td>${dto.writer}</td>
<td>${dto.regtime}</td>
<td>${dto.hits}</td>
</tr>
</c:forEach>
</table>
<br>
<input type="button" value="글쓰기" onclick="location.href='${pageContext.request.contextPath}/write.do'">
<script>
function ajax(num) {
var res = document.getElementById("result");
//var btn = document.getElementById("btn");
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
console.log(xhr.responseText);
res.innerHTML = xhr.responseText;
}
}
};
xhr.open("get", "view2.jsp?num="+num, true);
xhr.send();
}
</script>
</body>
</html>
2. view.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>
<head>
<meta charset="UTF-8">
<style>
table { width:680px; text-align:center; }
th { width:100px; background-color:cyan; }
td { text-align:left; border:1px solid gray; }
</style>
</head>
<body>
<table>
<tr>
<th>제목</th>
<td>${dto.title}</td>
</tr>
<tr>
<th>작성자</th>
<td>${dto.writer}</td>
</tr>
<tr>
<th>작성일시</th>
<td>${dto.regtime}</td>
</tr>
<tr>
<th>조회수</th>
<td>${dto.hits}</td>
</tr>
<tr>
<th>내용</th>
<td>${dto.content}</td>
</tr>
</table>
<br>
<input type="button" value="목록보기" onclick="location.href='${pageContext.request.contextPath}/list.do'">
<input type="button" value="수정"
onclick="location.href='${pageContext.request.contextPath}/write.do?num=${num}'">
<input type="button" value="삭제"
onclick="location.href='${pageContext.request.contextPath}/delete?num=${num}'">
</body>
</html>
3. write.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>
<head>
<meta charset="UTF-8">
<style>
table { width:680px; text-align:center; }
th { width:100px; background-color:cyan; }
input[type=text], textarea { width:100%; }
</style>
</head>
<body>
<form method="post" action="${action}">
<table>
<tr>
<th>제목</th>
<td><input type="text" name="title" maxlength="80"
value="${dto.title}">
</td>
</tr>
<tr>
<th>작성자</th>
<td><input type="text" name="writer" maxlength="20"
value="${dto.writer}">
</td>
</tr>
<tr>
<th>내용</th>
<td><textarea name="content" rows="10">${dto.content}</textarea>
</td>
</tr>
</table>
<br>
<input type="submit" value="저장" onclick="location.href='${pageContext.request.contextPath}/insert.do'">
<input type="button" value="취소" onclick="history.back()">
</form>
</body>
</html>
서블릿 init 설정 ( 서블릿 만들 때 init 체크 해주면 됨 )
jQuery
jQuery를 사용할라면 jQuery 사이트에서 다운로드 클릭 이미지 있는 곳으로 이동 (Google CDN 사용 )
Google CDN 버튼 클릭하면 해당 위치로 이동 3.x스니펫 코드 복사
자바스크립트 파일을 로드하기 전에 해당 코드처럼 우선 로드 해야됨
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.0/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
var resultText = "";
var $searchEles = $('li');
console.log($searchEles);
resultText+="검색된 엘리먼트 개수 : " + $searchEles.length+"\n";
$searchEles.each(function() {
resultText+= $(this).text() + "\t";
$(this).text('빵')
});
alert($.trim(resultText));
});
</script>
addClass
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.0/jquery.min.js"></script>
</head>
<style>
span{font-size: 30pt}
.redtext {color: red;}
.italictext { font-style: italic;}
</style>
<body>
<span> simple</span>
<script>
// jQuery 사용
$('span').addClass('italictext');
$('span').addClass('redtext');
</script>
</body>
</html>
jQuery사용 부분을 보면 <span> 부분 선택 후 css 적용
결과를 보면 css 클래스 2개 적용된 모습
셀렉터
엘리먼트에 접근해서 스타일 지정하기
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<style>
.spotlight{background-color: yellow;}
.redtext {color: red;}
.largetext {font-size: 30pt;}
.italictext {font-style: italic;}
</style>
<body>
<span id="simpletext1">simple</span>
<div class="simpletext1">jquery</div>
<span >basic</span>
<div >example</div>
<script>
$(document).ready(function(){
$('span').addClass('redtext');
debugger;
$('div').addClass('spotlight');
$('#simpletext1').addClass('largetext');
$('.simpletext1').addClass('italictext');
});
</script>
</body>
</html>
한 번에 다양한 엘리먼트에 접근하여 개수와 텍스트 얻기
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>한 번에 다양한 엘리먼트에 접근하여 개수와 텍스트 얻기-“selector1, selector2, selectorN”</title>
</head>
<body>
<span>simple</span>
<div class='simpletext1'>jQuery</div>
<div>basic</div>
<p>example</p>
<ul>
<li>떡볶이</li>
<li>순대</li>
<li>튀김</li>
</ul>
<script type="text/javascript">
$(document).ready(function() {
var resultText = ""; // " 검색된 엘리먼트 개수
var $searchEles = $('li'); // 배열 비슷
console.log($searchEles);
resultText+="검색된 엘리먼트 개수 : " + $searchEles.length+"\n";
$searchEles.each(function() { // each 반복문 비슷
resultText+= $(this).text() + "\t";
// $(this).text('빵') 해당 값 추가시 위에 li무시하고 '빵' 만 출력
});
alert($.trim(resultText));
});
</script>
</body>
</html>
확장 객체 집합에서 자손 엘리먼트에 스타일시트 적용하기
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>선택된 jQuery 확장 객체 집합에서 자손 엘리먼트에 스타일시트 적용하기-“ancestor descendant”</title>
<style type="text/css">
em { font-size: 12pt; line-height: 40pt}
</style>
</head>
<body>
<div>
<em>Hello!</em>
<em>jQuery</em>
<em>forever</em>
</div>
<span>
<em>Good Bye!</em>
<em>javascript</em>
</span>
<script type="text/javascript">
$(document).ready(function() { // 준비된 상태 (ready) 가 되었을 때 적용 콜백함수
// 엘리먼트 줄 div 엘리먼트에 포함된 것만 조회하기 위한 셀렉터를 jQuery 함수에 적 용하여 얻은 jQuery 확장 객체 집합에 css() 메소드로 경계선을 그린다.
$('div em').css('border', '3pt solid #f00')
.css('padding', '7pt 7pt 7pt 7pt');
$('span em').css('border', '1pt dotted #0f0')
.css('padding', '7pt 7pt 7pt 7pt');
console.log("검색된 엘리먼트 개수 : "+ $('div em').length); // 3개
console.log("검색된 엘리먼트 개수 : "+ $('span em').length); // 2
});
</script>
</body>
</html>
인접한 자손 엘리먼트를 노드로 추가 ( praent > child )
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>인접한 자손 엘리먼트를 노드로 추가하기</title>
<style type="text/css">
em {
font-size:20pt; line-height: 20pt;
margin:20px; color:blue;
}
</style>
</head>
<body>
<p>
<em> one </em>
<em> two </em>
<span> <em> three </em> </span>
</p>
<div>
<em> four </em>
<span> <em> five </em> </span>
<em>six</em>
</div>
<hr>
<div>
<span> ancestor descendant로 검색된 엘리먼트 : </span>
<span class="result1"></span>
</div>
<div>
<span> parent > child로 검색된 엘리먼트 : </span>
<span class="result2"></span>
</div>
<script type="text/javascript">
$(document).ready(function() {
$('p em').css('background-color', 'yellow').each(function() {
$('.result1').append($(this).text()+ "\n");
});
$('div > em').css('background-color', 'pink').each(function() {
$('.result2').append($(this).text()+ "\n");
});
console.log("검색된 엘리먼트 개수 : " + $('p em').length);
console.log("검색된 엘리먼트 개수 : " + $('div > em').length);
});
</script>
</body>
</html>
'프로젝트 기반 자바(JAVA) 응용 SW개발자 취업과정' 카테고리의 다른 글
2023-08-01 53일차 (0) | 2023.08.01 |
---|---|
2023-07-31 52일차 (0) | 2023.07.31 |
2023-07-27 50일차 (0) | 2023.07.27 |
2023-07-26 49일차 (0) | 2023.07.26 |
2023-07-25 48일차 (0) | 2023.07.25 |