4. 서블릿에서 뷰 관련 코드 제거
web04 프로젝트의 src/main/java의 spms.servlets 패키지에서 MemberListServlet.java 파일을 복사하여 web05 프로젝트의 src/main/java에 spms.servlets 패키지를 만들어 복사한다. 이후 다음과 같이 MemberListServlet 클래스를 수정한다.
package spms.servlets;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import javax.servlet.GenericServlet;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import spms.vo.Member;
//UI 출력 코드를 제거하고, UI 생성 및 출력을 JSP에게 위임한다.
@WebServlet("/member/list")
public class MemberListServlet extends HttpServlet {//extends GenericServlet
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
//데이터베이스 관련 코드를 위한 try ~ catch 블록 (JDBC API 사용시 예외가 발생할 수 있기 때문)
try {
//JDBC 드라이버를 로딩하고 데이터베이스 연결 시 컨텍스트 초기화 매개변수에서 해당 정보 가져와 처리.
ServletContext sc = this.getServletContext();
Class.forName(sc.getInitParameter("driver"));
conn = DriverManager.getConnection(
sc.getInitParameter("url"),
sc.getInitParameter("username"),
sc.getInitParameter("password"));
stmt = conn.createStatement();
rs = stmt.executeQuery(
"SELECT MNO,MNAME,EMAIL,CRE_DATE" +
" FROM MEMBERS" +
" ORDER BY MNO ASC");
response.setContentType("text/html; charset=UTF-8");
/*
PrintWriter out = response.getWriter();
out.println("<html><head><title>회원목록</title></head>");
out.println("<body><h1>회원목록</h1>");
out.println("<p><a href='add'>신규 회원</a></p>");
while(rs.next()) {
out.println(
rs.getInt("MNO") + "," + //getInt(1)
"<a href='update?no=" + rs.getInt("MNO") + "'>" + //회원 상세정보 출력 서블릿 URL 추가
rs.getString("MNAME") + "</a>," + //getString(2)
rs.getString("EMAIL") + "," + //getString(3)
//rs.getDate("CRE_DATE") + "<br>" //getDate(4)
rs.getDate("CRE_DATE") +
"<a href='delete?no=" + rs.getInt("MNO") + "'>[삭제]</a><br>"
);
}
out.println("</body></html>");
*/
ArrayList<Member> members = new ArrayList<Member>();
//데이터베이스에서 회원 정보를 가져와 Member에 담는다.
//그리고 Member객체를 ArrayList에 추가한다.
while(rs.next()) {
members.add(new Member().setNo(rs.getInt("MNO"))
.setName(rs.getString("MNAME"))
.setEmail(rs.getString("EMAIL"))
.setCreatedDate(rs.getDate("CRE_DATE")) );
}
//request에 회원 목록 데이터 보관한다.
request.setAttribute("members", members);
//JSP로 출력을 위임한다.
RequestDispatcher rd = request.getRequestDispatcher("/member/MemberList.jsp");
rd.include(request, response);
} catch (Exception e) {
throw new ServletException(e);
} finally {
try {if (rs != null) rs.close();} catch(Exception e) {}
try {if (stmt != null) stmt.close();} catch(Exception e) {}
try {if (conn != null) conn.close();} catch(Exception e) {}
}
}
}
- HTML 출력 코드 제거
MemberListServlet 클래스에서 HTML을 출력하는 모든 코드를 제거한다. 앞으로 회원 목록 화면을 생성하고 출력하는 것은 MemberList.jsp가 담당한다.
- JSP에 전달할 회원 목록 데이터 준비
MemberListServlet 클래스는 UI를 생성하지 않아 출력 코드를 작성할 필요가 없다. 그 대신 JSP가 회원 목록 화면을 만들 수 있도록 데이터를 준비해야 한다. 그 첫 번째 작업이 회원 목록을 담을 ArrayList 객체를 준비하는 것이다.
ArrayList<Member> members = new ArrayList<Member>();
그리고 ResultSet 객체를 통해 데이터베이스로부터 받은 레코드를 값 객체 Member에 담는다. 이 값 객체는 ArrayList에 보관된다. 테이블에 있는 레코드들을 모두 담을 때까지 이 과정을 반복한다.
while(rs.next()) {
members.add(new Member().setNo(rs.getInt("MNO"))
.setName(rs.getString("MNAME"))
.setEmail(rs.getString("EMAIL"))
.setCreatedDate(rs.getDate("CRE_DATE")) );
}
Member 객체를 만들 때 셋터 메서드를 연속해서 호출하고 있는데, 이것이 바로 셋터 메서드의 반환값을 this로 한 이유다. 객체를 생성하고 바로 초기화할 수 있기 때문이다.대부분 객체를 생성하고 값을 넣을 때 다음과 같이 작성한다.
//※ 객체를 생성하고 값을 넣는 전형적인 코드
Member member = new Member():
member.setNo(rs.getInt("MNO"));
member.setName(rs.getString("MNAME"));
member.setEmail(rs.getString("EMAIL"));
member.setCreatedDate(rs.getDate("CRE_DATE"));
위와 같이 전형적인 코딩 스타일에서는 객체를 생성하고 나서 그 주소를 참조 변수에 저장하고, 그 참조 변수를 통해 셋터(Setter) 메서드를 호출한다. 그러나 예제 코드에서는 객체를 생성한 즉시 셋터 메서드를 연속으로 호출하여 값을 할당한다. 이런 코딩 방식은 이미 스크립팅 언어에서 널리 사용되고 있는 방식이지만 자바 개발자들도 자주 사용한다.
- RequestDispatcher를 이용한 forward, include
회원 목록 데이터가 준비되었으면, 화면 생성을 위해 JSP로 작업을 위임해야 한다. 이렇게 다른 서블릿이나 JSP로 작업을 위임할 때 사용하는 객체가 RequestDispatcher이다. 클래스 이름(요청 배치 담당자)만 봐도 무슨 일을 하는 객체인지 알 수 있다. 이 객체는 HttpServletRequest를 통해 얻는다.
RequestDispatcher rd = request.getRequestDispatcher("/member/MemberList.jsp");
RequestDispatcher를 얻을 때, 만드시 어떤 서블릿(또는 JSP)으로 위임할 것인지 알려줘야 한다. 예제에서는 회원 목록을 출력할 MemberList.jsp의 경로를 인자값으로 넘겼다. 경로가 '/'로 시작하면 웹 애플리케이션 루트를 의미한다.
이제 RequestDispatcher 객체를 얻었으면 포워드(Forward) 하거나 인클루드(Include) 하면 된다. 포워드로 위임하면 해당 서블릿으로 제어권이 넘어간 후 다시 돌아오지 않는다. 인클루드로 위임하면 해당 서블릿으로 제어권을 넘긴 후 그 서블릿이 작업을 끝내면 다시 제어권이 넘어온다.
rd.include(request, response);
인클루드 방식으로 MemberList.jsp에 작업을 위임했다. 혹시 나중에라도 JSP가 작업을 끝낸 후 MemberListServlet 클래스에서 추가 작업을 할 경우를 고려한 것이다.
- ServletRequest(HttpServletRequest)를 통한 데이터 전달
MemberList.jsp를 인클루드할 때 MemberListServlet.doGet() 메서드의 매개변수 값을 그대로 넘겼다. 즉 MemberListServlet 클래스와 MemberList.jsp는 request와 response를 공유한다. 바로 이 부분을 이용하여 데이터를 전달할 수 있다.
ServletRequest는 클라이언트의 요청을 다루는 기능 외에 어떤 값을 보관하는 보관소 기능도 있다. setAttribute()를 호출하여 값을 보관할 수 있고, getAttribute()를 호출하여 보관된 값을 꺼낼 수 있다. 이 기능을 사용하여 회원 목록을 MemberList.jsp에 전달하고 있다.
request.setAttribute("members", members);
MemberListServlet 클래스의 request 객체는 MemberList.jsp와 공유하기 때문에, request에 값을 담아두면 MemberList.jsp에서 꺼내 쓸 수 있다.
참고도서 : https://freelec.co.kr/book/1674/
[열혈강의] 자바 웹 개발 워크북
[열혈강의] 자바 웹 개발 워크북
freelec.co.kr
'교재 실습 > 자바 웹 개발 워크북' 카테고리의 다른 글
43. 포워딩과 인클루딩 (1) (0) | 2022.06.13 |
---|---|
42. 서블릿에서 뷰 분리하기 (3) (0) | 2022.06.12 |
40. 서블릿에서 뷰 분리하기 (1) (0) | 2022.06.09 |
39. JSP의 주요 구성 요소 (3) (0) | 2022.02.05 |
38. JSP의 주요 구성 요소 (2) (0) | 2022.02.04 |
댓글