Jam's story

[JSP] MVC 패턴 본문

JSP

[JSP] MVC 패턴

애플쩀 2022. 6. 23. 17:23

컨트롤러(서블릿)가 가운데서 모든것을 관리한다. 

-비즈니스 로직을 처리하는 모델과 결과 화면을 보여주는 뷰를 분리한다.

-어플리케이션의 흐름제어나 사용자의 처리요청은 컨트롤러에 집중한다. 

 

컨트롤러= 서블릿

모델= 로직처리 클래스, 자바빈 

뷰 =jsp

사용자 = 웹브라우저나 기기 

 

유투브 우아한 tech 동영상에서

 

클라이언트에서 웹 브라우저를 띄어서 URL (주소) 입력 후 엔터 -> 요청할 때 명령 전달하는 방법

  • ㄱ. 특정 파라미터를 이용해서 명령어 정보를 전달...
  • ㄴ.요청 url자체에 명령 전달 

저기서 모델을 핸들러로 사용

      
  1) 컨트롤러(Controller) - 모든 요청, 응답에 대한 흐름 제어자(객체)
                 모든 요청을 -> 서블릿
               MVC패턴일 때는 컨트롤러는 서블릿이다.
                 
         2) 모델(Model) - 비지니스 로직 처리하는 객체 (여러개일 수 있음 list.do , write.do ...)
                 자바빈(DTO, VO), 로직처리 서비스 클래스, DAO (서블릿 아님)
                 
         3) 뷰(View) - 사용자에게 결과 화면을 출력하는 객체
               JSP
         
         결과물을 컨트롤러에게 넘기면 보낼땐 jsp로 보내야하는데 보여지는 페이지를 view라고 함
         컨트롤러가 뷰를 찾아 뷰에서 응답하는 것 (뷰에 모델 객체에서 처리된 리스트(결과물)를 넘김)
       뷰(View) list.jsp (list)  EL+JSTL
       
      로직 처리하는 모델이 DAO 같은건가요?
      DAO 기능도 포함되어지고, 서비스에서 DAO 호출했듯이 서비스가 더 넓은 의미로 로직을 처리하는 객체로 보        면 된다.
      서비스+DAO 합쳐 모델이라 해도 되고, 서비스를 모델이라 해도 됩니다.
      dao가 완벽한 모델 ? 은 아니다. dao는 db연동만 하는거니까 (로직 처리 중 db연동, 일부분인 것)       

      
     

 

1.days08안에 board 폴더만들기 

 

2.새로운 web.xml 만들기 (커넥션풀 DBCP 설정부분만 남아있도록 )

web.xml

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>jspPro</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>

<!--  p 415 커넥션풀을 사용하기 위해서 설정한 코딩.  -->
<resource-ref>
<description>Oracle Datasource example</description>
<res-ref-name>jdbc/myoracle</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>

<!--  MV[C] 단 하나의 서블릿( 컨트롤러 ) 등록  -->
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>days08.mvc.controller.DispatcherServlet</servlet-class>
<init-param>
<param-name>path</param-name>
<param-value>/WEB-INF/commandHandler.properties</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>

 

3.모든 요청 =>단하나의 서블릿 (MV[C] 컨트롤러)

 

4.web.xml 등록 

   <load-on-startup>1</load-on-startup>

요청이 없어도 톰캣(WAS)서버가 시작될때  서블릿 객체를 생성해서 바로 응답할 수 있도록 하기 위해서 

=즉 톰캣 시작과 동시에 서블릿 객체 생성 

 

5.DispatcherServlet 등록 - 컨트롤러 역할

a링크 요청- >get

브라우저 주소창[] 요청 ->get

 

  • 여기서 애노테이션은 주석처리해야한다. !! web.xml에 이미 등록해놨기때문에 
  • 모든 요청->각각요청->로직처리모델 찾아서 ->로직처리 ->저장- >뷰페이지(list.jsp)->포워딩 
  • map선언이유 :  요청 url 과 커맨드핸들러가 짝지어 저장되어있는   commandHandler.properties에서 값을 가져와서 요청이 들어오면 어떤 CommandHandler가 필요한지 알기위해 
  • 톰캣서버 시작될때 컨트롤러인  DispatcherServlet 서블릿 객체 생성되고(서버 시작하고 맵핑에 의해 서블릿이 실행될때) init() 호출됨 (초기화작업 )
  •  DispatcherServlet 역할은 모든 요청 ->handler.process()-> 명령어 핸들러가 요청한 리턴한 뷰로 포워딩 
  • init()- 웹 컨테이너 안에서 생성자처럼 서블릿 객체가  생성될때 호출되는 메소드, 초기화역할
  • init() 함수존재이유 => commandHandler.properties에서 url 풀네임을 가져와서 commandHandlerMap 객체에 넣는다. 
package days08.mvc.controller;

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.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import days08.mvc.command.CommandHandler;

public class DispatcherServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    public DispatcherServlet() {
        super(); 
    } 
    
    private Map<String, CommandHandler> commandHandlerMap = new HashMap<String, CommandHandler>();
    
    @Override
	public void init() throws ServletException {
		 // DispatcherServlet 서블릿 객체로 생성될 때 초기화 작업 - init() 메서드
    	 // WEB-INF/commandHandler.properties 파일을 읽어서  요청URL=CommandHandler => commandHandlerMap 추가.
    	
       //String path = "/WEB-INF/commandHandler.properties"; 경로 바뀌어도 수정 쉽게 path를 web.xml에 
        String path = this.getInitParameter("path");
       //realPath= C:\Class\JSPClass\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\jspPro\WEB-INF\commandHandler.properties
    	String realPath = this.getServletContext().getRealPath(path);  // *****
    	
    	Properties prop  = new Properties();
    	try ( FileReader fr = new FileReader( realPath ) ) {
			prop.load(fr); //자동으로 프로퍼티에 로딩
		} catch (Exception e) {
			throw new ServletException();
		}
        
        //prop -> commandHandlerMap 맵 채워넣는 작업
    	//  key = /board/list.do
    	//  value = "days08.mvc.command.ListHandler"  객체 생성
    	// commandHandlerMap 추가
    	
    	Iterator<Object> ir =  prop.keySet().iterator();
    	while (ir.hasNext()) {
			String url = (String) ir.next();   // 요청 url
			String commandHandlerFullName  = prop.getProperty(url);
		
        //풀클래스이름으로부터 객체(인스턴스) 생성 -> 맵 추가
			try {
            // 모든 유형이 될 수 있는 객체를 Class<?> = 와일드카드 
				Class<?> handlerClass =  Class.forName(commandHandlerFullName); //물리적인 클래스 파일명을 인자로 넣어주면 해당하는 클래스를 반환
				CommandHandler commandHandler = (CommandHandler) handlerClass.newInstance();  // 인스턴스 == 생성된 객체				
				
                //요청이 들어오면 맵을 뒤져 어떤 요청인지 확인 가능하게 됐다
				this.commandHandlerMap.put(url, commandHandler);
				
			} catch (ClassNotFoundException e) { 
				e.printStackTrace();
			} catch (InstantiationException e) { 
				e.printStackTrace();
			} catch (IllegalAccessException e) { 
				e.printStackTrace();
			}
			
		}
    	
	} 

	// 
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		 // 1. 요청 URL 분석   list.do, write.do, edit.do
	     String requestURI = request.getRequestURI();  //          "/jspPro/board/list.do"
	     // request.getRequestURL(); //          http://localhost/jspPro/board/list.do
	     
	     // requestURI   컨텍스트 패스 제거 
	     String contextPath = request.getContextPath();  // "/jspPro"
	     
	     if( requestURI.indexOf( contextPath)  == 0) {
	         requestURI = requestURI.substring( contextPath.length() );  //  "/board/list.do"   key
	     }
	     
	     // key : requestURI = "/board/list.do";
	     
		 // 2. 요청 URL -> 로직 처리하는 모델객체( 커맨드핸들러) 찾아서 +  request.setAttribute()/session	
	     // value = map.get(key)
	     // 인터페이스 upcasting
	    CommandHandler modelHandler = this.commandHandlerMap.get( requestURI );
	    
		// commandHandler.properties => ListHandler => new ListHandler() 객체 생성 로직 처리
	    String viewPage = null;
	    
        
        //M[View]C == JSP 페이지를 돌려줌
	    try {
	    	// list.jsp 포워딩
			viewPage = modelHandler.process(request, response);
		} catch (Exception e) { 
			e.printStackTrace();
		}
	    
		 // 3. 응답 ( View )  리다이렉트or 포워딩.
	    if ( viewPage != null ) {
			RequestDispatcher dispatcher = request.getRequestDispatcher(viewPage);
			dispatcher.forward(request, response);
		} // 
	    
	}
	
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		 doGet(request, response); // 
	}

}

 

 

6.설정파일 선언(추가) -commandHandler.properties 

요청url->커맨드핸들러

요청url->커맨드핸들러

web-inf폴더 

     ㄴcommandHandler.properties 파일을 만들기 

#requests URL=CommandHandler([M]VC)
/board/list.do=days08.mvc.command.ListHandler
/board/write.do=days08.mvc.command.WriteHandler
/board/edit.do=days08.mvc.command.EditHandler
/board/view.do=days08.mvc.command.ViewHandler

 

7.커맨드 핸들러 ->implements CommandHandler 인터페이스 오버라이딩 

 

days08.mvc.command.CommandHandler.java 는 인터페이스로 선언하고 

클래스 

days08.mvc.command.ListHandler implements  CommandHandler
days08.mvc.command.WriteHandler implements  CommandHandler
days08.mvc.command.EditHandler implements  CommandHandler
days08.mvc.command.ViewHandler implements  CommandHandler

 

days08.mvc.command.ListHandler 

package days08.mvc.command;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.util.DBconn;

import days05.board.BoardDAOImpl;
import days05.board.BoardDTO;
import days05.board.PageBlock;

public class ListHandler   implements  CommandHandler{

	@Override
	public String process(HttpServletRequest request, HttpServletResponse response) throws Exception {
		
		int currentPage = 1 ;                // 현재 페이지. 
	      int numberPerPage = 10;         // 한 페이지에 출력할 게시글 수 
	      int numberOfPageBlock = 10;  // 페이징 블럭 수   [1] 2 3 4 5 6 7 8 9 10 >  >>
	      
	      ArrayList<BoardDTO> list = null;
	      
	      // 페이징 처리
	      int totalRecords, totalPages  = 0;
	      
	      // 검색 1
	      int searchCondition = 1;   // 1,[2],3,4
	      String searchWord = "";
	      
	      Connection conn = DBconn.getConnection();
	      BoardDAOImpl dao = new BoardDAOImpl(conn);
	      try {
	         // ?currentPage X
	         // null  = > 1
	         try {  currentPage = Integer.parseInt( request.getParameter("currentpage") ); }catch(Exception e) {}      
	         
	         // 검색2
	         // 검색조건, 검색어 파라미터 넘어올 수 도 있다.
	         try {             searchCondition = Integer.parseInt( request.getParameter("searchCondition") );   }catch(Exception e) {         }
	         searchWord = request.getParameter("searchWord") == null ? "" : request.getParameter("searchWord");
	         
	         if (  searchWord.equals("")  ) {  // 검색 X
	            list = dao.select( currentPage, numberPerPage );
	            // 페이징 처리 위한 부분
	             totalRecords = dao.getTotalRecords();  // 총 레코드 수
	             totalPages = dao.getTotalPages(numberPerPage); // 총 페이지수 
	         } else {  // 검색 O
	                list = dao.search(currentPage, numberPerPage, searchCondition, searchWord);
	                totalPages = dao.getTotalPages(numberPerPage, searchCondition, searchWord);  // 검색된 총 페이지 수 
	         }
	           
	           
	           
	      } catch (SQLException e) { 
	         System.out.println("> List.doGet() Exception...");
	         e.printStackTrace();
	      }
	      DBconn.close();
	      
	      request.setAttribute("list", list);
	      
	      // 페이징 처리 부분
	      PageBlock pageBlock = new PageBlock();
	         pageBlock.setCurrentPage(currentPage);
	         pageBlock.setNumberPerPage(numberPerPage);
	         pageBlock.setNumberOfPageBlock(numberOfPageBlock);
	         
	         int startOfPageBlock = 1;
	         int endOfPageBlock ;
	         // ****
	         startOfPageBlock = (currentPage -1) /numberOfPageBlock * numberOfPageBlock +1 ;
	         endOfPageBlock = startOfPageBlock + numberOfPageBlock -1;
	         if(  endOfPageBlock > totalPages ) endOfPageBlock = totalPages;
	         
	         pageBlock.setStartOfPageBlock(startOfPageBlock);
	         pageBlock.setEndOfPageBlock(endOfPageBlock);
	         
	         if( startOfPageBlock != 1 ) pageBlock.setPrev( true );
	         if( endOfPageBlock != totalPages ) pageBlock.setNext(true);
	      
	      request.setAttribute("pageBlock", pageBlock);
		
	      //포워딩할 페이지
		return "/days08/board/list.jsp";
	}

}

days08.mvc.command.WriteHandler

package days08.mvc.command;

import java.sql.Connection;
import java.sql.SQLException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.util.DBconn;

import days05.board.BoardDAOImpl;
import days05.board.BoardDTO;

public class WriteHandler implements CommandHandler{

	@Override
	public String process(HttpServletRequest request, HttpServletResponse response) throws Exception {
		
		//System.out.println("> WriteHandler.process() 호출됨...");
		
		if(  request.getMethod().equals("GET") ) {    // get방식요청   새 게시글 작성 write.jsp 포워딩.
			return "/days08/board/write.jsp";
		}else if( request.getMethod().equals("POST") ){  // post 방식요청
			
			// 새 게시글 정보를 DB 저장
			// list.do 리다이렉트 
			request.setCharacterEncoding("UTF-8");
			
			// 1. 파라미터 -> BoardDTO dto 생성
			String writer = request.getParameter("writer");  
			String pwd = request.getParameter("pwd");
			String email = request.getParameter("email");
			String title = request.getParameter("title");
			String content = request.getParameter("content");
			int tag = Integer.parseInt( request.getParameter("tag") );
			
			BoardDTO dto = new BoardDTO();
			dto.setWriter(writer);
			dto.setPwd(pwd);
			dto.setEmail(email);
			dto.setTitle(title);
			dto.setContent(content);
			dto.setTag(tag);		
			
			// 2. insert( dto )
			Connection conn = DBconn.getConnection();
			BoardDAOImpl dao = new BoardDAOImpl(conn);
			int rowCount = 0;
			try {
				rowCount = dao.insert(dto);
			} catch (SQLException e) { 
				System.out.println("> Write.java doPost() Exception...");
				e.printStackTrace();
			}
			DBconn.close();
			
			// 3.  list.htm 리다이렉트 요청   ->   List.java 서블릿 호출 ->   list.jsp 포워딩
			String location = "/jspPro/board/list.do";
			if( rowCount == 1)    location +="?write=success";
			response.sendRedirect(location); 
			
		}else {  // PUT, DELETE, UPDATE 등등
			response.sendError( HttpServletResponse.SC_METHOD_NOT_ALLOWED  );
		}
		
		return null;
	}

}

days08.mvc.command.EditHandler

package days08.mvc.command;

import java.sql.Connection;
import java.sql.SQLException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.util.DBconn;

import days05.board.BoardDAOImpl;
import days05.board.BoardDTO;

public class EditHandler implements CommandHandler{

	@Override
	public String process(HttpServletRequest request, HttpServletResponse response) throws Exception {
		if(  request.getMethod().equals("GET") ) {   
			
			int seq = Integer.parseInt(request.getParameter( "seq"));			
			Connection conn = DBconn.getConnection();
			BoardDAOImpl dao = new BoardDAOImpl(conn);
			BoardDTO dto = null;
			try { 
				 dto = dao.view(seq);			 
				 request.setAttribute("dto", dto);			  
			} catch (SQLException e) { 
				System.out.println("> Edit.doGet() Exception...");
				e.printStackTrace();
			}
			DBconn.close();
			return "/days08/board/edit.jsp";
			
		}else if( request.getMethod().equals("POST") ){  // post 방식요청
			
			request.setCharacterEncoding("UTF-8");
			
			//System.out.println("> Edit.doPost() 호출됨.");
			// /cstvsboard/edit.htm?seq=364
			int seq = Integer.parseInt(request.getParameter( "seq"));
			
			// 1. 파라미터 -> BoardDTO dto 생성
			// String writer = request.getParameter("writer");  
			String pwd = request.getParameter("pwd");
			String email = request.getParameter("email");
			String title = request.getParameter("title");
			String content = request.getParameter("content");
			int tag = Integer.parseInt( request.getParameter("tag") );
			
			BoardDTO dto = new BoardDTO();
			//dto.setWriter(writer);
			dto.setPwd(pwd);
			dto.setEmail(email);
			dto.setTitle(title);
			dto.setContent(content);
			dto.setTag(tag);		
			dto.setSeq(seq);  // 수정할 글번호
			
			// 2. insert( dto )
			Connection conn = DBconn.getConnection();
			BoardDAOImpl dao = new BoardDAOImpl(conn);
			int rowCount = 0;
			try {
				rowCount = dao.update(dto);
			} catch (SQLException e) { 
				System.out.println("> View.doPost() Exception...");
				e.printStackTrace();
			}
			DBconn.close();
			
			// 3.  list.htm 리다이렉트 요청   ->   List.java 서블릿 호출 ->   list.jsp 포워딩
			String location = "/jspPro/board/view.do?seq="+seq;
			if( rowCount == 1)    location +="&edit=success";
			else                           location +="&edit=fail";
			response.sendRedirect(location); 
			
		}else {  // PUT, DELETE, UPDATE 등등
			response.sendError( HttpServletResponse.SC_METHOD_NOT_ALLOWED  );
		}
		
		return null;
	}

}

days08.mvc.command.ViewHandler

package days08.mvc.command;

import java.sql.Connection;
import java.sql.SQLException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.util.DBconn;

import days05.board.BoardDAOImpl;
import days05.board.BoardDTO;

public class ViewHandler implements CommandHandler{

	@Override
	public String process(HttpServletRequest request, HttpServletResponse response) throws Exception {
		// days05.board.View.java
		
		// System.out.println("> View.doGet() 호출됨...");
		int seq = Integer.parseInt(request.getParameter( "seq"));
		
		Connection conn = DBconn.getConnection();
		BoardDAOImpl dao = new BoardDAOImpl(conn);
		BoardDTO dto = null;
		try {
		    // 트랜잭션 처리 +  서비스 클래스 
			// ㄱ. 
			 dao.increaseReaded(seq);
			 // ㄴ.
			 dto = dao.view(seq);			 
			 request.setAttribute("dto", dto);			  
		} catch (SQLException e) { 
			System.out.println("> View.doGet() Exception...");
			e.printStackTrace();
		}
		DBconn.close();
		
		return "/days08/board/view.jsp";
	}

}

days08.mvc.command.DeleteHandler

package days08.mvc.command;

import java.sql.Connection;
import java.sql.SQLException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.util.DBconn;

import days05.board.BoardDAOImpl;
import days05.board.BoardDTO;

public class DeleteHandler implements CommandHandler{

	@Override
	public String process(HttpServletRequest request, HttpServletResponse response) throws Exception {
		 
		if(  request.getMethod().equals("GET") ) {    			
			return "/days08/board/delete.jsp";			
		}else if( request.getMethod().equals("POST") ){  // post 방식요청
			
			request.setCharacterEncoding("UTF-8");
			// System.out.println("> Delete.doPost() 호출됨.");
			int seq = Integer.parseInt( request.getParameter("seq") );  // delete.htm?seq=641
			String pwd = request.getParameter("pwd");  // 입력받은 비밀번호
			 
			
			// 2. insert( dto )
			Connection conn = DBconn.getConnection();
			BoardDAOImpl dao = new BoardDAOImpl(conn);
			int rowCount = 0;
			try {
				BoardDTO dto = dao.view(seq);
				String originalPwd =  dto.getPwd(); // null 반환 X   pwd 반환
				if( pwd.equals(originalPwd) ) {
					// 삭제
					rowCount = dao.delete(seq);
				}else {
					// 비밀번호 잘못되었다 경고. 
					// 삭제 delete.jsp 
					request.setAttribute("error", "비밀번호가 틀립니다.");
					return "/days08/board/delete.jsp";
				}
			} catch (SQLException e) { 
				System.out.println("> Delete.doPost() Exception...");
				e.printStackTrace();
			}
			DBconn.close();
			
			// 3.  list.htm 리다이렉트 요청   ->   List.java 서블릿 호출 ->   list.jsp 포워딩
			String location = "/jspPro/board/list.do";
			if( rowCount == 1)    location +="?delete=success";
			response.sendRedirect(location); 
			
		}else {  // PUT, DELETE, UPDATE 등등
			response.sendError( HttpServletResponse.SC_METHOD_NOT_ALLOWED  );
		}
		
		return null;
		
	}

}

days08.mvc.commandHandler 인터페이스 

package days08.mvc.command;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public interface CommandHandler {
	
	// 로직 처리 메서드
	// 리턴자료형 String  :   "list.jsp",   "write.jsp"
	// 포워딩, 리다이렉트      +   JSP 페이지                               클래스 
	public String process(HttpServletRequest request, HttpServletResponse response) throws Exception;

}

 

8.DispatcherServlet init(), doGet()구현

 

9./board/list.do 요청=>ListHandler.process() 구현 

days05/board/list.jsp 복사+붙이기 

 

list.jsp

<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ include file="/include.jspf" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>2022. 6. 20. - 오후 12:43:01</title>
<link rel="shortcut icon" type="image/x-icon" href="../images/SiSt.ico">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>

<style>
table, td, th {
	border: solid 1px gray;
}

table {
	border-spacing: 3px;
	border-collapse: separate;
}

table, tr, td {
	/* border-radius: 3px; */
	/* padding:3px;  */
	
}

tbody tr  td:nth-of-type(2) {
	text-align: left;
}

a {
	text-decoration: none;
	color: black;
}

a:hover {
	color: red;
}
</style>
<!-- 페이징 처리 style -->
<style>
.pagination {
	margin: 0 auto;
	display: flex;
	justify-content: center;
}

.pagination a {
	color: black;
	float: left;
	padding: 4px 8px;
	text-decoration: none;
	transition: background-color .3s;
}

.pagination a.active {
	background-color: dodgerblue;
	color: white;
}

.pagination a:hover:not (.active ) {
	background-color: #ddd;
}
</style>
<style>
.searchWord {
	background-color: yellow;
	color: red;
}
</style>
<style>
.title {
	display: inline-block;
	white-space: nowrap;
	width: 90%;
	overflow: hidden;
	text-overflow: ellipsis;
}
</style>

</head>
<body>

<h3>days08/board/list.jsp</h3>

<div align="center">
  <h2>목록 보기</h2>
  <a href="<%= contextPath %>/board/write.do">글쓰기</a>
  <table style="width:600px;">
    <thead>
	    <tr>
	        <th width="10%">번호</th>
	        <th width="45%">제목</th>
	        <th width="17%">작성자</th>
	        <th width="20%">등록일</th>
	        <th width="10%">조회</th>
	      </tr>
    </thead>
    <tbody>
      <!-- empty EL 연산자 -->
      <c:if test="${  empty list }">
        <tr>
          <td colspan="5">등록된 게시글이 없습니다.</td>
        </tr>
      </c:if>
      <!-- not EL 연산자 -->
      <c:if test="${ not empty list }">
      	<!-- request.setAttribute("list", list); -->	
         <c:forEach items="${ list }" var="dto">
            <tr>
	           <td>${ dto.seq }</td>
	           <td><a href="<%= contextPath %>/board/view.do?seq=${ dto.seq }">${ dto.title }</a></td>
	           <td><a href="mailto:${ dto.email }">${ dto.writer }</a></td>
	           <td>${ dto.writedate }</td>
	           <td>${ dto.readed }</td>
	         </tr>
         </c:forEach>         
      </c:if>
    </tbody>
    <tfoot>
      <tr>
        <td colspan="5" align="center">
          <div class="pagination"> 
          <%-- 
            <a href="#" class="active"> 1 </a> 
            <a href="<%= contextPath %>/cstvsboard/list.htm?currentpage=2"> 2 </a> 
            <a href="<%= contextPath %>/cstvsboard/list.htm?currentpage=3"> 3 </a> 
            <a href="<%= contextPath %>/cstvsboard/list.htm?currentpage=4"> 4 </a> 
            <a href="<%= contextPath %>/cstvsboard/list.htm?currentpage=5"> 5 </a> 
            <a href="<%= contextPath %>/cstvsboard/list.htm?currentpage=6"> 6 </a> 
            <a href="<%= contextPath %>/cstvsboard/list.htm?currentpage=7"> 7 </a> 
            <a href="<%= contextPath %>/cstvsboard/list.htm?currentpage=8"> 8 </a> 
            <a href="<%= contextPath %>/cstvsboard/list.htm?currentpage=9"> 9 </a> 
            <a href="<%= contextPath %>/cstvsboard/list.htm?currentpage=10"> 10 </a> 
            <a href="<%= contextPath %>/cstvsboard/list.htm?currentpage=11"> &raquo; </a>
             --%> 
             <!-- request.setAttribute("pageBlock", pageBlock); -->
             <!-- << -->
             <c:if test="${ pageBlock.prev }">
                <a href="<%= contextPath %>/cstvsboard/list.htm?currentpage=${ pageBlock.startOfPageBlock -1 }">&laquo;</a>
                <!--  &searchCondigion=${ param.searchCondition}&seachWord=${ param.searchWord }   -->
             </c:if>
             <c:forEach begin="${ pageBlock.startOfPageBlock }" end="${ pageBlock.endOfPageBlock }" step="1" var="i">
                
                <c:if test="${  i == pageBlock.currentPage }">
                   <a href="#" class="active">${ i }</a>
                </c:if>
             
               <c:if test="${  i != pageBlock.currentPage  }">
                   <a href="<%= contextPath %>/cstvsboard/list.htm?currentpage=${ i}">${ i }</a>
               </c:if>
               
             </c:forEach>
             <!-- >> -->
             <c:if test="${ pageBlock.next }">
                <a href="<%= contextPath %>/cstvsboard/list.htm?currentpage=${ pageBlock.endOfPageBlock +1 }">&raquo;</a>
             </c:if>
          </div>
        </td>
      </tr>
      <tr>
        <td colspan="5" align="center">
          <form method="get">
             <select name="searchCondition" id="searchCondition">
              <option value="1">title</option>
              <option value="2">content</option>
              <option value="3">writer</option>
              <option value="4">title+content</option>
            </select>
            <input type="text" name="searchWord" id="searchWord" />
            <input type="submit" value="search" />
          </form>
        </td>
      </tr>
    </tfoot>
  </table>
</div>

<script>
    // list.htm?write=success
    if( '<%= request.getParameter("write") %>' == 'success'){
    	alert("글 쓰기 완료!!!");
    }	
    
    // list.htm?delete=success
    if( '<%= request.getParameter("delete") %>' == 'success'){
    	alert("글 삭제 완료!!!");
    }
</script>
<script>
  // 검색 후 검색조건,검색어 상태 유지(관리)
  // EL  안에서 삼항 연산자를 사용가능
  $("#searchCondition").val( '${ empty param.searchCondition ? 1  : param.searchCondition }' );
  $("#searchWord").val('${ param.searchWord}');
  
  // /list.htm?currentpage=2&searchCondigion=3&seachWord=검색
 $(".pagination a:not(.active)").attr("href", function ( i, val ){
	 return val + "&searchCondition=${ param.searchCondition}&searchWord=${ param.searchWord }"; 
 });		  
</script>
</body>
</html>

write.jsp

<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ include file="/include.jspf" %>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>2022. 6. 20. - 오후 2:48:41</title>
<link rel="shortcut icon" type="image/x-icon" href="../images/SiSt.ico">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>

<style>
table, td, th {
	border: solid 1px gray;
}

table {
	border-spacing: 3px;
	border-collapse: separate;
}

table, tr, td {
	/* border-radius: 3px; */
	/* padding:3px;  */
	
}
</style>

</head>
<body>

<h3>days05/board/write.jsp</h3>

<div align="center">
  <h2>글 쓰기</h2>
  <!-- 
  action 생략 : http://localhost/jspPro/board/write.do
   -> WriteHandler(request).java 서블릿  
       if( POST 방식 ){
          //
       }
    -->
  <form method="post">
  
  <table style="padding: 2px; width: 600px">
			<tr>
				<td colspan="2" align="center"><b>글을 적어주세요</b></td>
			</tr>
			<tr>
				<td align="center">이름</td>
				<td><input type="text" name="writer" size="15"
					autofocus="autofocus" required="required"></td>
			</tr>
			<tr>
				<td align="center">비밀번호</td>
				<td><input type="password" name="pwd" size="15" required="required"></td>
			</tr>
			<tr>
				<td align="center">Email</td>
				<td><input type="email" name="email" size="50" ></td>
			</tr>
			<tr>
				<td align="center">제목</td>
				<td><input type="text" name="title" size="50" required="required"></td>
			</tr>
			<tr>
				<td align="center">내용</td>
				<td><textarea name="content" cols="50" rows="10"></textarea></td>
			</tr>
			<tr>
				<td align="center">HTML</td>
				<td><input type="radio" name="tag" value="1" checked>적용
					<input type="radio" name="tag" value="0">비적용</td>
			</tr>
			<tr>
				<td colspan="2" align="center">
				  <input type="submit" value="작성 완료">
				  &nbsp;&nbsp;&nbsp; 
				  <input type="reset" value="다시 작성">
				  &nbsp;&nbsp;&nbsp; 
				  <a href="<%= contextPath %>/board/list.do">Home</a>
				</td>
			</tr>
		</table>
  
  </form>
</div>

</body>
</html>

 

view.jsp

<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ include file="/include.jspf" %>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>2022. 6. 21. - 오전 10:31:55</title>
<link rel="shortcut icon" type="image/x-icon" href="../images/SiSt.ico">

<!-- jquery ui 모달창 -->
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<link rel="stylesheet" href="/resources/demos/style.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script> 
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
 
<style>
  table{
     border-spacing: 3px;
     border-collapse: separate; 
   }
   table,  tr, td {
      border:solid 1px gray;
      /* border-radius: 3px;  
      padding:3px;   */ 
   }
   
 #tblContent{
   width:600px;
 } 
</style>

</head>
<body>

<h3>view.jsp</h3>

<div align="center">
  <h2>내용보기</h2>
  <!-- <table id="tblContent" class="table"> -->
  <table id="tblContent">
   <tr>
       <td>이름</td>
       <td>${ dto.writer }</td>
       <td>등록일</td>
       <td>${ dto.writedate }</td>
   </tr>
   <tr>
       <td>Email</td>
       <td><a href="mailto:${ dto.email }">${ dto.email }</a></td>
       <td>조회</td>
       <td>${ dto.readed }</td>
   </tr>
   <tr>
        <td>제목</td>
        <td colspan="3">${ dto.title }</td>
   </tr>
   <tr>
       <td colspan="4" style="padding:15px;height: 200px;text-align: left;vertical-align: top">
       ${ dto.content }
       </td>
   </tr>
   <tr>
       <td colspan="4" align="center">
           <a class="btn btn-secondary"  href="<%= contextPath %>/board/edit.do?seq=${ dto.seq }" id="editLink">수정하기</a>
           <a class="btn btn-secondary"  href="<%= contextPath %>/board/delete.do?seq=${ dto.seq }" id="deleteLink">삭제하기</a>
           <a class="btn btn-secondary"  href="<%= contextPath %>/board/list.do" id="homeLink">HOme</a>
           
           <input class="btn btn-secondary"  type="button"  id="btnModalDelete" value="모달창으로 글삭제">
       </td>
   </tr>
</table>
</div>

<!-- 삭제 모달창 div 태그 -->
<div id="dialog-form" align="center" title="삭제">
  <h2>삭제하기</h2>
  <!-- http://localhost/jspPro/cstvsboard/view.htm?seq=349 -->
  <form action="<%= contextPath %>/board/delete.do?seq=${ param.seq }" method="post">
	<table>
	  <tr>
	    <td colspan="2" align="center"><b>글을 삭제합니다</b></td>
	  </tr>
	  <tr>
	    <td align="center">비밀번호</td>
	    <td>
	      <input type="password" name="pwd" size="15" autofocus="autofocus">
	    </td>
	  </tr>
	  <tr>
	    <td colspan="2" align="center">
	      <input type="submit" value="삭제">&nbsp;&nbsp;
	      <input type="button" id="cancel" value="취소">
	      <!-- 프로젝트할 때 hidden 타입 사용 이유 ?  -->
	      <%-- <input type="hidden" name= "seq" value="${ param.seq }"> --%>
	    </td>
	  </tr>
	</table>
  </form>  
</div>

<script>
  // 1. 
  dialog = $("#dialog-form").dialog({
	  autoOpen: false,
      height: 400,
      width: 350,
      modal: true,
      buttons:{},
      close: function (){
    	  form[0].reset();
      }
  });
  
  //2.
  form = dialog.find("form");
  
 // 3. 모달창 열기
  $("#btnModalDelete").on("click", function(event) {
	  dialog.dialog("open" ); 
  })
  // 4. 모달창 닫기
  $("#cancel").on("click", function(event) {
	  dialog.dialog("close" ); 
  })
</script>

<script>

   if( '<%= request.getParameter("edit") %>' == "success" ){
	   alert("글 수정 완료!!!");
   }else if( '<%= request.getParameter("edit") %>' == "fail"  ){
	   alert("글 수정 실패(비밀번호 잘못)!!!");
   }

</script>
</body>
</html>

delete.jsp

<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ include file="/include.jspf" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>2022. 6. 21. - 오후 12:14:39</title>
<link rel="shortcut icon" type="image/x-icon" href="../images/SiSt.ico">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>

<style>
 table , td, th {
   border:solid 1px gray;
 }
 table{
     border-spacing: 3px;
     border-collapse: separate;
   }
   table,  tr, td {
    /* border-radius: 3px; */
    /* padding:3px;  */
   }
 table{
    width: 600px;
 }
</style>

</head>
<body>

<h3>delete.jsp</h3>

<div align="center">
  <h2>삭제하기</h2>
  <form method="post">
	<table>
	  <tr>
	    <td colspan="2" align="center"><b>글을 삭제합니다</b></td>
	  </tr>
	  <tr>
	    <td align="center">비밀번호</td>
	    <td>
	      <input type="password" name="pwd" size="15" autofocus="autofocus">
	    </td>
	  </tr>
	  <tr>
	    <td colspan="2" align="center">
	      <input type="submit" value="삭제">&nbsp;&nbsp;
	      <input type="button" id="cancel" value="취소">
	    </td>
	  </tr>
	</table>
  </form>
</div>

<!-- EL + JSTL -->
<%
     String error = (String)request.getAttribute("error");
     if( error != null ){
%>
   <script>
      alert("<%= error %>");
   </script>
<%    	 
     }
%>

<script>
  $("#cancel").on("click", function (){
	  // history.go(-1);  ***
	  // 조회수 증가 + 게시글 보기
	  location.href="<%= contextPath %>/cstvsboard/view.htm?seq=${ param.seq }";
  });
</script>
</body>
</html>

 

 

10. days08/board/list.jsp 확인

 days05/board/list.jsp 복사+붙이기

 

11.테스트 

 

12.글쓰기

jsp 파일 안에 경로 바꾸기   

ㄱ.list.jsp 

<a href="<%=contextPath %>/board/write.do">글쓰기</a>

ㄴ.board/write.do (GET 방식)

Writehandler.java 코딩수정 

doGet() , write.jsp

ㄷ.days08/board/write.jsp 복사 붙이기 

 

-------

 

 

 

글쓰기 작업이 안된다 ->

데이터베이스에 저장도 안되고 

request.getMethod().equals("POST") 여기도 안되는 것 이다. 

 

해결방법 2:55

doPost에 doGet()메소드 추가 

 

 

  • 각각의 경로를 찾아가기 위한 것이 contextPath
  • db연동하려면 ojdbc6.jar web-lib 에 추가해야함 
  • dbcp설정  meta-inf  폴더 -context.xml f
  • web.xml에 <resouce-ref> 
  • com.util.  ConnectionProvider.java getConnection() 
  • conn.close() ->닫는게 아니라 커넥션 풀 반환 (재사용 ) 
  • mvc 패턴 구현  
    • MV[C]컨트롤러 구현 -단 하나의 서블릿  
    • DispatcherServlet.java  
      • MVC역할 
    • web.xml에 서블릿 등록 - url패턴에 모든 요청을 받기위해 *.do 를 넣어준다. 
    • 핸들러객체 CommandHandler 인터페이스 String process(request,response)   ->ListHandler.java WriteHandler.java 등등
    • commandHandler.properties -> init() 함수로 요청url과 핸들러를 map객체에 넣어준다.
    • post를 호출하더라도 doGet()익 실행되도록 doPost(){ doGet(r,r);}
    • get 방식으로 요청했을때-> 경로를 리턴(포워딩), post 방식, 그외의 방식
    • post 방식 -> String location = "/jspPro/board/list.do";로 리다이렉트  ,   if(rowCount ==1 ) location += "?write=success"; 제대로 작동되었는지도 확인 
    •  

'JSP' 카테고리의 다른 글

[JSP] EmpDeptList를 MVC패턴으로 구현  (0) 2022.06.29
[JSP] ServletContextListener 인터페이스 활용 방법  (0) 2022.06.24
[JSP] JSTL  (0) 2022.06.23
[JSP] EL을 사용해서 쿠키를 읽고 쓰기  (0) 2022.06.23
[JSP] EL  (0) 2022.06.22
Comments