30일차(1)/jsp(9) : Request Scope
새 다이나믹 웹프로젝트 생성 : Step03_Scope
index.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>/index.jsp</title>
</head>
<body>
<div class="container">
<h1>인덱스 페이지입니다.</h1>
<ul>
<li><a href="${pageContext.request.contextPath }/fortune">오늘의 운세</a></li>
<li><a href="${pageContext.request.contextPath }/member">회원 한명의 정보 보기</a></li>
<li><a href="${pageContext.request.contextPath }/friend/list">친구 목록 보기</a></li>
</ul>
</div>
</body>
</html>
test.servlet 패키지에 <FortuneServlet>
package test.servlet;
import java.io.IOException;
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;
@WebServlet("/fortune")
public class FortuneServlet extends HttpServlet{
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//오늘의 운세를 얻어오는 비즈니스 로직을 수행
String fortune="동쪽으로 가면 귀인을 만나요!";
//응답에 필요한 데이터를 request scope(HttpServletRequest 객체)에 담는다.
req.setAttribute("fortuneToday", fortune);
//응답을 여기서 하지 않고 jsp페이지로 응답을 위임할 수 있다.
RequestDispatcher rd=req.getRequestDispatcher("/test/fortune.jsp");
rd.forward(req, resp);
}
}
/test/ <fortune.jsp> 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
//request scope에 "fortuneToday"라는 키값으로 저장된 값을 읽어와서
//원래 타입으로 casting해서 변수에 대입하기
String fortuneToday=(String)request.getAttribute("fortuneToday");
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>/test/fortune.jsp</title>
</head>
<body>
<p> 오늘의 운세: <strong><%=fortuneToday %></strong></p>
</body>
</html>
- fortune의 비즈니스 로직을 수행하고 응답을 하면 되는데,
응답을 servlet 페이지에서 하지 않고 jsp페이지에 위임시킬 수가 있다.
- 운세부분(로직)은 servlet에서 하고, 응답은 jsp페이지에서 한다면
응답에 필요한 데이터는 어떻게 전달할 것인가?
1) 응답을 위임하는 방법은?
2) 얻어온 오늘의운세를 어떻게 전달할 수 있을까?
- req 변수 안의 getRequestDispatcher 메소드를 사용!
- 경로를 변수로 받고 메소드 요청 전달자(request dispatcher) 객체를 리턴해준다.
응답을 위임하는데 필요한 객체이다.
- java는 모든작업에서 객체를 활용한다. 각각의 객체를 어떻게 잘 사용하느냐가 java를 배우는 관건!
- RequestDispacher 타입 변수의 forward 메소드에 매개로 두개의 값을 전달해주어야 한다.(req, resp)
- HttpServletRequest 설명 : 링크
- 서비스 메소드의 req는 HttpServletRequest이지만, ServletRequest가 HttpServletRequest의 부모타입이다.
- 자식타입을 부모타입에 담는 것이기 때문에 가능!
RequestDispatcher rd=req.getRequestDispatcher("응답할 jsp 경로");
rd.forward(req, resp);
- 최초 servlet이 전달받았던 리퀘스트와, req, resp 객체를 jsp에도 전달해주겠다는 의미.
- 위임받을 jsp페이지를 넣어두고, req, resp 값을 전달하면 응답이 위임된다.
- 요청전달자 객체의 참조값을 얻어와서 forward객체를 호출해야 한다.
- 클라이언트의 요청을 메소드의 리턴타입으로 받아와야 한다.
- fortune (servlet) 페이지에서 요청하면
주소창에 보이는 페이지 주소는 그대로지만, 해당 페이지 소스를 확인해보면 fortune.jsp가 응답한 것을 볼 수 있다.
- 최초 요청을 받은 servlet을 대신해서 jsp가 응답했다!
위와 같은 단계로 요청이 실행된다고 보면 된다.
- jsp <%%>에서 사용하는 request와 같다. jsp에 참조값을 전달해 주는 것!
- 처음 전달된 타입은 HttpServletRequest이고,
forward에서 인자로 필요한 것은 ServletRequest 이지만
ServletRequest가 부모타입이기 때문에 담아서 사용할 수 있다.
- Servlet 페이지에서 응답에 필요한 데이터를 request scope에 담아서 전달한다.
.setAttribute : 어떤 속성을 담는 메소드.
- request 영역(scope)에 key-value를 쌍으로 저장한다.
- 영역을 scope 라고도 한다.
- object 타입이므로 어떤 타입이든지 다 들어갈 수 있다. 아무거나 다 전달할 수 있다!
- key값과 object type 담기
- jsp페이지에서는 getAtrribute 로 가져와준다.
- 변수에 담고 jsp페이지로 전달하는 것
- servlet - jsp 분업화된 것. 비즈니스 로직과 응답을 분리한다.
- Spring Framework에서 이렇게 많이 한다.모든 요청을 처음에는 servlet이 받고, 응답은 forward로 받아서 jsp로 이동
- '어떤 키 값'으로 '어떤 타입'이 담겼는지를 확인해서 쓰면 된다.
- object 타입으로 담았던 데이터의 casting이 필요하기 때문에!
Q) 속도가 빨라져서 분업하는것인가?
A) 아니다. jsp를 단순화시키기 위해서이다.(응답에만 집중할 수 있도록 하기 위해)
나중에는 java코드도 없이 바로 출력하게 된다.
/member 링크 추가
<MemberServlet> 생성
package test.servlet;
import java.io.IOException;
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 test.member.dto.MemberDto;
@WebServlet("/member")
public class MemberServlet extends HttpServlet{
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//회원 한명의 정보를 얻어오는 비즈니스 로직 수행
MemberDto dto=new MemberDto(1, "바나나", "서울");
//request scope에 "dto"라는 키값으로 MemberDto type 담기
req.setAttribute("dto", dto);
//jsp페이지로 응답을 위임시키기 (forward 이동)
RequestDispatcher rd=req.getRequestDispatcher("/test/member.jsp");
rd.forward(req, resp);
}
}
- forward: 응답을 다른 페이지에 위임시키는 메소드
- sendRedirect: 요청을 다시 하라고 강제로 페이지를 이동시키는 메소드
<member.jsp>
<%@page import="test.member.dto.MemberDto"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
//"dto"라는 키값으로 담긴 MemberDto type의 참조값 얻어오기
MemberDto dto=(MemberDto)request.getAttribute("dto");
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>test/member.jsp</title>
</head>
<body>
<h3>회원 한명의 정보입니다.</h3>
<p> 번호 : <strong><%=dto.getNum() %></strong></p>
<p> 이름 : <strong><%=dto.getName() %></strong></p>
<p> 주소 : <strong><%=dto.getAddr() %></strong></p>
</body>
</html>
- 어떤 키워드(key)로, 어떤 타입의 정보가 저장되었는지 기억하기
- 여기서는 "dto" / MemberDto 타입
- 주소는 servlet 처럼 생겼지만 페이지 소스에서 보이는 것은 jsp페이지
- 분업화하여 응답에 필요한 데이터는 servlet에서, forward 이동해서 응답은 jsp에서!
- jsp에 java코드가 많으면 유지보수가 힘들기 때문에, jsp페이지를 단순화시키기 위해서이다.
- index.jsp 에 친구목록을 볼 /friend/list 링크 추가
<FriendList> Servlet생성
package test.servlet;
import java.io.IOException;
import java.util.ArrayList;
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;
@WebServlet("/friend/list")
public class FriendList extends HttpServlet{
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//친구목록을 얻어오는 비즈니스 로직을 수행한다.
List<String> list=new ArrayList<>();
list.add("바나나");
list.add("딸기");
list.add("복숭아");
//로직 수행결과로 얻어낸 데이터(Model)을 request scope에 담기
req.setAttribute("list", list);
//jsp 페이지로(view page) forward 이동해서 응답하기 (forward이동은 WEB-INF 폴더 안쪽도 가능하다.)
RequestDispatcher rd=req.getRequestDispatcher("/WEB-INF/views/friend/list.jsp");
rd.forward(req, resp);
}
}
- 프로그래밍의 관점에서 데이터를 모델이라고도 부른다.
- jsp 페이지로(view page) forward 이동해서 응답하기.(forward이동은 WEB-INF 폴더 안쪽도 가능하다.)
- WEB-INF는 원래는 보안되는 폴더이기 때문에, 클라이언트가 직접 요청해서 들어갈 수는 없다.
- 하지만 forward 이동하는 경우에는 WEB-INF폴더 사용이 가능하다.(이건 클라이언트가 요청하는 것이 아니므로)
/WEB-INF/views/friend/ <list.jsp> 생성하기
<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
//"list"라는 키값으로 request scope 에 담겨 있는 List<String> type의 참조값 얻어오기
List<String> list=(List<String>)request.getAttribute("list");
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>/WEB-INF/views/friend/list.jsp</title>
</head>
<body>
<h3>친구 목록입니다.</h3>
<ul>
<% for(String tmp:list){ %>
<li><%=tmp %></li>
<%} %>
</ul>
</body>
</html>
- 어떤 키워드로, 어떤 타입의 정보가 저장되었는지 기억하기
- "list" / String 타입
- 클라이언트가 /friend/list 요청을 하면
→ friendListServlet이 요청을 받아서 request scope에 담아주고
→ 응답은 forward 한 /WEB-INF/views/friend/list.jsp 페이지에서 하고
→ 응답을 브라우저 화면으로 response 해준다.
- request 영역에 담은 것은 응답할 때까지만 남아 있다.(응답하기 전까지만 유효하다)
응답을 다 하고 나면 사라진다. 일회성 데이터라고 할 수 있다.
- 페이지 소스에서 확인해보면 jsp 페이지를 보여주고 있다는 것을 알 수 있다.
- 해당 jsp 경로를 클라이언트가 주소창에 직접 요청하면 접속할 수 없다.
forward 이동 용도로만 사용된다.
- 주소창에 WEB-INF 경로가 들어가면 잘못 요청한 것!
'국비교육(22-23)' 카테고리의 다른 글
[참고] Eclipse에 Quantum DB 설치 (0) | 2022.11.21 |
---|---|
30일차(2)/jsp(10) : Session Scope (0) | 2022.11.18 |
29일차(2)/CSS(6) : bootstrap CSS 적용하기 (0) | 2022.11.17 |
29일차(1)/jsp(8) : DBCP활용 예제 (todo 테이블) (0) | 2022.11.17 |
28일차(2)/jsp(7) : DBCP활용 (Update) (0) | 2022.11.16 |