Jam's story
[JSP] MVC 패턴 본문
컨트롤러(서블릿)가 가운데서 모든것을 관리한다.
-비즈니스 로직을 처리하는 모델과 결과 화면을 보여주는 뷰를 분리한다.
-어플리케이션의 흐름제어나 사용자의 처리요청은 컨트롤러에 집중한다.
컨트롤러= 서블릿
모델= 로직처리 클래스, 자바빈
뷰 =jsp
사용자 = 웹브라우저나 기기
클라이언트에서 웹 브라우저를 띄어서 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"> » </a>
--%>
<!-- request.setAttribute("pageBlock", pageBlock); -->
<!-- << -->
<c:if test="${ pageBlock.prev }">
<a href="<%= contextPath %>/cstvsboard/list.htm?currentpage=${ pageBlock.startOfPageBlock -1 }">«</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 }">»</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="작성 완료">
<input type="reset" value="다시 작성">
<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="삭제">
<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="삭제">
<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 |