일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 상관서브쿼리
- sleep()메소드
- ID중복
- String char[] 형변환
- 동기화
- 상관 서브 쿼리
- interrupted()
- interrupt()
- include액션태그
- InputDialog
- 리눅스셋팅
- Linux셋팅
- include지시자
- 아이디중복
- isinterrupted()
- include 지시자
- first-child
- Daemon()
- ThreadGroup()
- Linux세팅
- 메모리스트림
- first-of-child
- 리눅스세팅
- 표현 언어
- char[] String 형변환
- StringWriter
- MemoryStream
- 스레드그룸
- ObjectInputStream
- StringReader
- Today
- Total
다연이네
[days08] MVC 패턴 본문
MVC 패턴
mvc 패턴을 알려면
모델1 구조와 모델 2구조를 알아야 한다.
모델1 구조는 클라이언트가 요청하면 JSP/Servlet이 응답해주는 구조이다. 클 <->JSP/Servlet
장점) 직관적으로 연결되어 쉽다.
단점) 로직코드와 뷰 코드가 혼합되어 JSP 코드가 복잡해지며, 유지보수가 힘들다.
코드 중복이 발생하기 쉽다
웹사이트는 유지보수가 빈번히 발생하기 때문에 모델1을 사용하지 않는다.
모델2는 MVC 패턴으로, 로직-모델, 뷰 코드-뷰 로 분리하여 컨트롤러라는 서블릿이 모든 요청에 대한 흐름 제어를 한다.
로직 코드와 뷰 코드를 분리해 유지보수가 쉬워지며, 컨트롤러 서블릿에서 권한 검사나 인증과 같은 공통 기능 처리가
가능하다.
장점) 유지보수가 쉽다, 확장이 용이하다.
단점) 작업량이 많고 접근이 어렵다.
더 오래걸리고 힘들더라도 mvc 패턴을 사용해야 한다.
1. [MVC 패턴]
- 모델 1 구조 (유지보수 어려움)
클라이언트 -(요청)-> JSP/Servlet
<-(응답)-
- 모델 2 구조 (==MVC 패턴)
클 -(요청)-> [C]ontroller
list.do list.do -> 컨트롤러가 서블릿 객체를 찾아 일 시킴 -> 로직 처리(모델[M]odel)
//(실질적으로 로직 처리하는 애는 모델 객체이고 그 모델 객체를 찾는 역할은 컨트롤러가 )
list.do(컨트롤러에게 결과물 돌아옴) <- request.setAttribute(ArrayList <> list)
<-(응답)- <-
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연동, 일부분인 것)
ex10.jsp -> 인터페이스 -> 컨트롤러 (+ web.xml, xxx.properties) -> 모델(핸들러) -> 컨트롤러 -> 뷰
ex10.jsp
<%@ page 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">
<title>Insert title here</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="">
<style>
</style>
<script>
$(document).ready(function (){
});
</script>
</head>
<body>
<!--
MVC 패턴의 구현 방법을 설명할 때
컨트롤러(서블릿)가 해야할 두 번째 작업은 사용자가 어떤 것을 요청했는지 분석하는 작업
> 요청 분석하는 방법 (두 가지 사용) *여기서 요청은 : 글쓰기인지, 글보기 인지, ... 등
ㄱ. 특정 이름의 파라미터에 명령어 정보를 전달(?cmd=boardList)
예) 게시판 글 목록 요청
http://localhost:80/jspPro/controller(임의대로)?cmd=boardList
http://localhost:80/jspPro/controller(임의대로)?cmd=boardContent&seq=20
ㄴ. 요청URI 자체에 명령어를 사용
예) 게시판 글 목록 요청
http://localhost:80/jspPro/board/list/1 (1페이지)
http://localhost:80/jspPro/board/content/20 (20번 글 내용)
-->
<!-- 1 모델 (Model) implements CommandHandler -->
<!-- days08.mvc.command.CommandHandler 인터페이스 (우리가 정함)
모든 모델 객체가 구현할 인터페이스 -->
<!-- 2 컨트롤러로 요청이 들어왔는데 요청을 처리할 모델 객체가 없다면 NullHandler 클래스가 처리하도록 -->
<!-- days08.mvc.command.NullHandler -->
<!-- 3 컨트롤러 - 서블릿 클래스 -->
<!-- days08.mvc.command.ControllerUsingFile -->
<!-- 5 -->
<!-- 4 어떤 요청이 들어오면 어떤 모델 객체가 처리해야하는지 설정하는 파일 -->
<!-- WEB-INF > commandHandler.properties -->
<!-- 컨트롤러가 목록을 보고 어떤 요청이 들어오면 어떤 모델로 처리할지 알 수 있도록 -->
<!-- *.do -> 모든 요청은 컨트롤러가 처리 -->
<a href="/jspPro/hello.do">/jspPro/hello.do</a><br>
<a href="/jspPro/board/list.do">/jspPro/board/list.do</a><br>
<a href="/jspPro/board/write.do">/jspPro/board/write.do</a><br>
</body>
</html>
인터페이스
CommandHandler.java
package days08.mvc.command;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//로직을 처리할 모델(Model)객체가 공통적으로 구현할 인터페이스
public interface CommandHandler {
// 리턴자료형 String (내맘) - 뷰(View ==JSP)
public String process( HttpServletRequest request
, HttpServletResponse response ) throws Exception ;
//인터페이스니까 몸체가 있으면 안됨
}
NullHandler.java
컨트롤러로 요청이 들어왔는데 요청을 처리할 모델 객체가 없다면 NullHandler 클래스가 처리
package days08.mvc.command;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class NullHandler implements CommandHandler{
@Override
public String process(HttpServletRequest request, HttpServletResponse response) throws Exception {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
//요청에 대해 응답을 찾을 수 없다는 에러메시지를 보내겠다
return null;
}
}
web.xml
<servlet>
<servlet-name>Controller</servlet-name>
<servlet-class>days08.mvc.command.ControllerUsingFile</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>Controller</servlet-name>
<url-pattern>*.do</url-pattern> <!--확장자가 do인 모든 -->
</servlet-mapping>
commandHandler.properties
# Request = Model
/hello.do=days08.mvc.hello.HelloHandler
/board/list.do=days08.mvc.board.ListHandler
/board/write.do=days08.mvc.board.WriteHandler
/board/content.do=days08.mvc.board.ContentHandler
Controller
ControllerUsingFile.java
package days08.mvc.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;
//MV[C] - 컨트롤러(서블릿)
public class ControllerUsingFile extends HttpServlet{
//오버라이딩 - 제네릭서블릿 (destroy, init)
@Override
public void destroy() {
// 웹 컨테이너 안에서 생성된 서블릿이 제거될때 호출되는 메소드
}
private Map<String, CommandHandler> commandHandlerMap =
new HashMap<String, CommandHandler>();
@Override
public void init() throws ServletException {
// 웹 컨테이너 안에서 처음 서블릿이 생성될때 호출되는 메소드
// 초기화 작업
// ㄱ. /WEB-INF/commandHandler.properties 파일을 읽어와
// 서블릿(컨트롤러)이 어떤 요청에 어떤 모델이 처리하는지 알 수 있어야 함
//String path = "/WEB-INF/commandHandler.properties"; 경로 바뀌어도 수정 쉽게 path를 web.xml에 주자
String path = getInitParameter("path");
String configFilePath = getServletContext().getRealPath(path);
//System.out.println(configFilePath);
//C:\Class\JSPClass\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps
// \jspPro\WEB-INF\commandHandler.properties
Properties prop = new Properties();
try(FileReader fr = new FileReader(configFilePath)) {
prop.load(fr); //자동으로 프로퍼티에 로딩
} catch (Exception e) {
throw new ServletException(e);
}
//prop -> commandHandlerMap 맵 채워넣는 작업
Iterator<Object> ir = prop.keySet().iterator(); //모든 key값에서 바로 iterator 받아오기
while (ir.hasNext()) {
String url = (String) ir.next(); //요청한 url : "/hello.do" key값
String handlerClassFullName = prop.getProperty(url); // "days08.mvc.hello.HelloHandler"
//풀클래스이름으로부터 객체(인스턴스) 생성 -> 맵 추가
try {
Class<?> handlerClass = Class.forName(handlerClassFullName); //물리적인 클래스 파일명을 인자로 넣어주면 해당하는 클래스를 반환
CommandHandler handlerInstance = (CommandHandler)handlerClass.newInstance();
this.commandHandlerMap.put(url, handlerInstance);
//요청이 들어오면 맵을 뒤져 어떤 요청인지 확인 가능하게 됐다
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
throw new ServletException(e);
}
}
}//init
@Override
protected void doGet(HttpServletRequest request
, HttpServletResponse response) throws ServletException, IOException {
String requestURI = request.getRequestURI();
//System.out.println(requestURI); // "/jspPro/hello.do"
String contextPath = request.getContextPath(); // "/jspPro"
if( requestURI.indexOf(contextPath)==0) { //요청 url이 그 contextPath로 시작하더라
int beginIndex = contextPath.length();
requestURI = requestURI.substring(beginIndex); //앞에 /jspPro 잘림 (endIndex 안주면 끝까지)
}
//System.out.println(requestURI); // "/hello.do"
//Model을 찾고 있는 중
//핸들러(handler) =모델
CommandHandler handler = this.commandHandlerMap.get(requestURI);
//일 시켜야 함
//M[View]C == JSP 페이지를 돌려줌
String viewPage = null;
try {
viewPage = handler.process(request, response);
} catch (Exception e) {
e.printStackTrace();
}
//포워딩 or 리다이렉트
if(viewPage!=null) {
RequestDispatcher dispatcher = request.getRequestDispatcher(viewPage);
dispatcher.forward(request, response);
}
}//doGet
@Override
protected void doPost(HttpServletRequest request
, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}//doPost
}//class
Model 1
-HelloHandler.java
package days08.mvc.hello;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import days08.mvc.command.CommandHandler;
//Model
public class HelloHandler implements CommandHandler {
@Override
public String process(HttpServletRequest request, HttpServletResponse response) throws Exception {
//일처리
//
//
request.setAttribute("greeting", "안녕하세요... MVC 이해하죠~");
return "/days08/ex10_hello.jsp"; //View(JSP 페이지)
}
}
View 1
-ex10_hello.jsp
<%@ page 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">
<title>Insert title here</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="">
<style>
</style>
<script>
$(document).ready(function (){
});
</script>
</head>
<body>
<h3>ex10_hello.jsp</h3>
<!-- MVC 패턴 : 처리 -->
${requestScope.greeting }<br>
${greeting }<br>
</body>
</html>
Model 2
-ListHandler.java
package days08.mvc.board;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import javax.servlet.RequestDispatcher;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.util.ConnectionProvider;
import com.util.DBConn;
import days05.board.BoardDTO;
import days05.board.PageBlock;
import days08.mvc.command.CommandHandler;
public class ListHandler implements CommandHandler{
@Override
public String process(HttpServletRequest request, HttpServletResponse response) throws Exception {
String pCurrentPage = request.getParameter("currentPage");
int currentPage = pCurrentPage == null ? 1 : Integer.parseInt(pCurrentPage);
String pPumberPerPage = request.getParameter("numberPerPage");
int numberPerPage = pPumberPerPage == null ? 10 : Integer.parseInt(pPumberPerPage);
// 검색 추가 코딩
String pSearchCondition = request.getParameter("searchCondition");
int searchCondition = pSearchCondition == null ? 1 : Integer.parseInt(pSearchCondition);
String searchWord = request.getParameter("searchWord");
if( searchWord == null || searchWord == "") searchWord = "*";
//
request.setAttribute("searchWord", searchWord);
request.setAttribute("searchCondition", searchCondition);
//DBCP dbconn -> connprovider
Connection con = ConnectionProvider.getConnection();
PreparedStatement pstmt = null;
ResultSet rs = null;
String sql =" SELECT * " +
" FROM ( " +
" SELECT rownum no, t.* " +
" FROM ( " +
" SELECT seq, title, writer, writedate, readed " +
" , case when ( sysdate - writedate) between 0 and 1/24 then 'true' else 'false' end newmark " +
" FROM TBL_CSTVSBOARD ";
switch (searchCondition) {
case 1: // 제목
sql += " WHERE regexp_like( title , ? , 'i' ) ";
break;
case 2: // 내용
sql += " WHERE regexp_like( content , ? , 'i' ) ";
break;
case 3: // 작성자
sql += " WHERE regexp_like( writer , ? , 'i' ) ";
break;
case 4: // 제목 + 내용
sql += " WHERE regexp_like( title , ? , 'i' ) OR regexp_like( content , ? , 'i' ) ";
break;
} // switch
sql += " ORDER BY seq DESC " +
" ) t " +
" ) b " +
" WHERE b.no BETWEEN ? AND ? ";
int start = (currentPage - 1)*numberPerPage+1;
int end = currentPage*numberPerPage;
ArrayList<BoardDTO> list = null;
try {
pstmt = con.prepareStatement(sql);
// BETWEEN ? AND ?
pstmt.setInt(1, start);
pstmt.setInt(2, end);
// 검색 조건 1/2/3/4
if (searchCondition == 4 ) {
// 검색조건 4 Wherer ? or ? Between ? And ?
pstmt.setString(1, searchWord);
pstmt.setString(2, searchWord);
pstmt.setInt(3, start);
pstmt.setInt(4, end);
} else {
pstmt.setString(1, searchWord);
pstmt.setInt(2, start);
pstmt.setInt(3, end);
}
rs = pstmt.executeQuery();
int seq;
String title;
String writer;
Date writedate; // java.sql.Date 타입.
int readed;
boolean newmark ;
BoardDTO dto = null;
if (rs.next()) {
list = new ArrayList<BoardDTO>();
do {
// 글번호 글제목 글쓴이 작성일 조회수
seq = rs.getInt("seq");
title = rs.getString("title");
if( searchCondition == 1 && !searchWord.equals("*")) {
title = title.replace(searchWord
, String.format("<span class=\"searchWord\">%s</span>", searchWord) );
}
writer = rs.getString("writer");
writedate = rs.getDate("writedate");
readed = rs.getInt("readed");
//newmark = rs.getBoolean("newmark"); //
newmark = Boolean.parseBoolean(rs.getString("newmark"));
dto = new BoardDTO();
dto.setSeq(seq);
dto.setTitle(title);
dto.setWriter(writer);
dto.setWritedate(writedate);
dto.setReaded(readed);
dto.setNewmark(newmark); //
list.add(dto);
} while (rs.next());
} // if
} catch (SQLException e1) {
e1.printStackTrace();
}finally {
try {
rs.close();
pstmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
} // try 현재 페이지 게시글 ArrayList 채워넣는 코딩
// *** 페이징 처리 시작~ ***
// 페이징 처리할 때 필요한 것을 필드로 가지는 클래스 선언 : PageBlock
// (ㄱ). 현재페이지 (ㄴ). 한페이지당 게시글수 ㄷ. 페이지블럭 ㄹ. 페이지블럭 시작, 끝 ㅁ. 이전, 다음
// 1. 총페이지수 계산
int totalPages = 0;
sql = "SELECT count(*) totalRecords , CEIL(count(*)/?) totalPages"
+" FROM TBL_CSTVSBOARD ";
switch (searchCondition) {
case 1: // 제목
sql += " WHERE regexp_like( title , ? , 'i' ) ";
break;
case 2: // 내용
sql += " WHERE regexp_like( content , ? , 'i' ) ";
break;
case 3: // 작성자
sql += " WHERE regexp_like( writer , ? , 'i' ) ";
break;
case 4: // 제목 + 내용
sql += " WHERE regexp_like( title , ? , 'i' ) OR regexp_like( content , ? , 'i' ) ";
break;
} // switch
try {
pstmt = con.prepareStatement(sql);
pstmt.setInt(1, numberPerPage);
pstmt.setString(2, searchWord);
if (searchCondition == 4 ) pstmt.setString(3, searchWord);
rs = pstmt.executeQuery();
if( rs.next() )
totalPages = rs.getInt("totalPages");
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
pstmt.close();
rs.close();
//DBConn.close();
con.close(); // DBCP 반환
} catch (SQLException e) {
e.printStackTrace();
}
} // try 총페이지 수 처리 블럭.
int numberOfPageBlock = 10;
int startOfPageBlock = (currentPage-1)/numberOfPageBlock*numberOfPageBlock+1;
int endOfPageBlock = startOfPageBlock + numberOfPageBlock -1;
if( endOfPageBlock > totalPages ) endOfPageBlock = totalPages;
// 2.
PageBlock pageBlock = new PageBlock();
pageBlock.setCurrentPage(currentPage);
//pageBlock.setNumberPerPage(numberPerPage);
//pageBlock.setNumberOfPageBlock(numberOfPageBlock);
pageBlock.setStart(startOfPageBlock);
pageBlock.setEnd(endOfPageBlock);
pageBlock.setPrev( startOfPageBlock != 1 ? true : false );
pageBlock.setNext( endOfPageBlock != totalPages ? true : false );
// 포워딩~
// ?currentPage=1&numberPerPage=10 list.jsp 파라미터 전달 O
request.setAttribute("list", list);
request.setAttribute("pageBlock", pageBlock);
return "/days08/board/ex10_list.jsp";
}//process
}//class
View 2
-ex10_list.jsp
<%@page import="days05.board.PageBlock"%>
<%@page import="java.util.Iterator"%>
<%@page import="days05.board.BoardDTO"%>
<%@page import="java.util.ArrayList"%>
<%@ page pageEncoding="UTF-8" contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>SS13 - k≡n¡k ( 2020. 12. 29 - t오후 2:25:17 )</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="">
<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>
<script>
$(document).ready(function (){
// list.htm?write=success
if( '<%= request.getParameter("write") %>' == 'success' ){
alert("글 쓰기 완료!!!");
}
// 상태 유지
$("#searchCondition").val( '${ requestScope.searchCondition }');
$("#searchWord").val('${ param.searchWord}');
$(".pagination a").attr("href", function (i, val){
return val
+"&searchCondition=${ requestScope.searchCondition}&searchWord=${ param.searchWord}";
});
/*
$(".pagination a")
.eq("${ pageBlock.currentPage / 10 -1 }")
.addClass("active")
.attr("href","#");
*/
// ?seq=1
$("a.title").attr("href", function (i, val){
return val
+"¤tPage=${ param.currentPage }&searchCondition=${ requestScope.searchCondition}&searchWord=${ param.searchWord}";
});
});
</script>
</head>
<body>
<!-- <h3>list.jsp</h3> -->
<div align="center">
<h2>목록 보기 - EL+ JSTL</h2>
<a href="/jspPro/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>
<c:if test="${ empty list }">
<tr><td colspan="5">등록된 게시글이 없습니다.</td></tr>
</c:if>
<c:if test="${ not empty list }">
<c:forEach items="${ list }" var="dto">
<tr align="center">
<td>${ dto.seq }</td>
<td>
<a class="title" href="/jspPro/board/content.do?seq=${ dto.seq }">${ dto.title }</a>
<c:if test="${ dto.newmark }">
<img src="/jspPro/days08/board/images/ico-new.gif" alt="" />
</c:if>
</td>
<td>
<c:if test="${ dto.writer eq 'kenik' }">
<img src="/jspPro/days08/board/images/star.gif" alt="" />
</c:if>
<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">
<c:if test="${ pageBlock.prev }">
<a href="/jspPro/board/list.do?currentPage=${ pageBlock.start-1 }"> « </a>
</c:if>
<c:forEach begin="${ pageBlock.start }" end="${ pageBlock.end }" var="i" >
<a class="${ i eq pageBlock.currentPage ? 'active':'' }" href="/jspPro/board/list.do?currentPage=${ i }">${ i }</a>
</c:forEach>
<c:if test="${ pageBlock.next }">
<a href="/jspPro/board/list.do?currentPage=${ pageBlock.end+1 }"> » </a>
</c:if>
</div>
</td>
</tr>
<tr>
<td colspan="5" align="center">
<form>
<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>
<!-- GET 방식 요청 -->
<a href="/jspPro/board/write.do">글쓰기</a>
</div>
</body>
</html>
Model 3
-WriteHandler.java
package days08.mvc.board;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.util.DBConn;
import days08.mvc.command.CommandHandler;
public class WriteHandler implements CommandHandler{
@Override
public String process(HttpServletRequest request, HttpServletResponse response) throws Exception {
//글쓰기 작업시 get/ post 달리 해야함 if로 나누자
//request.getMethod() : GET /POST 돌림(대문자로)
if(request.getMethod().equalsIgnoreCase("GET")) {
return "/days08/board/ex10_write.jsp"; //그 자체로 포워딩이니 경로만 주자
}else if(request.getMethod().equalsIgnoreCase("POST")) {
request.setCharacterEncoding("UTF-8");
String writer = request.getParameter("writer");
String pwd = request.getParameter("pwd");
String email = request.getParameter("email");
String title = request.getParameter("title");
int tag = Integer.parseInt( request.getParameter("tag") );
String content = request.getParameter("content");
Connection con = DBConn.getConnection();
PreparedStatement pstmt = null;
String sql = "INSERT INTO TBL_CSTVSBOARD "
+ " ( seq, writer, pwd, email, title, tag, content ) "
+ " VALUES ( SEQ_TBL_CSTVSBOARD.NEXTVAL, ?, ?, ?, ?, ?, ? )";
int rowCount = 0;
try {
pstmt = con.prepareStatement(sql);
pstmt.setString(1, writer );
pstmt.setString(2, pwd );
pstmt.setString(3, email );
pstmt.setString(4, title );
pstmt.setInt(5, tag );
pstmt.setString(6, content );
rowCount = pstmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
pstmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
} // try
// redirect list.htm
String location = "/jspPro/board/list.do";
if( rowCount == 1 ) location +="?write=success";
response.sendRedirect(location);
}
return null;
}
}
View 3
-ex10_write.jsp
<%@page import="java.util.Iterator"%>
<%@page import="days05.board.BoardDTO"%>
<%@page import="java.util.ArrayList"%>
<%@ page pageEncoding="UTF-8" contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>write.jsp</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="">
<style>
table, td, th {
border: solid 1px gray;
}
table {
border-spacing: 3px;
border-collapse: separate;
}
table, tr, td {
/* border-radius: 3px; */
/* padding:3px; */
}
</style>
<script>
$(document).ready(function (){
});
</script>
</head>
<body>
<!-- <h3>write.jsp</h3> -->
<div align="center">
<h2>글 쓰기</h2>
<!-- [기억] action 속성 설정 되지 않으면 http://localhost/jspPro/cstvsboard/write.htm 요청 -->
<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="/jspPro/board/list.do">Home</a>
</td>
</tr>
</table>
</form>
</div>
</body>
</html>
Model 4
-ContentHandler.java
package days08.mvc.board;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.servlet.RequestDispatcher;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.util.ConnectionProvider;
import com.util.DBConn;
import days05.board.BoardDTO;
import days08.mvc.command.CommandHandler;
public class ContentHandler implements CommandHandler{
@Override
public String process(HttpServletRequest request, HttpServletResponse response) throws Exception {
int seq = Integer.parseInt(request.getParameter("seq"));
Connection con = ConnectionProvider.getConnection();
PreparedStatement pstmt = null;
ResultSet rs = null;
// 1. 조회수 증가
String sql = "UPDATE TBL_CSTVSBOARD "
+ " SET readed = readed + 1 "
+ " WHERE seq = ?";
int rowCount = 0;
try {
pstmt = con.prepareStatement(sql);
pstmt.setInt(1, seq);
rowCount = pstmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
pstmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
// 2. 게시글 얻어오는 코딩.
sql = "SELECT seq, writer, title, content, readed, writedate , email "
+ " FROM TBL_CSTVSBOARD "
+ " WHERE seq = ?";
BoardDTO dto = null;
try {
pstmt = con.prepareStatement(sql);
pstmt.setInt(1, seq);
rs = pstmt.executeQuery();
if (rs.next()) {
// seq, writer, title, content, readed, writedate
dto = new BoardDTO();
dto.setSeq( rs.getInt("seq"));
dto.setWriter(rs.getString("writer"));
dto.setTitle(rs.getString("title"));
dto.setContent(rs.getString("content"));
dto.setReaded( rs.getInt("readed"));
dto.setWritedate(rs.getDate("writedate"));
dto.setEmail(rs.getString("email"));
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
rs.close();
pstmt.close();
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
} // try
request.setAttribute("dto", dto);
String path = "/days08/board/ex10_content.jsp";
RequestDispatcher dispatcher = request.getRequestDispatcher(path);
dispatcher.forward(request, response);
return null;
}
}
View 4
-ex10_content.jsp
<%@page import="days05.board.BoardDTO"%>
<%@ page pageEncoding="UTF-8" contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
BoardDTO dto = (BoardDTO) request.getAttribute("dto");
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>content.jsp</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- 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>
<!-- bootstrap4 -->
<!--
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.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>
<script>
$(document).ready(function (){
$("#homeLink")
.attr("href"
, "/jspPro/cstvsboard/list.htm?currentPage=${ param.currentPage }&searchCondition=${ param.searchCondition}&searchWord=${ param.searchWord}");
$("#btnModalDelete").on("click", function(event) {
// 객체.메서드("open")
dialog.dialog("open");
});
$("#cancel").on("click", function(event) {
// 객체.메서드("open")
dialog.dialog("close");
});
dialog = $( "#dialog-form" ).dialog({
autoOpen: false,
height: 400,
width: 350,
modal: true,
buttons: {
/* "Create an account": addUser,
Cancel: function() {
dialog.dialog( "close" );
} */
},
close: function() {
form[ 0 ].reset();
//allFields.removeClass( "ui-state-error" );
}
});
form = dialog.find( "form" );
});
</script>
</head>
<body>
<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="/jspPro/cstvsboard/edit.htm?seq=${dto.seq}" id="editLink">수정하기</a>
<a class="btn btn-secondary" href="/jspPro/cstvsboard/delete.htm?seq=${dto.seq}" id="deleteLink">삭제하기</a>
<a class="btn btn-secondary" href="#" id="homeLink">Home</a>
<input class="btn btn-secondary" type="button" id="btnModalDelete" value="모달창으로 글 삭제">
</td>
</tr>
</table>
</div>
<!-- 삭제 모달창 -->
<div id="dialog-form" align="center" title="삭제">
<h2>삭제하기</h2>
<form action="/jspPro/cstvsboard/delete.htm" 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" onClick="javascript:history.back();" value="취소"> -->
<input type="button" id="cancel" value="취소">
</td>
</tr>
</table>
<input type="hidden" name="seq" value="${ param.seq }" />
</form>
</div>
</body>
</html>
게시글 제목 클릭시 |
내용 보기로 이동 |
'JSP' 카테고리의 다른 글
[days09] 필터 - 모든 파일에 setCharacterEncoding("UTF-8"); (0) | 2021.01.06 |
---|---|
[days09] 필터(Filter) (0) | 2021.01.06 |
[days08] JSTL이 제공하는 EL함수 (0) | 2021.01.05 |
[days08] 숫자 및 날짜 포맷팅 처리 태그 (fmt) (0) | 2021.01.05 |
[days08] c태그들 (c:if, c:choose, c:forEach, c:forTokens, c:url, c:redirect c:out, c:catch) (0) | 2021.01.05 |