데이터융합 JAVA응용 SW개발자 기업 채용연계 연수과정 46일차 강의 정리

misung·2022년 5월 24일
0

JSP

JSTL

실습

score_form.jsp, jstl_choose_test.jsp

score_form.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<form action="jstl_choose_test.jsp">
		# 점수를 입력하세요:
		<input type="text" name="point" size="5"><input type="submit" value="확인">
	</form>
</body>
</html>

jstl_choose_test.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<%--
      jstl choose 태그와 el을 활용하여
      100점이 넘어가면 "점수를 잘못 입력하셨습니다."
      90점이 넘으면 조건을 한번 더 검사해서,
      95 ~ 100은 A+, 94 ~ 90은 A0,
      80점이 넘으면 B, 70점이 넘으면 C, 60점대는 D
      나머지는 모두 F처리하시면 됩니다.
    --%>
    <c:set var="point" value="${param.point}" />
    
    <c:choose>
    	<c:when test="${point > 100}">
    		<h3>점수를 잘못 입력하셨습니다.</h3>
    	</c:when>
    	<c:when test="${point >= 95}">
    		<h3>A+</h3>
    	</c:when>
    	<c:when test="${point >= 90}">
    		<h3>A0</h3>
    	</c:when>
    	<c:when test="${point >= 80 }">
    		<h3>B</h3>
    	</c:when>
    	<c:when test="${point >= 70 }">
    		<h3>C</h3>
    	</c:when>
    	<c:when test="${point >= 60 }">
    		<h3>D</h3>
    	</c:when>
    	<c:otherwise>
    		<h3>F</h3>
    	</c:otherwise>
    </c:choose>
</body>
</html>

<c:choose> <c:when> 태그를 사용하여 if~else if~else 문과 같은 결과를 같도록 한 예제.

jstl_foreach.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<%--
		int total = 0;
		for (int i = 1; i <= 100; i++) {
			total += i;
		}
		out.print("<h4>1부터 100까지의 누적 합 : " + total + "</h4>");
	--%>
	
	<%--
		<c:set> 태그는 변수의 생성과 동시에, 이미 동일한 이름의 변수가 존재한다면,
		기존의 데이터를 지목해서 값을 변경할 때도 사용합니다.
	 --%>
	<c:set var="total" value="0" />	
	<c:forEach var="i" begin="1" end="100" step="1">
		<c:set var="total" value="${total + i}" />
	</c:forEach>
	
	<h4>1부터 100까지의 누적합: ${total}</h4>
	
	<hr>
	
	<h4>구구단 4단</h4>
	<% for (int i = 1; i <= 9; i++) { %>
		4 x <%=i %> = <%= 4 * i %> <br>
	<% } %>
	
	<hr> 
	
	<c:forEach var="i" begin="1" end="9" step="1">
		4 x ${i} = ${4 * i} <br>
	</c:forEach>
	
	<hr>
	
	<%-- JSTL을 사용하여 구구단 2~9단 중, 짝수 단만 출력 --%>
	<c:forEach var="i" begin="2" end="9" step="2">
	 	<c:forEach var="j" begin="1" end="9">
	 		${i} * ${j} = ${i * j} <br>
	 	</c:forEach>
	 	<br>
	</c:forEach>
	
	<hr>
	
	<h2>배열이나 컬렉션 내부의 값을 출력하기</h2>
	
	<c:set var="arr" value="<%=new int[] {1, 3, 5, 7, 9}%>" />
	
	<c:forEach var="n" items="${arr}">
		${n} &nbsp;
	</c:forEach>
	
</body>
</html>

java의 for each 와 같이, <c:forEach> JSTL을 사용하여 같은 결과를 얻을 수 있다. step은 적지 않는 경우 1로 취급된다.

MVC 1, 2

MVC1

  • MVC1 모델은 로직 처리용 java 코드와 페이지를 보여주기 위한 html 코드가 혼재되어 있는 구조였다.
  • 한 jsp 페이지 안에서 표현(view), 저장(model), 처리(control)가 되므로 재사용도 힘들고 프로젝트의 규모가 커질 수록 jsp파일이 늘어나는 문제가 있었다.

MVC2

  • 웹 브라우저의 요청을 단 한 개의 Servlet이라는 컨트롤러가 받게 되었다.

  • 서블릿은 웹 브라우저의 요청을 처리한 후, 결과를 JSP 페이지(View)로 포워딩한다.

  • MVC 모델2 구조의 핵심은 모델은 로직만 처리, 뷰는 화면만 보여주기, 컨트롤러는 사용자의 요청에 대해 알맞은 모델을 사용하고 뷰를 선택하는 역할만 한다.

MVC2 실습 1. 서블릿

web.xml 에 서블릿 태그 추가

<servlet>
	<servlet-name>basic</servlet-name>
	<servlet-class>kr.co.jsp.servlet.basic.ServletBasic</servlet-class>
</servlet>

<servlet-mapping>
	<servlet-name>basic</servlet-name>
	<url-pattern>/basic</url-pattern>
</servlet-mapping>

서블릿 이름과 경로를 지정한 후, url 패턴을 지정해 준다.

패키지 생성 및 ServletBasic.java 추가

패키지 이름은 kr.co.jsp.servlet.basic

ServletBasic.java

package kr.co.jsp.servlet.basic;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import kr.co.jsp.user.model.UserDAO;
import kr.co.jsp.user.model.UserVO;

/*
	- 서블릿이란 웹 페이지를 자바 언어로만 구성하는 기법이다.
	즉, jsp 파일을 자바 언어로만 구성하는 것이다. (...con.jsp)
	
	- 톰캣을 사용하여 jsp 파일을 자동으로 class로 변환했다면,
	이제는 직접 클래스를 생성해서 클래스로 요청을 처리해 보자는 것이다.
 */

public class ServletBasic extends HttpServlet{
	
	// 서블릿 클래스를 만드는 방법
	// 1. HttpServlet 클래스를 상속
	
	// 2. 생성자를 선언 (선택)
	public ServletBasic() {
		System.out.println("페이지에 요청 들어옴!");
		System.out.println("서블릿 객체 생성!");
	}
	
	// 3. HttpServlet이 제공하는 상속 메서드를 오버라이딩(재정의)한다.
	// init, doGet, doPost, destroy() ...
	
	@Override
	public void init() throws ServletException {
		/*
		 	- 페이지 요청이 들어왔을 때, 처음 실행할 로직을 작성
		 	- init()은 컨테이너(서버 프로그램)에 의해 서블릿 객체가 생성될 때
		 	최초 1회 자동으로 호출된다.
		 	- 객체의 생성자와 비슷한 역할을 수행한다.
		 */
		System.out.println("init 메서드 호출!");
	}
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// http 통신 중 get 요청이 발생했을 때 자동으로 호출되는 메서드.
		// 매개값으로 내장객체 request와 response가 전달되므로
		// 객체의 메서드를 통해 파라미터값을 가져오거나, 페이지 이동이 가능하다.
		System.out.println("doGet 메서드가 호출!");
		
		/*
		 	- 이 안에서 getParameter(), sendRedirect() 등과 같은 메서드 사용 가능.
		 */
	}
	
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// http 통신 중 post 요청이 발생했을 때 자동으로 호출되는 메서드.
		// doGet과 마찬가지로 내장객체 request와 response를 매개값으로 받는다.	
		System.out.println("doPost 메서드가 호출!");
		
		String account = req.getParameter("account");
		UserVO vo = UserDAO.getInstance().getUserInfo(account);
	
		// 자바 클래스에서 세션을 사용하는 방법
		// request로부터 session을 얻어와 저장
		HttpSession session = req.getSession();
		session.setAttribute("user", vo);
		
		resp.sendRedirect("Servlet/info.jsp");
	}
	
	@Override
	public void destroy() {
		// 서블릿 객체가 소멸될 때 호출되는 메서드 (객체 소멸 시 1회 자동으로 호출)
		// 대부분 객체 반납이나 소멸 등에 사용.
		System.out.println("destroy 메서드가 호출!");
	}
	
	
}

일일히 함수를 자동완성으로 추가하면서 만든 케이스.
디렉토리에 우클릭 - New - Servlet으로 만드는게 훨씬 편하다.

로직을 미리 추가해두긴 했는데, 로직에 대응되는 페이지들은 다음과 같다.

test.jsp, info.jsp

test.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<form action="/MyWeb/basic" method="post">
		# 아이디: <input type="text" name="account"> <br>
		<input type="submit" value="서블릿 페이지 열어보기">
	</form>
</body>
</html>

info.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<p>
		# 아이디: ${sessionScope.user.id } <br>
		# 이름: ${user.name } <br>
		# 이메일: ${user.email } <br>
		# 주소: ${user.address } <br>
	</p>
</body>
</html>

test에서 form으로 넘긴 데이터를, 이전의 경우 .jsp 페이지로 리다이렉트시켰지만 이제는 서블릿을 지정해주면 된다.

/MyWeb/basic 이 그 부분이다.

test.jsp 에서 버튼을 눌러 info.jsp로 이동될 때 서블릿의 doPost() 가 호출된다.

URL-Pattern

예시

	<a href="/MyWeb/FrontController">글 작성 요청</a>
	<a href="/MyWeb/FrontController">글 목록 요청</a>
	<a href="/MyWeb/FrontController">글 수정 요청</a>
	<a href="/MyWeb/FrontController">글 삭제 요청</a>

다음과 같은 doGet() (a태그get() 방식이다) 을 호출하는 요청이 4개가 있다고 치자. 네개 중 어떤 것을 눌렀는지 서블릿은 알 길이 없다. 따라서 우리는 다른 방법을 찾아야 할 필요가 있다.

디렉토리 패턴

디렉토리 형태로 서버의 해당 컴포넌트를 찾아 실행하는 구조.

http://localhost:8080/cr/Hello

하지만 이 방법은 정확한 이름을 지정하지 않은 경우 동작하지 않을 여지가 있다.

확장자 패턴

http://localhost:8080/cr/Hello.do
http://localhost:8080/cr/Bye.do

이렇게 하면 .do 로 전달되는 요청이 있으면 서블릿에서 .do 에 해당하는 요청은 다 받아들이게 된다.

URL Pattern 실습 1. FrontController.java 및 front_con.jsp

front_con.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<a href="/MyWeb/write.do">글 작성 요청</a>
	<a href="/MyWeb/list.do">글 목록 요청</a>
	<a href="/MyWeb/update.do">글 수정 요청</a>
	<a href="/MyWeb/delete.do">글 삭제 요청</a>
</body>
</html>

위와 같이 <a> 태그들을 정해 두고, FrontController를 만든다.

FrontContoller.java

package kr.co.jsp.servlet.basic;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class FrontController
 */
@WebServlet("*.do")
public class FrontController extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public FrontController() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		System.out.println("doGet 메서드 호출!");
		System.out.println("요청 들어온 URI : " + request.getRequestURI());
		
		String uri = request.getRequestURI();
		String conPath = request.getContextPath(); // /MyWeb (작업중인 프로젝트의 contextPath)
		
		uri = uri.substring(conPath.length() + 1, uri.lastIndexOf("."));
		System.out.println("정제된 uri : " + uri);
		
		/*
		 * 정제 후에는 /MyWeb/write.do 같은 형식이 아닌
		 * write, list 등과 같이 많은 부분을 생략할 수 있다.
		 */
		if (uri.equals("write") ) {
			System.out.println("글 작성 요청 들어옴!");
		} else if (uri.equals("list")) {
			System.out.println("글 목록 요청 들어옴!");
		}
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

좀 중요한 부분들이 있는데, 일단 이 서블릿은 자동 생성으로 만들었다.

그리고 이 부분,

@WebServlet("*.do")

매핑을 통해 .do 로 끝나는 요청은 이 서블릿으로 처리하도록 하게 하는 부분이다.

그리고 doGet() 메서드에 집중해야 하는데,

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		System.out.println("doGet 메서드 호출!");
		System.out.println("요청 들어온 URI : " + request.getRequestURI());
		
		String uri = request.getRequestURI();
		String conPath = request.getContextPath(); // /MyWeb (작업중인 프로젝트의 contextPath)
		
		uri = uri.substring(conPath.length() + 1, uri.lastIndexOf("."));
		System.out.println("정제된 uri : " + uri);
		
		/*
		 * 정제 후에는 /MyWeb/write.do 같은 형식이 아닌
		 * write, list 등과 같이 많은 부분을 생략할 수 있다.
		 */
		if (uri.equals("write")) {
			System.out.println("글 작성 요청 들어옴!");
		} else if (uri.equals("list")) {
			System.out.println("글 목록 요청 들어옴!");
		}
	}

보면 요청이 들어온 uri를 request 객체로부터 얻어오고 있다.

이 때는 /MyWeb/요청이름.do 의 형태로 넘어오게 되는데, 이것을 if문에 다 집어넣기엔 상당히 길고 복잡해지므로 한 번의 정제 과정을 거친다.

subString() 메서드를 통해 /MyWebb 뒤부터 시작하여, .do. 앞까지만 잘라 write, list 등만 뽑아내어 조건문에 넣기 편하게 만들었다.

실습 2. MVC Model 2 Board 만들기

테이블 생성

CREATE TABLE my_board (
    board_id NUMBER PRIMARY KEY,
    writer VARCHAR2(30) NOT NULL,
    title VARCHAR2(100) NOT NULL,
    content VARCHAR2(2000),
    reg_date DATE DEFAULT sysdate,
    hit NUMBER DEFAULT 0
);

CREATE SEQUENCE board_seq
    START WITH 1
    INCREMENT BY 1
    MAXVALUE 1000
    NOCYCLE
    NOCACHE;

BoardVO, IBoardDAO, BoardDAO 생성

BoardVO.java

package kr.co.jsp.board.model;

import java.sql.Timestamp;

/*
 * CREATE TABLE my_board (
    board_id NUMBER PRIMARY KEY,
    writer VARCHAR2(30) NOT NULL,
    title VARCHAR2(100) NOT NULL,
    content VARCHAR2(2000),
    reg_date DATE DEFAULT sysdate,
    hit NUMBER DEFAULT 0
);

CREATE SEQUENCE board_seq
    START WITH 1
    INCREMENT BY 1
    MAXVALUE 1000
    NOCYCLE
    NOCACHE;
 */

public class BoardVO {
	
	private int board_id;
	private String writer;
	private String title;
	private String content;
	private Timestamp reg_date;
	private int hit;
	
	public BoardVO() {}

	public BoardVO(int board_id, String writer, String title, String content, Timestamp reg_date, int hit) {
		super();
		this.board_id = board_id;
		this.writer = writer;
		this.title = title;
		this.content = content;
		this.reg_date = reg_date;
		this.hit = hit;
	}

	public int getBoard_id() {
		return board_id;
	}

	public void setBoard_id(int board_id) {
		this.board_id = board_id;
	}

	public String getWriter() {
		return writer;
	}

	public void setWriter(String writer) {
		this.writer = writer;
	}

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public String getContent() {
		return content;
	}

	public void setContent(String content) {
		this.content = content;
	}

	public java.sql.Timestamp getReg_date() {
		return reg_date;
	}

	public void setReg_date(java.sql.Timestamp reg_date) {
		this.reg_date = reg_date;
	}

	public int getHit() {
		return hit;
	}

	public void setHit(int hit) {
		this.hit = hit;
	};
}

IBoardDAO.java

package kr.co.jsp.board.model;

import java.util.List;

public interface IBoardDAO {
	// 글 등록 메서드
	void regist(String writer, String title, String content);
	
	// 글 전체 목록을 가지고 오는 메서드
	List<BoardVO> listBoard();
	
	// 글 상세보기 요청을 처리할 메서드
	public BoardVO contentBoard(int bId);
	
	// 글 수정 요청을 처리할 메서드 (제목, 내용)
	void updateBoard(String title, String content, int bId);
	
	// 글 삭제 요청을 처리할 메서드
	void deleteBoard(int bId);
}

BoardDAO.java

package kr.co.jsp.board.model;

import java.util.List;

import javax.activation.DataSource;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public class BoardDAO implements IBoardDAO {
	
	private DataSource ds;
	
	private BoardDAO() {
		try {
			InitialContext ct = new InitialContext();
			ds = (DataSource) ct.lookup("java:comp/env/jdbc/myOracle");
		} catch (NamingException e) {
			e.printStackTrace();
		}
	}
	
	private static BoardDAO dao = new BoardDAO();
	
	public static BoardDAO getInstance() {
		if (dao == null)
			dao = new BoardDAO();
		return dao;
	}

	// ------------------------------------
	
	@Override
	public void regist(String writer, String title, String content) {
		// TODO Auto-generated method stub

	}

	@Override
	public List<BoardVO> listBoard() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public BoardVO contentBoard(int bId) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void updateBoard(String title, String content, int bId) {
		// TODO Auto-generated method stub

	}

	@Override
	public void deleteBoard(int bId) {
		// TODO Auto-generated method stub

	}

}
private DataSource ds;
	
	private BoardDAO() {
		try {
			InitialContext ct = new InitialContext();
			ds = (DataSource) ct.lookup("java:comp/env/jdbc/myOracle");
		} catch (NamingException e) {
			e.printStackTrace();
		}
	}

싱글턴 패턴은 그렇다 치는데, 커넥션 풀 객체 만드는 부분은 도통 외워지지가 않는 것 같다.

board 디렉토리 생성 및 board_list.jsp 생성

board 디렉토리를 WebContent 하위에 생성하고 board_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" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<style>
   tbody{
      font-size: 20px;
   }

   
</style>

</head>
<body>

   <jsp:include page="../include/header.jsp"/>

   <div class="container">
      <h2>My Web게시판</h2>
      
      <table class="table table-secondary table-hover table-bordered">
         <thead style="font-size: 25px">
            <tr>
               <th>글 번호</th>
               <th>작성자</th>
               <th>제목</th>
               <th>날짜</th>
               <th>조회수</th>
            </tr>
         </thead>

         
         <tbody>

               <tr>
                  <td></td>
                  <td></td>
                  <td>
                     
                  </td>
                  <td>
                     
                  </td>
                  <td></td>
               </tr>

         </tbody>
         
         <%-- 페이징을 처리할 구간 --%>
         <tbody>
            <tr>
               <td colspan="5" align="center">
                  <ul class="pagination pagination-lg">
                  
                  <%-- 이전 버튼 --%>
                        
                           <li class="page-item"><a class="page-link"
                              href=""
                              style="background-color: #643691; margin-top: 0; height: 40px; color: white; border: 0px solid #f78f24; opacity: 0.8">이전</a>
                           </li>
                        

                       <%-- 페이지 버튼 --%>
                     
                     
                           <li class="page-item">
                           <a href="" class="page-link"
                              style="margin-top: 0; height: 40px; color: pink; border: 1px solid #643691;">1</a>
                           </li>
                        

                        <%-- 다음 버튼 --%>
          
                           <li class="page-item"><a class="page-link"
                              href=""
                              style="background-color: #643691; margin-top: 0; height: 40px; color: white; border: 0px solid #f78f24; opacity: 0.8">다음</a>
                           </li>
               
                  </ul>
               </td>
            </tr>
         </tbody>
         
         <tbody>
            <tr>
               <td colspan="5" align="right">
                  <form action="/MyWeb/search.board" class="form-inline" >
                    <div class="form-group">
                       <select name="category" class="form-control">
                          <option value="title">제목</option>
                          <option value="writer">작성자</option>
                          <option value="content">내용</option>
                       </select>
                      <input type="text" name="search" placeholder="검색어 입력" class="form-control" >
                       <input type="submit" value="검색" class="btn btn-default">
                     <input type="button" value="글 작성" class="btn btn-default" onclick="location.href='/MyWeb/write.board'">
                    </div>
                  </form> 
               </td>
            </tr>
         </tbody>
      
      </table>
   </div>

   <jsp:include page="../include/footer.jsp"/>

</body>
</html>

BoardController.java 서블릿 작성

kr.co.jsp.board.controller 패키지를 새로 작성하고 안에 BoardController.java 서블릿을 만든다.

package kr.co.jsp.board.controller;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("*.board")
public class BoardController extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    public BoardController() {
        super();
    }

    /*
     	- 원래대로라면 Get, Post 메서드를 나눠 작성하는게 맞긴 한데,
     	한 쪽에 몰아서 작성하도록 할 수도 있다.
     */
    
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doRequest(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		doRequest(request, response);
	}
	
	protected void doRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String uri = request.getRequestURI();
		String conPath = request.getContextPath();
		uri = uri.substring(conPath.length() + 1, uri.lastIndexOf("."));
		
		System.out.println(uri);
		
		switch (uri) {
		case "write" :
			System.out.println("글쓰기 페이지로 이동 요청");
			response.sendRedirect("board/board_write.jsp");
			break;
		}
	}

}

그 후 board_list.jsp로 이동하여

<input type="button" value="글 작성" class="btn btn-default" onclick="location.href='/MyWeb/write.board'">

location.href= 부분을 MyWeb에게 write.board 요청을 보내도록 작성해 둔다.

이전같았으면 요청을 컨트롤러로 보내는 것이 아닌, 'board_write.jsp' 등과 같이 직접 보냈겠지만, 우리는 MVC2 기반의 설계를 토대로 진행하고 있으므로 이제부터 모든 요청들은, 컨트롤러를 통하도록 한다.

물론 Board에 관련된 요청만 BoardController를 통하는 것이고, User에 관한 요청은 UserController를 통해야 한다.

이제 컨트롤러에서 board_write.jsp로 이동을 요청했으므로 board_write 페이지를 만들 차례이다.

board_write.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<style>
.virtual-box {
   margin-bottom: 20px;
}

</style>
</head>
<body>

<jsp:include page="../include/header.jsp"/>

<div class="virtual-box"></div>
<div class="container">
       <div class="row">
           <div class="col-md-offset-2 col-md-8">
               <div class="panel">
                   <div class="panel-heading text-white"  align="center" style="background: #F8F8FF;">
                       <h2>게시글 등록</h2>
                   </div>
                   <div class="panel-body">
                       <form action="/MyWeb/regist.board" method="post">
                           <div class="form-group">
                               <label for="writer" hidden>작성자</label>
                     <!-- 로그인 성공시 제작된 session id를 이곳에 고정값으로 두고 변경을 하지 못하게.-->
                               <input id="writer" name="bWriter" value=""
                               type="text" class="form-control" placeholder="작성자" readonly>
                           </div>
   
                           <div class="form-group">
                               <label for="title" hidden>글제목</label>
                               <input id="title" name="bTitle" type="text" class="form-control" placeholder="글제목">
                           </div>
   
                           <div class="form-group">
                               <label for="content" hidden>글내용</label>
                               <textarea id="content" name="bContent" class="form-control" placeholder="게시글 내용을 입력하세요." rows="5"></textarea>
                           </div>
                           
                     
                     <div>
                            <button type="submit" class="btn btn-primary form-control" onclick="return confirm('등록하시겠습니까?')">등록</button>
                            <button type="button" class="btn btn-danger form-control" onclick="location.href=">취소</button>
                          </div>
                       </form>
                       
                   </div>
               </div>
           </div>
       </div>
   </div>

<jsp:include page="../include/footer.jsp"/>
</body>
</html>

글 등록시 처리는 보드컨트롤러에 regist.board 로 보내고 있다.

소스를 수정할 부분은 이곳이다.

<!-- 로그인 성공시 제작된 session id를 이곳에 고정값으로 두고 변경을 하지 못하게.-->
                               <input id="writer" name="bWriter" value="${user.id}"
                               type="text" class="form-control" placeholder="작성자" readonly>

BoardController.java 수정

BoardController.java

package kr.co.jsp.board.controller;

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

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 kr.co.jsp.board.model.BoardDAO;
import kr.co.jsp.board.model.BoardVO;

@WebServlet("*.board")
public class BoardController extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    public BoardController() {
        super();
    }

    /*
     	- 원래대로라면 Get, Post 메서드를 나눠 작성하는게 맞긴 한데,
     	한 쪽에 몰아서 작성하도록 할 수도 있다.
     */
    
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doRequest(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		doRequest(request, response);
	}
	
	protected void doRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String uri = request.getRequestURI();
		String conPath = request.getContextPath();
		uri = uri.substring(conPath.length() + 1, uri.lastIndexOf("."));
		
		System.out.println(uri);
		
		switch (uri) {
		case "write" :
			System.out.println("글쓰기 페이지로 이동 요청");
			response.sendRedirect("board/board_write.jsp");
			break;
			
		case "regist" :
			System.out.println("글 등록 요청이 들어옴!");
			String writer = request.getParameter("bWriter");
			String title = request.getParameter("bTitle");
			String content = request.getParameter("bContent");
			BoardDAO.getInstance().regist(writer, title, content);
		
			// jsp쪽으로 보내서 다시 list로 보내기보다, 여기서 바로 보내기
			response.sendRedirect("/MyWeb/list.board");
			break;
		
		case "list":
			System.out.println("글 목록 요청이 들어옴!");
			List<BoardVO> boardList = BoardDAO.getInstance().listBoard();
			request.setAttribute("bList", boardList);
			
			/*
			 * sendRedirect()를 쓰면, request 안에 담긴 객체가
			 * 응답이 나가면서 바로 소멸해 버린다. (req는 res로 응답 보내면 소멸해버림)
			 * 
			 * 따라서 request 객체를 다음 화면까지 운반하기 위한 foward 기능을 지원하는 객체
			 * RequestDispatcher를 써야 한다.
			 */
			// response.sendRedirect("board/board_list.jsp");
			RequestDispatcher dp = request.getRequestDispatcher("board/board_list.jsp");
			dp.forward(request, response);
			break;
		}
	}

}

여기서 먼저 조금 주목할 부분은,

// jsp쪽으로 보내서 다시 list로 보내기보다, 여기서 바로 보내기
			response.sendRedirect("/MyWeb/list.board");
			break;

이 부분이다.

이렇게 해야 하는 이유는, board_list.jsp 에는 DB로부터 전체 글 목록을 가져오는 로직이 없기 때문이다. (이제부터 .jspView 의 역할만 하기로 했으므로)

따라서, 컨트롤러로 글 목록 요청이 다시 들어올 수 있게끔
sendRedirect() 를 사용해서 자동으로 목록 재요청이 들어오게 해야 한다.

다음으로 주목할 부분은 list의 부분이다.

case "list":
			System.out.println("글 목록 요청이 들어옴!");
			List<BoardVO> boardList = BoardDAO.getInstance().listBoard();
			request.setAttribute("bList", boardList);
			
			/*
			 * sendRedirect()를 쓰면, request 안에 담긴 객체가
			 * 응답이 나가면서 바로 소멸해 버린다. (req는 res로 응답 보내면 소멸해버림)
			 * 
			 * 따라서 request 객체를 다음 화면까지 운반하기 위한 foward 기능을 지원하는 객체
			 * RequestDispatcher를 써야 한다.
			 */
			// response.sendRedirect("board/board_list.jsp");
			RequestDispatcher dp = request.getRequestDispatcher("board/board_list.jsp");
			dp.forward(request, response);
			break;

우리는 BoardDAO 로부터 listBoard() 메서드를 통해서 글 목록을 얻어오고 있다. 그리고 이렇게 얻어온 글 목록을 다음 페이지로 넘겨 주어야 한다.

자, 이런 상황에서 글 목록을 넘겨줄 객체는 session 이 좋은 것일까? 강사님 멘트에 따르면, 별로 좋지 않은 결정이라고 한다.

이유는 세션의 경우 정적인 상태가 오랫동안 유지되는 (예. 로그인 정보, 회원 정보) 경우에만 세션으로 유지시키고, 아닌 데이터들은 request로 보내는게 맞다고 하셨다.
(왜냐하면, 리퀘스트는 응답이 한번 나가는 순간 이전 객체는 자동으로 소멸하므로)

단, 여기서 발생하는 문제는 페이지 리다이렉팅을 위해서 responsesendRedirect() 를 써버리면, 아까 글 목록을 담아둔 객체가 소멸해 버려서 문제가 된다.

그래서 우리는 새로운 녀석인 RequestDispatcher 를 써서, 객체를 다음 화면까지 운반시켜야 한다.

이 객체의 foward() 라는 메서드는, request, response 를 각각 매개 변수로 받아 다음 화면으로 보내준다. 이것을 이용해야 한다.

다음은 board_list.jsp 에서 글 목록을 표시할 부분을 수정해야 한다.

board_list.jsp

글 목록 볼 수 있게 하기

board_list.jsp

<tbody>
			<c:forEach var="b" items="${bList}">
               <tr>
                  <td>${b.boardId}</td>
                  <td>${b.writer}</td>
                  <td>
                     ${b.title}
                  </td>
                  <td>
                     ${b.regDate}
                  </td>
                  <td>${b.hit}</td>
               </tr>
			</c:forEach>
</tbody>

EL문법을 이용해서 표시를 하고, 반복문의 경우 JSTL을 사용해서 반복하도록 한다.

아까 request 객체로 보낸 글 목록은 bList 라는 이름으로 보냈으므로 그것으로 받는다.

로그인하지 않은 사용자가 게시판에 접근하지 못 하게 하기
<%--
		로그인하지 않은 사용자가 게시판에 들어왔을 경우 돌려보내는 코드 작성.
		스크립트릿 사용하지 말 것!
	 --%>

	<c:if test="${user == null}">
		<script>
			alert("회원만 이용 가능한 게시판입니다. 로그인 해 주세요.");
			/*
				board_list.jsp로 직접 요청이 들어가는 경우는 없으므로
				컨트롤러를 기준으로 상대 경로로 작성하거나, 절대 경로로 작성해야 한다.
				만약 ../ 등을 앞에 붙여서 작성하면  /MyWeb이 잘려나간다. 
			*/
			location.href="user/user_login.jsp";
		</script>
	</c:if>

EL과 JSTL을 사용하여 user 세션 데이터가 존재하지 않는 경우 게시판으로의 접근을 막고 있다.

게시글 목록에 보이는 게시글의 제목을 눌러 글 상세보기로 이동할 수 있게 만들어주기

board_list.jsp

...
<a href="/MyWeb/content.board?bId=${b.board_id}">${b.title}</a>
...

몇 번째 게시글을 눌렀는지 컨트롤러에서는 알 길이 없으므로 URL에 붙여서 보내주도록 한다.

오늘 구현은 여기까지이고, 다음엔 content 요청에 따른 BoardDAO의 구현을 진행한다.

0개의 댓글