본문 바로가기

JSP & Servlet

회원제 게시판(02), JSTL과 EL 21. 03. 19.

회원제 게시판(02)

1. BoardDao.java에 나머지 메소드들 채워줌. (findBy, modity, remove)

 

	public Board findBy(Integer boardno) {
		Board result = null;
		Connection conn = DBConn.getConnection();
		String sql = "SELECT BOARDNO, TITLE, CONTENT, USERID, REGDATE, HITCOUNT, PARENTNO, CATEGORY\r\n" + 
				"FROM BOARD\r\n" + 
				"WHERE BOARDNO = ?\r\n";
		try {
			PreparedStatement pstmt = conn.prepareStatement(sql);
			pstmt.setInt(1, boardno);
			
			ResultSet rs = pstmt.executeQuery();
			while(rs.next()) {
				int idx = 1;
				result = new Board();
				result.setBoardno(rs.getInt(idx++));
				result.setTitle(rs.getString(idx++));
				result.setContent(rs.getString(idx++));
				result.setUserid(rs.getString(idx++));
				result.setRegdate(rs.getString(idx++));
				result.setHitcount(rs.getInt(idx++));
				result.setParentno(rs.getInt(idx++));
				result.setCategory(rs.getInt(idx++));
			}
			
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return result;
	}

 

executeQuery()의 리턴 타입은 ResultSet!!!

 

	public void modify(Board board) {
		Connection connection = DBConn.getConnection();
		// 문장 작성
		try {

		// 전처리 문장을 선언
		String sql = "UPDATE BOARD SET\r\n" + 
				"    TITLE = ?,\r\n" + 
				"    CONTENT = ?,\r\n" + 
				"    REGDATE = SYSDATE\r\n" + 
				"WHERE BOARDNO = ?";
		
		// 전처리 문장 생성
		PreparedStatement pstmt = connection.prepareStatement(sql);
		
		int idx = 1;
		pstmt.setString(idx++, board.getTitle());
		pstmt.setString(idx++, board.getContent());
		pstmt.setInt(idx++, board.getBoardno());
		
		
		
		// 실행
		pstmt.executeUpdate();
		}
		catch (SQLException e) {
			e.printStackTrace();
		}		
	}

- 쿼리문 가져와서 ""에 붙여넣기하고 ?로 바꿀 때 ?, 콤마 잘 확인하기!

- 수정 되는 부분 : 제목, 내용, 글번호

 

	public int remove(Integer boardno) {
		int ret = 0;
		Connection connection = DBConn.getConnection();
		// 문장 작성
		try {

		// 전처리 문장을 선언
		String sql = "DELETE BOARD WHERE BOARDNO = ?";
		
		// 전처리 문장 생성
		PreparedStatement pstmt = connection.prepareStatement(sql);
		
		int idx = 1;
		pstmt.setInt(idx++, boardno);
		
		
		
		// 실행
		ret = pstmt.executeUpdate();
		}
		catch (SQLException e) {
			e.printStackTrace();
		}
		return ret;
	}

- void remove였던 걸 int remove로 바꿈.

- 왜 !?

executeUpdate() 리턴 타입이 int라 !! 반영 된 행의 개수를 나타냄. (숫자값으로 성공/실패를 확인할 수 있음.)

- try catch 때문에 바로 return pstmt.executeUpdate();하면 안 되고 int ret = 0; 을 해서 ret에 담아야 함.

작성 후 실행을 했을 때 오류가 났는데, pstmt.executeUpdate(); 에서 오류가 난 건 저 메소드를 실행하려고 할 때 전처리 문장에서 오류가 난 것 이었음. ,를 쓰지 말아야 할 곳에 썼었던 것.

 

 

(수정) write 메소드

 

	public void write(Board board) {
		Connection connection = DBConn.getConnection();
		// 문장 작성
		try {

		// 전처리 문장을 선언
		String sql = "INSERT INTO BOARD(BOARDNO, TITLE, CONTENT, USERID, PARENTNO, CATEGORY)\r\n" + 
				"VALUES (SEQ_BOARD.NEXTVAL, ?, ?, ?, ?, ?)";
		
		// 전처리 문장 생성
		PreparedStatement pstmt = connection.prepareStatement(sql);
		
		int idx = 1;
		pstmt.setString(idx++, board.getTitle());
		pstmt.setString(idx++, board.getContent());
		pstmt.setString(idx++, board.getUserid());
		pstmt.setObject(idx++, board.getParentno());
		pstmt.setInt(idx++, board.getCategory());
		
		// 실행
		pstmt.executeUpdate();
		}
		catch (SQLException e) {
			e.printStackTrace();
		}
	}

- Parentno가 null 값이 될 수 있어서 null 처리를 해야 했는데 setObject로 수정했음.

 

 

BoardDao.java (오늘의 최종)

 

package board.dao;

import java.sql.Connection;
import java.sql.JDBCType;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import board.vo.Board;
import member.vo.Member;
import util.DBConn;

public class BoardDao {
	public void write(Board board) {
		Connection connection = DBConn.getConnection();
		// 문장 작성
		try {

		// 전처리 문장을 선언
		String sql = "INSERT INTO BOARD(BOARDNO, TITLE, CONTENT, USERID, PARENTNO, CATEGORY)\r\n" + 
				"VALUES (SEQ_BOARD.NEXTVAL, ?, ?, ?, ?, ?)";
		
		// 전처리 문장 생성
		PreparedStatement pstmt = connection.prepareStatement(sql);
		
		int idx = 1;
		pstmt.setString(idx++, board.getTitle());
		pstmt.setString(idx++, board.getContent());
		pstmt.setString(idx++, board.getUserid());
		pstmt.setObject(idx++, board.getParentno());
		pstmt.setInt(idx++, board.getCategory());
		
		
		
		// 실행
		pstmt.executeUpdate();
		}
		catch (SQLException e) {
			e.printStackTrace();
		}
	}
	public static void main(String[] args) {
		BoardDao dao = new BoardDao();
//		Board board = new Board("자바에서 쓴 글 제목", "자바에서 쓴 글 내용", "javava", 1, 1);
//		dao.write(board);
		System.out.println("====목록조회====");
		dao.list(1).forEach(System.out::println);
		
		System.out.println("====상세조회====");
		System.out.println(dao.findBy(1));
		System.out.println(dao.findBy(3));
		
		System.out.println("====수정확인====");
		dao.modify(new Board(2, "자바에서 수정된 글 제목", "자바 내용"));
		System.out.println(dao.findBy(2));
		
		System.out.println("====삭제 후 반영 행 개수 확인====");
		System.out.println(dao.remove(3));
		System.out.println(dao.remove(4));
		
		System.out.println("====목록조회====");
		dao.list(1).forEach(System.out::println);
	}

	public List<Board> list(Integer category) {
		ArrayList<Board> result = null;
		Connection conn = DBConn.getConnection();
		String sql = "SELECT BOARDNO, TITLE, CONTENT, USERID, CASE\r\n" + 
				"	WHEN SYSDATE - REGDATE < 1 THEN TO_CHAR(REGDATE, 'HH24:MI:SS')\r\n" + 
				"	ELSE TO_CHAR(REGDATE, 'YY/MM/DD')\r\n" + 
				"END REGDATE, HITCOUNT, PARENTNO, CATEGORY\r\n" + 
				"FROM BOARD\r\n" + 
				"WHERE CATEGORY = ? AND BOARDNO > 0\r\n" + 
				"ORDER BY 1 DESC";
		try {
			PreparedStatement pstmt = conn.prepareStatement(sql);
			pstmt.setInt(1, category);
			
			ResultSet rs = pstmt.executeQuery();
			result = new ArrayList<Board>();
			while(rs.next()) {
				int idx = 1;
				Board board = new Board();
				board.setBoardno(rs.getInt(idx++));
				board.setTitle(rs.getString(idx++));
				board.setContent(rs.getString(idx++));
				board.setUserid(rs.getString(idx++));
				board.setRegdate(rs.getString(idx++));
				board.setHitcount(rs.getInt(idx++));
				board.setParentno(rs.getInt(idx++));
				board.setCategory(rs.getInt(idx++));
				result.add(board);
			}
			
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return result;
	}

	public Board findBy(Integer boardno) {
		Board result = null;
		Connection conn = DBConn.getConnection();
		String sql = "SELECT BOARDNO, TITLE, CONTENT, USERID, REGDATE, HITCOUNT, PARENTNO, CATEGORY\r\n" + 
				"FROM BOARD\r\n" + 
				"WHERE BOARDNO = ?\r\n";
		try {
			PreparedStatement pstmt = conn.prepareStatement(sql);
			pstmt.setInt(1, boardno);
			
			ResultSet rs = pstmt.executeQuery();
			while(rs.next()) {
				int idx = 1;
				result = new Board();
				result.setBoardno(rs.getInt(idx++));
				result.setTitle(rs.getString(idx++));
				result.setContent(rs.getString(idx++));
				result.setUserid(rs.getString(idx++));
				result.setRegdate(rs.getString(idx++));
				result.setHitcount(rs.getInt(idx++));
				result.setParentno(rs.getInt(idx++));
				result.setCategory(rs.getInt(idx++));
			}
			
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return result;
	}

	public void modify(Board board) {
		Connection connection = DBConn.getConnection();
		// 문장 작성
		try {

		// 전처리 문장을 선언
		String sql = "UPDATE BOARD SET\r\n" + 
				"    TITLE = ?,\r\n" + 
				"    CONTENT = ?,\r\n" + 
				"    REGDATE = SYSDATE\r\n" + 
				"WHERE BOARDNO = ?";
		
		// 전처리 문장 생성
		PreparedStatement pstmt = connection.prepareStatement(sql);
		
		int idx = 1;
		pstmt.setString(idx++, board.getTitle());
		pstmt.setString(idx++, board.getContent());
		pstmt.setInt(idx++, board.getBoardno());
		
		
		
		// 실행
		pstmt.executeUpdate();
		}
		catch (SQLException e) {
			e.printStackTrace();
		}		
	}

	public int remove(Integer boardno) {
		int ret = 0;
		Connection connection = DBConn.getConnection();
		// 문장 작성
		try {

		// 전처리 문장을 선언
		String sql = "DELETE BOARD WHERE BOARDNO = ?";
		
		// 전처리 문장 생성
		PreparedStatement pstmt = connection.prepareStatement(sql);
		
		int idx = 1;
		pstmt.setInt(idx++, boardno);
		
		
		
		// 실행
		ret = pstmt.executeUpdate();
		}
		catch (SQLException e) {
			e.printStackTrace();
		}
		return ret;
	}

}

 

2. list.jsp

 

jsp를 노출시키지 않으려고 파일 경로를 WebContent밑이 아닌 WEB-INF안에 둠.

-> (서블릿으로만 접근 가능함.) 컨트롤러를 통해서만 접근 가능.

 

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<jsp:include page="../../../template/header.jsp"/>
${list}
<jsp:include page="../../../template/footer.jsp"/>

- 브라우저에 헤더 풋터 사이에 게시판 목록이 잘 뜨는지 확인.

- 만들어 둔 css를 적용하려면 header.jsp에 css 링크 수정.

<link rel="stylesheet" href="/member_board/assets/css/common.css">

 

 

3. board.controller.BoardList.java

package board.controller;

import java.io.IOException;
import java.util.List;

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 board.service.BoardService;
import board.service.BoardServiceImpl;
import board.vo.Board;

@WebServlet("/board/list")
public class BoardList extends HttpServlet{

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		BoardService service = new BoardServiceImpl();
		List<Board>list = service.list(1); // 자유게시판 목록
//		System.out.println(list); 로그 찍는 작업
		req.setAttribute("list", list);
		req.getRequestDispatcher("../WEB-INF/jsp/board/list.jsp").forward(req, resp);	
	}
}

- service.list(1)이 아직 return null;이기 때문에 채워주러 감!

- List<Board>list가 담길 곳은 req.setAttribute

(req 요청하는 동안에만 해당 attribute를 지정. 무엇을? "list"이름의 list 타입을)

 

3-1. BoardServiceImpl.java

 

package board.service;

import java.util.List;

import board.dao.BoardDao;
import board.vo.Board;

public class BoardServiceImpl implements BoardService{
	private BoardDao boardDao = new BoardDao();
	@Override
	public void write(Board board) {
		boardDao.write(board);
	}

	@Override
	public List<Board> list(Integer category) {
		return boardDao.list(category);
	}

	@Override
	public Board findBy(Integer boardno) {
		return boardDao.findBy(boardno);
	}

	@Override
	public void modify(Board board) {
		boardDao.modify(board);
	}

	@Override
	public void remove(Integer boardno) {
		boardDao.remove(boardno);
	}

}

 

- 후에 fileDao도 써야 하기 때문에 BoardDao 타입의 변수명을 dao가 아닌 풀네임을 써주자!


 

14. JSTL(JSP Standard Tag Library)과 EL(Expression Langueage)

(jstl과 lombok 라이브러리 사용)

 

EL의 개요

JSP 스크립트 태그(<%=%>)를 대신하여 JSP 값들을 좀 더 편리하게 출력하기 위해 제공되는 언어.
목적 : 영역 객체에 저장된 변수에 접근하기 위해 사용.
결국 JSP에서 자바코드를 없애기 위해서 사용하며 JSP 실행 시 EL 인터프리터에 의해 번역되어 실행됨.
자바클래스의 메소드에 대한 호출 가능.
가장 큰 장점 : null 처리
사용법 : test 변수를 표현 할 때 -> ${test}

 

EL의 내장 객체

pageScope
requestScope
sessionScope
applicationScope
pageContext
↓맵형 객체(key,value) 쌍으로 저장하는 객체
param
paramValues
header
headerValues
cookie (※ 쿠키를 굽는 건 Servlet, 확인은 jsp)
intParam

 

EL의 연산자

.
[]
()
x ? a : b
empty : 값이 NULL이거나 컬렉션의 사이즈가 0일 경우 true를 반환.
+ - * / %
&& (and), || (or), ! (not)
== (eq)
!= (ne)
< (lt)
> (gt)
<= (le)
>= (ge)

 

 

 

el.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="ko">
<head>
	<meta charset="UTF-8">
	<title>2021. 3. 19. 오후 12:49:57</title>
	<script src="//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
</head>
<body>
	<%
		String str = "hello";
	pageContext.setAttribute("page", "페이지값");
	request.setAttribute("req", "요청값");
	session.setAttribute("sess", "세션값");
	application.setAttribute("app", "어플값");
	
	pageContext.setAttribute("key", "페이지값");
	request.setAttribute("key", "요청값");
	session.setAttribute("key", "세션값");
	application.setAttribute("key", "어플값");
	%>
	<p><%=str %></p>
	<p>${str}</p> <!-- 안 나옴. -->
	
	<p><%=pageContext.getAttribute("page") %></p>
	<p>${page}</p>
	<p>${req}</p>
	<p>${sess}</p>
	<p>${app}</p>
	
	<h3>${key}</h3>
	<h3>${sessionScope.key}</h3>
	
	<form>
		<input type="text" name="name">
		소고기 <input type="checkbox" name="meat" value="beef">
		돼지고기 <input type="checkbox" name="meat" value="pork">
		닭고기 <input type="checkbox" name="meat" value="chicken">
		<button>전송</button>
	</form>
	<h2>표현식을 사용하였을 때</h2>
	<h3>이름: <%=request.getParameter("name") %></h3>
<%--<h3>고기들: <%=request.getParameterValues("meat")[0] %></h3>
	<h3>고기들: <%=request.getParameterValues("meat")[1] %></h3>
	<h3>고기들: <%=request.getParameterValues("meat")[2] %></h3> --%>
	<h2>표현 언어를 사용하였을 때</h2>
	<h3>이름: ${param.name}</h3>
	<h3>고기들: ${paramValues["meat"][0]}</h3>
	<h3>고기들: ${paramValues.meat[1]}</h3>
	<h3>고기들: ${paramValues.meat[2]}</h3>
	<h3>저장된 쿠키: ${cookie.idsave}</h3> <!-- 챕터 14라 쿠키가 없음ㅋㅋ -->
	
	<h4>\${5+7} : ${5+7}</h4>
	<h4>\${5-7} : ${5-7}</h4>
	<h4>\${5*7} : ${5*7}</h4>
	<h4>\${5/7} : ${5/7}</h4> <!-- 정수가 아닌 실수로 나옴. -->
	<h4>\${5%7} : ${5%7}</h4>
</body>
</html>

- ${key} 같은 변수가 여러 개면 가장 좁은 범위로 출력됨. -> 결과 : 페이지값

- 특정 범위를 지정하려면 변수 앞에 ${범위.변수}

 

 

el.jsp의 큰 장점인 null 처리

 

 

- 배열 내용 확인는 법 : 인덱스 사용

연관배열도 됨!! ${paramValues["meat"][0]}

- 자바에서 배열을 사용 할 때 인덱스 범위를 벗어나는 오류를 피하기 위해 고군분투 했는데 EL에선 이 부분이 자유로움.

 

 

JSTL core

등록 방법

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

 

종류

출력 태그 : <c:out> 少 (escape 처리 땐 必)
변수 설정 및 삭제 태그 :<c:set>, <c:remove> 특정 영역
예외 처리 태그 : <c:catch>
조건 처리 태그 : <c:if>, <c:choose> 多, <c:when>, <c:otherwise>
반복 처리 태그 : <c:forEach>, <c:forTokens>
페이지 처리 태그 : <c:import> (include), <c:redirect>, <c:url>, <c:param>
<c:set var="변수명" value="설정값" target="객체" property="값" scope="범위"></c:set>
<c:if test="조건" var="변수명" scope="범위">
<c:choose>
    <c:when test="조건"> </c:when>
    <c:otherwise></c:otherwise>
</c:choose>
<c:forEach begin="시작 인덱스" end="끝 인덱스" items="객체명" step="증감식" var="변수명" varStatus="상태 변수">

 

 

Emp.java

package chapter14;

import lombok.Data;

@Data
public class Emp {
	private String ename;
	private int sal;
	private int deptno;
}

 

 

jstl1.jsp

<%@page import="java.util.ArrayList"%>
<%@page import="java.util.HashMap"%>
<%@page import="chapter14.Emp"%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html lang="ko">
<head>
	<meta charset="UTF-8">
	<title>2021. 3. 19. 오후 2:28:12</title>
	<script src="//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
</head>
<body>
	<%
		Emp emp = new Emp();
		emp.setEname("SMITH");
		emp.setDeptno(101);
		emp.setSal(5000);
		
		request.setAttribute("emp", emp);
	%>
	<jsp:useBean id="emp2" class="chapter14.Emp"/>
	<jsp:setProperty property="ename" name="emp2" value="SCOTT"/>
	<c:set var="myStr" scope="request" value="Hello World"/>
<pre>	
	${emp}
	${emp.ename}
	${emp.sal}
	${emp.deptno}
	
	${emp2}
	${emp2.ename}
	${emp2.sal}
	${emp2.deptno}
	
	${myStr}
	
	<c:remove var="emp2"/>
	${emp2}
	<c:set var="" value="" target="" property="" scope=""></c:set>
</pre>
<h2>&lt;c:if>문&lt;/c:if></h2>
<c:if test="${5 > 7}">
	<h3>5 > 7</h3>
</c:if>
<c:if test="${5 < 7}">
	<h3>5 &lt; 7</h3>
</c:if>
<c:set var="score" value="85"/>
<c:choose>
	<c:when test="${score >= 90 }">
		<h3>A학점</h3>
	</c:when>
	<c:when test="${score >= 80 }">
		<h3>B학점</h3>
	</c:when>
	<c:when test="${score >= 70 }">
		<h3>C학점</h3>
	</c:when>
	<c:when test="${score >= 60 }">
		<h3>D학점</h3>
	</c:when>
	<c:otherwise><h3>F학점</h3></c:otherwise>
</c:choose>
 <%
 	HashMap<String, String> map = new HashMap<>();
 	map.put("A", "가");
 	map.put("B", "나");
 	map.put("C", "다");
 	map.put("D", "라");
 	
 	request.setAttribute("map", map);
 	
 	ArrayList<Integer> list = new ArrayList<>();
 	list.add(15);
 	list.add(5);
 	list.add(1);
 	list.add(3);
 	list.add(20);
 	
 	request.setAttribute("list", list);
 %>
 <c:forEach begin="2" end="9" var="i">
 	<c:forEach var="j" begin="1" end="9">
 		<h4>${i } * ${j } = ${i*j}</h4>
 	</c:forEach>
 </c:forEach>
<c:forEach items="${map }" var="m">
	<h4>${m }</h4>
</c:forEach>
<c:forEach items="${list}" var="l">
	<h4>${l}</h4>
</c:forEach>

<c:forTokens items="a, b, c, d, e, f, g, h" delims=", " var="a">
	<h4>${a}</h4>
</c:forTokens>



	<%-- <%
		Emp emp; //c:set과 같은 말.
	%> --%>
</body>
</html>

 

Hello World 밑에 remove 돼서 빈 공간

 

- <pre>는 자동 줄바꿈 태그

 

 

회원제 게시판(02) 이어서

 

- 이 list는 BoardList.java에서 만든

 

- 23번 줄의 list를 쓴 것. request 상태인 lit.jsp에서 확인하는 것!!

 

 

4. list.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<jsp:include page="../../../template/header.jsp"/>
	<table>
		<tr>
			<th>글번호</th>
			<th>제목</th>
			<th>작성자</th>
			<th>작성일</th>
			<th>조회수</th>
		</tr>
		<c:forEach items="${list}" var="board">
		<tr>
			<td>${board.boardno}</td>
			<td><a href="detail?boardno=${board.boardno}">${board.title}</a></td>
			<td>${board.userid}</td>
			<td>${board.regdate}</td>
			<td>${board.hitcount}</td>
		</tr>
		</c:forEach>
	</table>
<jsp:include page="../../../template/footer.jsp"/>

 

5. 게시글 작성 시간이 하루를 넘기면 날짜를, 넘기지 않으면 작성 시간을 표시하도록.

DB에서 작업 후 BoardDao.java로 가져와서 sql쪽 수정.

-- 목록조회
SELECT BOARDNO, TITLE, CONTENT, USERID,
CASE
WHEN SYSDATE - REGDATE < 1 THEN TO_CHAR(REGDATE, 'HH24:MI:SS')
ELSE TO_CHAR(REGDATE, 'YY/MM/DD')
END REGDATE,
HITCOUNT, PARENTNO, CATEGORY
FROM BOARD
WHERE CATEGORY = 1 AND BOARDNO > 0
ORDER BY 1 DESC;

 

※ INDEX 꿀팁!
고유 인덱스를 만들 때 BOARDNO 뿐만 아니라 CATEGORY도 같이 건 다음
CREATE UNIQUE INDEX IDX_BOARD_CATEGORY ON BOARD(BOARDNO, CATEGORY);

목록 조회 쿼리에서
WHERE CATEGORY = 1 AND BOARDNO > 0
를 추가해주면 

목록 조회 시, 계획 설명을 보면 COST가 줄어 있는 걸 볼 수 있음!

 

 

6. Detail.java

package board.controller;

import java.io.IOException;
import java.util.List;

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 board.service.BoardService;
import board.service.BoardServiceImpl;
import board.vo.Board;

@WebServlet("/board/detail")
public class Detail extends HttpServlet{

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		BoardService service = new BoardServiceImpl();
		Board board = service.findBy(Integer.parseInt(req.getParameter("boardno")));// 자유게시판 목록
		req.setAttribute("board", board);
		req.getRequestDispatcher("../WEB-INF/jsp/board/detail.jsp").forward(req, resp);		
	}
}

- req.getParameter()의 타입이 String이고 findBy()의 인자 타입을 int로 바꾸기 위해 Integer.partInt를 해 줌 -> 해당 메소드를 호출한 타입은 Board타입.

 

 

6-1. detail.jsp (상세 보기. 글 하나.)

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<jsp:include page="../../../template/header.jsp"/>
	<table>
		<tr>
			<th>제목</th>
			<td colspan="5">${board.title}</td>
		</tr>
		<tr>
			<th>작성자</th>
			<td>${board.userid}</td>
			<th>작성일</th>
			<td>${board.regdate}</td>
			<th>조회수</th>
			<td>${board.hitcount}</td>
		</tr>
		<tr>
			<td colspan="6">
				${board.content}
			</td>
		</tr>
	</table>
<jsp:include page="../../../template/footer.jsp"/>

 

7. (수정) header.jsp

	<form method="post" action="<%=request.getContextPath()%>/login">
		<ul>
		<c:if test="${empty member}">
			<li><label>아이디 <input type="text" name="id" value="${cookie.idsave.value}"></label></li>
			<li><label>비밀번호 <input type="password" name="pw"></label></li>
			<li><button>로그인</button></li>
			<li>
				<label>아이디 저장
					<input type="checkbox" name="idsave" ${empty cookie.idsave.value ? '' : 'checked'}>
				</label>
			</li>
		</c:if>
		<c:if test="${!empty member}">
			<li>${member.name}님 환영합니다. <button formaction="<%=request.getContextPath()%>/logout">로그아웃</button></li>
		</c:if>
		</ul>
		</form>
		<script>
		 $("<input>").attr({type:"hidden", name:"uri", value:location.pathname+location.search}).appendTo("form");
		</script>

- id와 idsave에도 value 값이 있어야 함.

- form 태그 action에 <%=request.getContextPath()%>를 하면 프로젝트 이름인 member_board가 나옴.

- 로그인/로그아웃 서블릿을 이용하고 나면 이전 페이지로 와야 함. -> form 태그 밑에 jQuery문 써 줌.

- value 값 의미 : 상대경로와 쿼리스트링이 포함 된 것.

- attr(속성 세 개)를 담은 <input>이 <form> 태그 다음에 붙는 것.(appendTo) - </ul>과 </form> 사이.

 

8. (수정) Login.java, Logout.java

resp.sendRedirect(req.getParameter("uri"));

- 두 곳 다 sendRedirect 부분을 "uri"로 해 줌.

- 로그인/로그아웃 하고 폼으로 보내서 그 곳으로 sendRedirect.

- 게시글 상세조회 페이지에서 로그인/로그아웃 해도 그대로 상세조회 페이지에 있음.

(원래는 무조건 index.jsp로 갔었음.)