서블릿 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 &gt; 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

+ Recent posts