국비/JSP

2023.03.30 45일차 JSP

춘핑이 2023. 3. 30. 18:18

45일차 JSP

자바코드 스크립트
page 디렉티브 include 디렉티브
include 액션태그를 배우고 있다.
include자체가 중요한 것이 아니라 request에 attribute를 붙여넣어서 꺼내 사용할 수 있는 것이 중요하다.
jsp를 배우고 있지만 상속관계에 의해서 서블릿이다.

서블릿 기반으로 스프링 web mvc가 동작한다.
서블릿을 알면 스프링을 아는데 도움이 된다.
jsp에서 서블릿을 구현하고 있으니 도움이 될 것이다.

request의 attribute 전달이 중요하다.

7.9 foward액션태그

jsp:fowrad 태그는 중요하진 않지만 foward 라는 의미는 중요하다.
요청을 받고 jsp가 다른 jsp에게 요청처리흐름을 foward시킨다.
클라이언트는 첫번째 jsp가 처리를 해줬다고 생각한다.
그래서 주소창에 첫번째 요청을 한게 남아있다.

출력스트림을 쭉 채우다가 forward를 만나면 포워드한 페이지가 일하게 된다.
1번파일 요청을 보내면 2번 파일로 요청이 이어진다.

foward 액션태그를 실행하면 생성했던 출력결과는 모두 제거된다.
다음예제를 실행하면 to.jsp파일의 결과가 출력되게 된다.

클라이언트 입장에서는 첫 문서의 주소를 받는다.
그래서 주소는 http://localhost:8080/JSP2023/ch07/from.jsp으로 나오고
출력결과는 to.jsp가 나오게 된다.

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>from.jsp의 제목</title>
</head>
<body>
    이 페이지는 from.jsp가 생성한 것입니다.
    <jsp:forward page="to.jsp"></jsp:forward>
</body>    
</html>

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>to.jsp의 실행결과</title>
</head>
<body>
    이 페이지는 to.jsp가 생성한 것입니다.
</body>
</html>

7.10 경로 - 1

submit을 누르면 action의 경로로 요청을 보내게 된다.
클라이언트가 요청을 보낼때 사용하는 경로
포워드 할때 서버가 사용하는 경로
두가지 경로가 있다.
절대경로는 /로 시작한다. 상대경로는 /로시작하지 않는다.

상대경로는 주소 기준이다. 마지막 / 이후의 값을 변경해서 사용한다.
http://localhost:8080/JSP2023/ch07/lecture/04path/01path.jsp에서
상대경로 02path.jsp로 이동하면
http://localhost:8080/JSP2023/ch07/lecture/04path/02path.jsp이게 된다.

절대경로는 첫번째 ip:포트번호 /를 기준으로 한다.
http://localhost:8080/JSP2023/ch07/lecture/04path/01path.jsp
절대경로 /02path.jsp로 이동하면
http://localhost:8080/02path.jsp가 되게 된다.

즉 상대 경로는 현재 위치 기준으로 가게 되고 절대 경로는 상관없이 이동하게 된다.
이때 우리가 작성한 jsp는 대부분 폴더명을 따라가게 된다.

톰캣이 어플리케이션을 실행시키는데 하나가 아닐 수 있다.
그래서 각 어플리케이션을 구분하는 경로가 폴더명으로 정해져있다.
이것을 context라고 한다.
우리가 작성한 폴더는 우리 프로젝트 명으로 정해지게 된다.

클라이언트 입장에서의 절대경로는 ip:포트번호/부터 시작하게 된다.
서버의 절대 경로는 webapp기준으로 절대경로를 찾는다.

상대경로
<jsp:forward page="03path.jsp"></jsp:forward>
절대경로
<jsp:forward page="/03path.jsp"></jsp:forward>

위 예제의 경우 전자는 같은 폴더의 03path.jsp을 찾게되고
후자는 webapp파일(root)을 기준으로 03path.jsp를 찾게 된다.

7.11 경로 - 2

상대경로와 사용할 수 있는 기호가 있다.
.. : 한단계위로라는 뜻이다.
http://localhost:8080/JSP2023/ch07/lecture/04path/04path.jsp을 기준으로 햇을때

05path.jsp의 요청경로는 마지막만 바뀐다.
http://localhost:8080/JSP2023/ch07/lecture/04path/05path.jsp 가된다.

../05path.jsp의 요청경론느 한단계위로 올라간다음의 경로이다.
http://localhost:8080/JSP2023/ch07/lecture/05path.jsp

../../05path.jsp하면 두단계위로 가게 된다.
http://localhost:8080/JSP2023/ch07/05path.jsp

같은 경로들을 절대경로로 표현하면 다음과 같다.
/JSP2023/ch07/lecture/04path/05path.jsp
/JSP2023/ch07/lecture/05path.jsp
/JSP2023/ch07/05path.jsp
루트파일을 기준으로 표현을 해줘야한다.

톰캣이 사용할때 사용하는 폴더명(컨텍스트명)은 변경될 수 있다.
서버를 더블클릭하면 설정 창이 뜬다. -> modules를 누를 수잇다.
그러면 들어있는 module(프로젝트)가 보이게 된다.
edit누르면 어떤 경로에서 실행되야하는지 알 수있다.
처음에는 프로젝트 명을 기준으로 실행된다.
컨텍스트 명을 바꿔서 경로를 바꿀 수 있다.

7.12 경로 - 3

절대경로를 사용할때 컨텍스트명으로 바뀔 수 있어서 그대로 사용하면 안된다.
따라서 컨텍스트명을 request에서 얻어서 사용해야한다.
String contextPath = request.getContextPath();
/<%= contextPath %>/ch07/lecture/04path/04path.jsp"
를하게 되면 다음과 같은 결과를 가지게 된다.
/jsp2023/ch07/lecture/04path/04path.jsp"

따라서 절대경로를 사용할때는 직접을 사용하지 않고 익스프레션을 이용해서 경로를 받아서 사용하도록 하자.

7.13 foward - 2

view.jsp의 내용이다.
값을 받아 확인하면 각 페이지로 foward해주게 되는데
사용자 입장에서는 view.jsp가 일하는 것처럼 보이게 된다.
포워드 액션태그 자체는 중요하진 않지만 포워드의 내용은 매우 중요하니 잘알아두자.

<% 
    String code = request.getParameter("code");
    String viewPageURI = null;

    if (code.equals("A")){
        viewPageURI = "/c07/viewModule/a.jsp";
    } else if (code.equals("B")){
        viewPageURI = "/c07/viewModule/b.jsp";
    } else if (code.equals("C")){
        viewPageURI = "/c07/viewModule/c.jsp";
    }
%>
<jsp:forward page="<%=viewPageURI%>"></jsp:forward>

7.14 foward - 3

클라이언트는 하나의 요청만 보내는데 두개의 jsp가 처리를 해준다.
그래서 forward받는 jsp가 정보를 전달받아 일을 해야한다면 request객체를 넘겨줄 수 있다.
그 방법에는 여러가지가 있다.

7.14.1 파라미터

첫번째 방법은 파라미터로 값을 넘기는 것이다.

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

<jsp:forward page="04to.jsp">
    <jsp:param value="seoul" name="address" />
</jsp:forward>

<%@ 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>
    <h1> address : <%= request.getParameter("address") %></h1>
</body>
</html>

7.14.2 attribute

파라미터는 String밖에 보내지 못한다.
두번째 방법은 request.setAttribute로 보내는 것이다.
attribute는 object타입을 반환하기 때문에 형변환을 해줘야한다.

<%
    List<String> nameList = new ArrayList<>();
    nameList.add("바바리안");
    nameList.add("바드");
    nameList.add("소서러");
    request.setAttribute("nameList", nameList);
%>
<jsp:forward page="10attribute-to.jsp"></jsp:forward>

<%
    List<String> names = (List<String>) request.getAttribute("nameList");
%>
<h1>1번이름 : <%= names.get(0) %></h1>
<h1>2번이름 : <%= names.get(1) %></h1>
<h1>3번이름 : <%= names.get(2) %></h1>

foward라는 기능이 잇고 같은 request를 사용하는데 붙엿다 꺼냇다 할 수 있다.

7.15 redirection

redirection은 foward와 비슷한 기능을 해서 비교가 되는 기능이다.

foward는 요청을 한번만해서 응답을 하는 것이다.

redirect는 첫번째 요청에 대해서 다른데로 요청을 하라고 응답한다.
그래서 두번째 요청이 발생하고 두번째 응답을 받은 것이 화면에 표시가 된다.
서비스함수의 두개의 파라미터중에서 response객체를 사용하게 된다.
response객체는 톰캣이 잘 분석해서 브라우저에게 적절한 응답을 하게 된다.
그래서 응답을 하고 싶다면 response객체를 조작하면된다.
HttpServletResoponse를 api에서 보면 사용할 수 잇는 메소드를 볼 수 있다.

resonse.sendRedirect()를 사용하면 redirection을 사용할 수 있다.
resonse.sendRedirect를하게 되면 302요청하게 된다.
이것을 응답 받으면 Location헤더를 찾고 이곳으로 재 요청을 하게 된다.

<%
    response.sendRedirect("https://www.daum.net");
%>

을 하게 되면 다음을 응답받게 된다.
03redirect.jsp가 302응답을 하게 되고 주어진 경로를 Location헤더에 포함하게 한다.
그래서 두번째 요청을 daum을 요청해서 응답받게 된다.

foward는 요청을 한번만 받기 때문에 주소가 바뀌지 않는다.
redirect는 요청을 새로 보내는 것이라 주소도 바뀐다.

7.16 redirection-2

sendRedirect("05to.jsp");를 하게 되면
05to.jsp로 다시 요청하라는 응답이다.
response header에 다음 내용을 심게 된다.
상태코드 : 302
Location : 05to.jsp

response객체를 사용하는 이유는 redirection이 응답이기 때문이다.
그런데 redirect는 새로운 응답을 보내는 것이기때문에 request객체를 이어서 작성할 수 없다.

foward는 첫번째 요청이 들어올때 request를 받는다. 그래서 이걸이어서 다른 jsp파일에서 처리를 하는 것이다.
그런데 redirect는 처음 jsp에서 request를 받은 후 응답으로 새로운 jsp로 요청하라고 하기때문에
새로 request를 하는 것이라 이전 jsp의 request를 사용할 수 없다.

<%
    request.setAttribute("name", "강백호");
    response.sendRedirect("07to.jsp");
%>

<h1>07to.jsp입니다.</h1>
<%
    String name = (String) request.getAttribute("name"); //불가능
%>
<h1> name : 속성 <%= name %></h1> <!-- null -->

7.17 redirect - 3

그래도 redirect할때 값을 전달하고 싶을때 사용할 수 있는 방법이 있다.
주소를 요청할때 부가적인 정보를 전달하는 방법을 우리는 알고 있다 바로 쿼리스트링이다.
두번째 요청에 쿼리스트링도 작성해서 redirect를 하게 되면 그 값을 꺼내서 사용할 수 있다.

<%
    String location = "09to.jsp?name=backho&address=seoul";
    response.sendRedirect(location);
%>

<h1>9번 파일</h1>    
<h1>name 파라미터 : <%= request.getParameter("name") %></h1>
<h1>address 파라미터 : <%= request.getParameter("address") %></h1>

7.18 redirect 4 연습

10번파일로 첫번째 요청 11번으로 redirect하는 코드를 작성해보자.
두개의 배열을 받아와야하니 두개이상의 name쿼리스트링을 작성해야한다.

<%
    String p = request.getParameter("position");
    String[] names = request.getParameterValues("name");
%>
<h1> 포지션 : <%= p %></h1>
<h1> 이름1 : <%= names[0] %></h1>
<h1> 이름2 : <%= names[1] %></h1>

<%
    String location = "11to.jsp?position=druid&name=malfurion&name=tirande";
    response.sendRedirect(location);
%>

7.19 session

redirect를 할때 값을 가져가고 싶다면 세션을 사용할 수 있다.
request에 값을 넣듯이 session.setAttribute 하면 객체를 건넬수 있다.

<%
request.setAttribute("address", "seoul");
session.setAttribute("address", "jeju");

String location = "13toSession.jsp";
response.sendRedirect(location);
%>

<h1>13번 파일</h1>

<%
Object a = request.getAttribute("address");
Object b = session.getAttribute("address");
%>

<p>request attribute address : <%= a %></p>
<p>session attribute address : <%= b %></p>

7.20 session 연습

14번 파일 작성 -> 15번으로 redirect 하기, 오류 나지 않게

<h1>15번 파일</h1>
<%
List<String> list = (List<String>) session.getAttribute("names");
%>

<h1>name1 : <%= list.get(0) %></h1>
<h1>name2 : <%= list.get(1) %></h1>

<%
List<String> list = new ArrayList<>();
list.add("강백호");
list.add("서태웅");
session.setAttribute("names", list);

response.sendRedirect("15to.jsp");
%>

10장 session

중요해서 다른 장으로 나누어져있다.
여러 브라우저에서 공유하는 한 공간이 세션이다.

session은 하나의 브라우저에서 오는 요청들(request)이 공유하는 객체이다.
같은 브라우저에서 요청을 보냈다는 사실을 알면 이 정보를 세션을 만들어서 정보를 저장할 수 있다.
이 세션을 다른사람이 볼수 있느냐? 그건 아니다
그 사람을 위한 다른 객체를 만들어서 저장을 하게 된다.

세션은 브라우저마다 하나씩 잇고 이것은 서버에 저장이 된다.

<h1>2번파일</h1>
<h1>session 참조값 : <%= System.identityHashCode(session) %></h1>

<h1>3번 파일</h1>
<h1>session 참조값 : <%= System.identityHashCode(session) %></h1>

같은 session의 값을 가지고 있다. 세션은 각 서버에 저장이된다.
같은 브라우저에서 요청이 오면 같은 세션에서 정보를 전달해준다.

10.1 session -1

장바구니라고 해보자.
폼의 체크박스에 담은것을 전송할 수 있다.
브라우저마다 서로다른 세션을 가지고 있기 때문에 브라우저마다 다른 장바구니를 유지할 수 있다.
다음은 product라는 이름으로 리스트를 만들어서 담고 remove로 리스트를 비우는 것이다.

<form method="post">
    <select name="product" id="">
        <option value="apple">apple</option>
        <option value="banana">banana</option>
        <option value="milk">milk</option>
        <option value="beer">beer</option>
        <option value="water">water</option>
    </select>
    <input type="submit" value="장바구니 담기" />
</form>

<hr />

<form action="" method="post">
    <input type="hidden" name="remove" value="true" />
    <input type="submit" value="장바구니 비우기" />
</form>

<hr />
<h3>장바구니</h3>
<%
List<String> cart = (List<String>) session.getAttribute("cart");
if (cart == null) {
    cart = new ArrayList<>();
    session.setAttribute("cart", cart);
}

String product = request.getParameter("product");
if (product != null && !product.isEmpty()) {
    cart.add(product);
}

String remove = request.getParameter("remove");
if (remove != null && remove.equals("true")) {
    cart.clear();
}

out.println("<ul>");
for (String c : cart) {
    out.println("<li>");
    out.println(c);
    out.println("</li>");
}
out.println("</ul>");
%>

10.2 session -2

각자의 세션을 가지게 되는데 네이버는 수천명이 접속하면 수천명의 세션을 만들게 된다.
로그인을 해서 다른 페이지로 가도 로그인이 유지가 되는 것이 세션을 사용하는 것이다.

<a href="05name.jsp">이름 등록 페이지</a> <br />
<a href="06name.jsp">메일 보기</a> <br />
<a href="07name.jsp">뉴스 보기</a>

<form action="" method="post">
이름 <input type="text" name="username" value="채소연" /> 
<input type="submit" value="등록" />
</form>

<%
String userName = request.getParameter("username");

if (userName != null) {
    session.setAttribute("user", userName);
    out.println("이름이 등록되었습니다.");
}
%>

<a href="05name.jsp">이름 등록 페이지</a> <br />
<a href="06name.jsp">메일 보기</a> <br />
<a href="07name.jsp">뉴스 보기</a>

<h1>6번 파일 : 메일 보는 페이지</h1>
<h1><%= session.getAttribute("user") %>님의 메일 보는 중</h1>

<a href="05name.jsp">이름 등록 페이지</a> <br />
<a href="06name.jsp">메일 보기</a> <br />
<a href="07name.jsp">뉴스 보기</a>

<h1>7번 파일 : 뉴스 보는 페이지</h1>
<h1><%= session.getAttribute("user") %>님이 선택한 뉴스 보는 중</h1>

10.3 session 상태 유지

요청을 하면 응답을 해준다. 첫 요청을 하고 첫 응답을 할때 증표를 건네준다.
다음부터는 증표를 가지고 오게 한다. 두번째 요청할때 증표를 가지고 가면 같은 사람임을 알게 된다.

개발자도구 를 보면 첫 요청이면 response헤더에 쿠키에 담아 보내주게 된다.
이후 두번째 요청을 하면 request 헤더에 가지고 갔던 세션아이디를 가지고 오게 된다.

session.getId()메소드를 사용하면 세션아이디를 볼 수 있다.
session.invalidate();을 하면 세션을 파기시킬 수 있다.

<h1>세션 아이디 보기</h1>
<h1><%= session.getId() %></h1>

<hr />

<a href="09invalidate.jsp">세션 파기하기</a>

2023.03.30 후기

redirect vs foward에 대해서 구분을 잘할 필요가 있다.
포워드는 모델2에 가서 서블릿에서 jsp로 값을 넘길때 아주 잘 사용된다. 의미를 잘 파악해둘 필요가 있다.