본문 바로가기
네이버클라우드/JAVA 웹 프로그래밍

JAVA 64일차 (2023-08-23) 자바 프로그래밍_Servlet 정리 ex09~ex11

by prometedor 2023. 8. 23.
- 서블릿 프로그래밍
  - 보관소 사용법: ServletContext, HttpSession, ServletRequest, JspContext
  - 쿠키 사용법
  - 세션 사용법

 

Servlet 정리

servlet-app 프로젝트

ㄴ eomcs.servlet.ex09 패키지 생성하기

=>

ㄴ /Users/사용자명/git/eomcs-java/eomcs-servlet/app/src/main/java/com/eomcs/web/ex09 에 존재하는 파일 모두 복사하기

=>

ㄴ 인텔리제이에서 생성한 ex09 패키지에 복사한 파일 모두 붙여넣기

=>

보관소에 값 넣기

Servlet01.java (ex09)

// 보관소에 값 넣기
package eomcs.servlet.ex09;

import javax.servlet.ServletContext;
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 javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/ex09/s1")
@SuppressWarnings("serial")
public class Servlet01 extends HttpServlet {

  @Override
  protected void service(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

    // 테스트 방법:
    // => http://localhost:8080/java-web/ex09/s1
    //

    // 1) ServletContext 보관소에 값 넣기
    // => ServletContext 객체는 웹 애플리케이션이 시작될 때 생성된다.
    ServletContext sc = this.getServletContext();
    sc.setAttribute("v1", "aaa");

    // 2) HttpSession 보관소에 값 넣기
    // => HttpSession 객체는 웹 브라우저에서
    //    '세션 아이디(예:고객번호, 스탬프 카드)'를 제공하지 않으면,
    //    getSession()을 호출할 때 생성된다.
    //    즉 이 요청을 한 클라이언트의 HttpSession 객체가 없다면 만들어준다.
    // => 웹 브라우저에서 '세션 아이디'를 제공하면,
    //    getSession()을 호출할 때 기존에 생성했던 세션 객체를 리턴한다.
    //    즉 이미 이 클라이언트를 위해 만든 객체가 있다면 그 객체를 리턴한다.
    HttpSession session = request.getSession();
    session.setAttribute("v2", "bbb");

    // 3) ServletRequest 보관소에 값 넣기
    // => ServletRequest 객체는 클라이언트가 요청할 때마다 생성된다.
    request.setAttribute("v3", "ccc");

    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();

    out.println("보관소에 값을 넣었습니다. - /ex09/s1");

  }
}

ㄴ ServletContext 보관소에 값 넣기

ㄴ HttpSession 보관소에 값 넣기

ㄴ ServletRequest 보관소에 값 넣기

=>

ㄴ App 실행

=>

ㄴ 크롬에서 localhost:8888/ex09/s1 를 요청하여 보관소에 값을 넣음

 

 

보관소에 저장된 값 꺼내기

Servlet02.java  (ex09)

// 보관소에 저장된 값 꺼내기
package eomcs.servlet.ex09;

import javax.servlet.ServletContext;
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 javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/ex09/s2")
@SuppressWarnings("serial")
public class Servlet02 extends HttpServlet {

  @Override
  protected void service(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

    // 테스트 방법:
    // => http://localhost:8080/java-web/ex09/s2
    //

    // 1) ServletContext 보관소에 저장된 값 꺼내기
    ServletContext sc = this.getServletContext();
    String v1 = (String) sc.getAttribute("v1");

    // 2) HttpSession 보관소에 저장된 값 꺼내기
    // => 이 요청을 한 클라이언트의 HttpSession 객체가 없다면 만들어준다.
    // => 이미 이 클라이언트를 위해 만든 객체가 있다면 그 객체를 리턴한다.
    HttpSession session = request.getSession();
    String v2 = (String) session.getAttribute("v2");

    // 3) ServletRequest 보관소에 저장된 값 꺼내기
    String v3 = (String) request.getAttribute("v3");

    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();

    out.println("보관소에 저장된 값 꺼내기 - /ex09/s2");
    out.printf("v1 = %s\n", v1);
    out.printf("v2 = %s\n", v2);
    out.printf("v3 = %s\n", v3);

  }
}

=>

Servlet02.java  (ex09)

ㄴ ServletContext 의 getServletContext() 메서드 이용하여 ServletContext 보관소에 저장된 값 꺼낼 수 있음

=>

Servlet02.java  (ex09)

ㄴ HttpServletRequest 의 getSession() 메서드 이용하여 HttpSession 보관소에 저장된 값 꺼낼 수 있음

=>

Servlet02.java  (ex09)

ㄴ HttpServletRequest 의 getAttribute 메서드를 이용하여 ServletRequest 보관소에 저장된 값 꺼낼 수 있음

=>

ㄴ 크롬에서 localhost:8888/ex09/s2 요청 시 v1 과 v2  값을 꺼낼 수 있음

=>

ㄴ 네이버 웨일에서 localhost:8888/ex09/s2 요청 시 v1 값만 꺼낼 수 있음

=>

ㄴ 크롬에서 새 창을 띄워 localhost:8888/ex09/s2 요청 시 그대로 v1 과 v2  값을 꺼낼 수 있음

=>

ㄴ 크롬에서 [새 시크릿 창] 선택

=>

ㄴ 시크릿 창은 쿠키를 저장하지 않으므로 v1 값 만 가져올 수 있음

 

 

보관소에 값 넣기 - forward/include 서블릿끼리 ServletRequest 공유하는 것 테스트

Servlet11.java

// 보관소에 값 넣기 - forward/include 서블릿끼리 ServletRequest 공유하는 것 테스트
package eomcs.servlet.ex09;

import javax.servlet.ServletContext;
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 javax.servlet.http.HttpSession;
import java.io.IOException;

@WebServlet("/ex09/s11")
@SuppressWarnings("serial")
public class Servlet11 extends HttpServlet {

  @Override
  protected void service(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

    // 테스트 방법:
    // => http://localhost:8080/java-web/ex09/s11
    //

    // 1) ServletContext 보관소에 값 넣기
    ServletContext sc = this.getServletContext();
    sc.setAttribute("v1", "xxx");

    // 2) HttpSession 보관소에 값 넣기
    // => 이 요청을 한 클라이언트의 HttpSession 객체가 없다면 만들어준다.
    // => 이미 이 클라이언트를 위해 만든 객체가 있다면 그 객체를 리턴한다.
    HttpSession session = request.getSession();
    session.setAttribute("v2", "yyy");

    // 3) ServletRequest 보관소에 값 넣기
    request.setAttribute("v3", "zzz");

    // 주목!
    // => 포워드(인클루드 포함)할 때 이 서블릿이 파라미터로 받은
    // ServletRequest와 ServletResponse를 전달한다.
    // => 따라서 포워드/인클루드 서블릿들은 응답을 완료할 때까지 이 객체들을 공유하는 것이다.
    //
    request.getRequestDispatcher("s12").forward(request, response);

  }
}

=>

ㄴ forward 를 이용 "s12"라는 이름을 가진 리소스로 포워딩할 수 있는 객체를 반환

    ㄴ 여기서 "s12"는 포워딩 대상 리소스의 경로를 나타내는 것

ㄴ 포워딩은 현재 서블릿의 제어를 다른 리소스로 넘겨주는 것이며, 브라우저에 응답을 보내지 않고 서버 내부에서 이루어짐

=>

보관소에 저장된 값 꺼내기 - forward/include 서블릿끼리 ServletRequest 공유하는 것 테스트

Servlet12.java

// 보관소에 저장된 값 꺼내기 - forward/include 서블릿끼리 ServletRequest 공유하는 것 테스트
package eomcs.servlet.ex09;

import javax.servlet.ServletContext;
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 javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/ex09/s12")
@SuppressWarnings("serial")
public class Servlet12 extends HttpServlet {

  @Override
  protected void service(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

    // 테스트 방법:
    // => http://localhost:8080/java-web/ex09/s11
    //

    // 1) ServletContext 보관소에 저장된 값 꺼내기
    ServletContext sc = this.getServletContext();
    String v1 = (String) sc.getAttribute("v1");

    // 2) HttpSession 보관소에 저장된 값 꺼내기
    // => 이 요청을 한 클라이언트의 HttpSession 객체가 없다면 만들어준다.
    // => 이미 이 클라이언트를 위해 만든 객체가 있다면 그 객체를 리턴한다.
    HttpSession session = request.getSession();
    String v2 = (String) session.getAttribute("v2");

    // 3) ServletRequest 보관소에 저장된 값 꺼내기
    String v3 = (String) request.getAttribute("v3");

    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();

    out.println("보관소에 저장된 값 꺼내기 - /ex09/s12");
    out.printf("v1 = %s\n", v1);
    out.printf("v2 = %s\n", v2);
    out.printf("v3 = %s\n", v3);

  }
}

=>

 

 

ㄴ eomcs.servlet.ex09 패키지 생성하기

=>

ㄴ /Users/사용자명/git/eomcs-java/eomcs-servlet/app/src/main/java/com/eomcs/web/ex10 에 존재하는 파일 모두 복사하기

=>

ㄴ 인텔리제이에서 생성한 ex10 패키지에 복사한 파일 모두 붙여넣기

 

 

쿠키(cookie) 보내기

 쿠키
     => 웹서버가 웹브라우저에게 맡기는 데이터이다.
     => 응답할 때 응답 헤더에 포함시켜 보낸다.
     => 웹브라우저는 응답헤더로 받은 쿠키 데이터를 보관하고 있다가
        지정된 URL을 요청할 때 요청 헤더에 포함시켜 웹 서버에게 쿠키를 다시 보낸다.
     => HTTP 응답 프로토콜

     HTTP/1.1 200
     Set-Cookie: name=hong <---- Set-Cookie 헤더에 '이름=값' 형태로 쿠키를 보낸다.
     Set-Cookie: age=20
     Set-Cookie: working=true
     Set-Cookie: name2=홍길동 <---- URL 인코딩 하지 않은 상태
     Set-Cookie: name3=%ED%99%8D%EA%B8%B8%EB%8F%99 <---- URL 인코딩한 예
     Content-Type: text/plain;charset=UTF-8
     Content-Length: 35 Date: Thu, 24 Aug 2023 15:49:15 GMT
     ...

Servlet01.java (ex10)

// 쿠키(cookie) 보내기
package eomcs.servlet.ex10;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLEncoder;

@WebServlet("/ex10/s1")
@SuppressWarnings("serial")
public class Servlet01 extends HttpServlet {

  @Override
  protected void service(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

    // 테스트 방법:
    // => http://localhost:8080/java-web/ex10/s1
    //

    // 쿠키 생성
    // => 이름과 값으로 생성한다.
    // => 쿠키의 유효기간을 설정하지 않으면 웹브라우저가 종료될 때 까지 유지된다.
    //    웹브라우저를 종료하면 유효기간이 지정되지 않은 쿠키는 모두 삭제된다.
    // => 쿠키의 사용범위를 지정하지 않으면 현재 경로에 한정한다.
    //    쿠키를 보낼 때의 URL이 /ex10/s1 이라면,
    //    웹브라우저는 /ex10/* 경로를 요청할 때만 웹서버에게 쿠키를 보낸다.
    Cookie c1 = new Cookie("name", "hong");
    // 프로토콜 예 => Set-Cookie: name=hong


    // => 값은 반드시 문자열이어야 한다.
    //    만약 문자열이 아닌 값을 보내려면 Base64와 같은 인코딩 기법을 이용하여
    //    바이너리 데이터를 문자화시켜서 보내야 한다.
    Cookie c2 = new Cookie("age", "20");
    // 프로토콜 예 => Set-Cookie: age=20

    Cookie c3 = new Cookie("working", "true");
    // 프로토콜 예 => Set-Cookie: working=true

    // => 또한 값은 반드시 ISO-8859-1 이어야 한다.
    //    만약 UTF-8을 보내고 싶다면 URL 인코딩 같은 기법을 사용하여
    //    ASCII 코드화시켜 보내야 한다.
    Cookie c4 = new Cookie("name2", "홍길동");
    // 프로토콜 예 => Set-Cookie: name2=홍길동

    Cookie c5 = new Cookie("name3", URLEncoder.encode("홍길동", "UTF-8"));
    // 프로토콜 예 => Set-Cookie: name3=%ED%99%8D%EA%B8%B8%EB%8F%99

    // 쿠키를 응답 헤더에 포함시키기
    response.addCookie(c1);
    response.addCookie(c2);
    response.addCookie(c3);
    response.addCookie(c4);
    response.addCookie(c5);

    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();

    out.println("/ex10/s1 - 쿠키 보냈습니다.");
  }
}

=>

Servlet01.java (ex10)

ㄴ Cookie 는 이름과 값으로 생성함

=>

Servlet01.java (ex10)

ㄴ 값은 반드시 문자열이어야 함

     ㄴ 만약 문자열이 아닌 값을 보내려면 인코딩 기법을 이용하여 바이너리 데이터를 문자화시켜서 보내야 함

=>

Servlet01.java (ex10)

ㄴ addCookie() 메서드를 이용하면 쿠키를 응답 헤더에 포함시킬 수 있음

=>

ㄴ App 실행

=>

ㄴ 넘어가는 쿠키 값을 확인

=>

ㄴ UTF-8 을 보내고 싶다면 URL 인코딩 기법을 사용하여 ASCII 코드화시켜 보내야 함

 

받은 쿠키(cookie) 읽기

 클라이언트 보낸 쿠키 읽기
     => 요청 헤더에 포함된 쿠키를 읽는다.
     => HTTP 요청 프로토콜

     GET /java-web/ex10/s2 HTTP/1.1
     Host: localhost:8080
     Connection: keep-alive
     Cookie: name=hong; age=20; working=true; name2=홍길동; name3=%ED%99%8D%EA%B8%B8%EB%8F%99
     ...

Servlet02.java

// 받은 쿠키(cookie) 읽기
package eomcs.servlet.ex10;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLDecoder;

@WebServlet("/ex10/s2")
@SuppressWarnings("serial")
public class Servlet02 extends HttpServlet {

  @Override
  protected void service(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

    // 테스트 방법:
    // => http://localhost:8080/java-web/ex10/s2
    //

    // 쿠키 꺼내기
    // => 쿠키를 이름으로 한 개씩 추출할 수 없다.
    // => 한 번에 배열로 받아야 한다.
    // => 요청 헤더에 쿠키가 없으면 리턴 되는 것은 빈 배열이 아니라 null이다.
    // => 따라서 무조건 반복문을 돌리면 안된다.
    //
    Cookie[] cookies = request.getCookies();

    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();

    if (cookies != null) {
      for (Cookie c : cookies) {
        // 쿠키 값이 'URL 인코딩'한 값이라면
        // 개발자가 직접 디코딩 해서 사용해야 한다.
        // 쿠키 값에 대해서는 서버가 자동으로 디코딩 해주지 않는다.
        out.printf("%s=%s,%s\n",
            c.getName(),
            c.getValue(),
            URLDecoder.decode(c.getValue(), "UTF-8"));
      }
    }

  }
}

=>

ㄴ name2 의 값을 보면 이상한 문자가 넘어가는 것을 확인할 수 있음

 

 

쿠키(cookie) - 유효기간 설정하기

 쿠키 유효기간
     => 유효기간을 설정하면 웹브라우저는 그 기간 동안 보관하고 있다가
        웹서버에게 쿠키를 보낸다.
     => HTTP 응답 프로토콜

     HTTP/1.1 200
     Set-Cookie: v1=aaa
     Set-Cookie: v2=bbb; Max-Age=30; Expires=Thu, 24 Aug 2023 16:10:17 GMT
     Set-Cookie: v3=ccc; Max-Age=60; Expires=Thu, 24 Aug 2023 16:10:47 GMT
     Content-Type: text/plain;charset=UTF-8
     Content-Length: 36
     Date: Thu, 24 Aug 2023 16:09:47 GMT
     Keep-Alive: timeout=20
     Connection: keep-alive

Servlet11.java

// 쿠키(cookie) - 유효기간 설정하기
package eomcs.servlet.ex10;

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

@WebServlet("/ex10/s11")
@SuppressWarnings("serial")
public class Servlet11 extends HttpServlet {

  @Override
  protected void service(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

    // 테스트 방법:
    // => http://localhost:8080/java-web/ex10/s11
    //

    // 유효기간을 설정하지 않으면 웹브라우저가 실행되는 동안에만 웹서버에게 쿠키를 보낸다.
    // => 웹 브라우저는 메모리에 쿠키를 보관한다.
    Cookie c1 = new Cookie("v1", "aaa");

    // 유효기간을 설정하면 웹브라우저를 종료해도 삭제되지 않는다.
    // 단 유효기간이 지나면 웹서버에 보내지 않고 삭제한다.
    // => 웹 브라우저는 로컬 디스크에 쿠키를 보관한다.
    Cookie c2 = new Cookie("v2", "bbb");
    c2.setMaxAge(30); // 쿠키를 보낸 이후 30초 동안만 유효

    Cookie c3 = new Cookie("v3", "ccc");
    c3.setMaxAge(60); // 쿠키를 보낸 이후 60초 동안만 유효

    // 쿠키를 응답 헤더에 포함시키기
    response.addCookie(c1);
    response.addCookie(c2);
    response.addCookie(c3);

    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();

    out.println("/ex10/s11 - 쿠키 보냈습니다.");
  }
}

ㄴ setMaxAge 메서드를 이용하여 쿠키를 보낸 이후 ss초 동안만 유효하도록 유효기간 설정할 수 있음

 

 

쿠키(cookie) 읽기 - 유효기간이 설정된 쿠키 읽기

클라이언트 보낸 쿠키 읽기
     => 요청 헤더에 포함된 쿠키를 읽는다.
     => HTTP 요청 프로토콜

     GET /java-web/ex10/s2 HTTP/1.1 Host: localhost:8080 Connection: keep-alive ... Cookie:
     name=hong; age=20; working=true; name2=홍길동; name3=%ED%99%8D%EA%B8%B8%EB%8F%99

Servlet12.java

// 쿠키(cookie) 읽기 - 유효기간이 설정된 쿠키 읽기
package eomcs.servlet.ex10;

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

@WebServlet("/ex10/s12")
@SuppressWarnings("serial")
public class Servlet12 extends HttpServlet {

  @Override
  protected void service(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

    // 테스트 방법:
    // => http://localhost:8080/java-web/ex10/s12
    //

    // 쿠키 꺼내기
    // => 쿠키를 이름으로 한 개씩 추출할 수 없다.
    // => 한 번에 배열로 받아야 한다.
    // => 요청 헤더에 쿠키가 한 개라도 없으면 리턴 되는 것은 null이다.
    Cookie[] cookies = request.getCookies();

    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();

    if (cookies != null) {
      for (Cookie c : cookies) {
        out.printf("%s=%s\n", c.getName(), c.getValue());
      }
    }

  }
}

 

 


ㄴ Safari > 설정... 선택

=>

ㄴ 메뉴 막대에서 개발자용 메뉴 보기 > 체크 박스 체크하기

=>

ㄴ [control] + [command] + [i] 선택하여 개발자도구 띄우기 가능


 

ㄴ localhost:8888/ex10/s11 요청하기

=>

ㄴ 쿠키 유효기간 설정 확인

=>

ㄴ localhost:8888/ex10/s12 요청하기

=>

=>

ㄴ localhost:8888/ex10/s11 요청하기

=>

ㄴ localhost:8888/ex10/s12 요청하기

=>

=>

=>

ㄴ Safari 완전 종료 시키기

=>

ㄴ 크롬으로 실행하여 남아있는 v1, v3 확인

 

 

쿠키(cookie) - 쿠키 사용 범위 지정하기

     쿠키 사용범위
     => 쿠키의 사용 범위를 지정하지 않으면 쿠키를 발행한 URL 범위에 한정된다.
        즉 같은 URL로 요청할 때만 쿠키를 보낸다.
     => 예)
        서버에서 쿠키를 발행한 URL : /ex10/s21
        클라이언트가 쿠키를 보내는 URL : /ex10/*
        클라이언트가 쿠키를 보내지 않는 URL  : /ex10/* 이외의 모든 URL
     => HTTP 응답 프로토콜

Servlet21.java

// 쿠키(cookie) - 쿠키 사용 범위 지정하기
package eomcs.servlet.ex10;

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

@WebServlet("/ex10/s21")
@SuppressWarnings("serial")
public class Servlet21 extends HttpServlet {

  @Override
  protected void service(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

    // 테스트 방법:
    // => http://localhost:8080/java-web/ex10/s21
    //

    // 사용 범위를 지정하지 않은 쿠키
    // => 쿠키를 발급한 서블릿과 같은 경로이거나 하위 경로의 서블릿을 요청할 때만
    //    웹 브라우저가 서버에 쿠키를 보낸다.
    // => 기본: /ex10
    Cookie c1 = new Cookie("v1", "aaa");

    // 사용 범위 지정
    // => 쿠키를 발급한 서블릿의 경로에 상관없이 지정된 경로의 서블릿을 요청할 때
    // 웹 브라우저가 서버에 쿠키를 보낸다.
    Cookie c2 = new Cookie("v2", "bbb");
    c2.setPath("/ex10/a");

    Cookie c3 = new Cookie("v3", "ccc");
    c3.setPath("/");

    // 왜 쿠키의 경로를 적을 때 웹 애플리케이션 루트(컨텍스트 루트)까지 적나요?
    // => 쿠키 경로는 서블릿 컨테이너가 사용하는 경로가 아니다.
    // => 웹 브라우저가 사용하는 경로다.
    // => 웹 브라우저에서 '/' 은 서버 루트를 의미한다.
    // => 따라서 웹 브라우저가 사용하는 경로를 지정할 때는 조심해야 한다.
    // '/'가 서버 루트를 의미하기 때문이다.
    // => 그래서 쿠키의 경로를 지정할 때는 웹 애플리케이션 루트(컨텍스트 루트)를 정확하게 지정해야 한다.


    // 쿠키를 응답 헤더에 포함시키기
    response.addCookie(c1);
    response.addCookie(c2);
    response.addCookie(c3);

    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();

    out.println("/ex10/s21 - 쿠키 보냈습니다.");
  }
}

 

Servlet22.java

// 쿠키(cookie) 읽기 - 사용 범위가 지정된 쿠키 읽기
package eomcs.servlet.ex10;

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

@WebServlet("/ex10/s22")
@SuppressWarnings("serial")
public class Servlet22 extends HttpServlet {

  @Override
  protected void service(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

    // 테스트 방법:
    // => http://localhost:8080/java-web/ex10/s22
    //

    Cookie[] cookies = request.getCookies();

    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();

    if (cookies != null) {
      for (Cookie c : cookies) {
        out.printf("%s=%s\n", c.getName(), c.getValue());
      }
    }

  }
}

 

=>

=>

ㄴ v2 는 /ex10/a 경로 아래에서 요청할 때 보내짐

 

Servlet23.java

// 쿠키(cookie) 읽기 - 사용 범위가 지정된 쿠키 읽기
package eomcs.servlet.ex10;

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

@WebServlet("/ex10/a/b/c/s23")
@SuppressWarnings("serial")
public class Servlet23 extends HttpServlet {

  @Override
  protected void service(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

    // 테스트 방법:
    // => http://localhost:8080/java-web/ex10/a/b/c/s23
    //

    Cookie[] cookies = request.getCookies();

    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();

    if (cookies != null) {
      for (Cookie c : cookies) {
        out.printf("%s=%s\n", c.getName(), c.getValue());
      }
    }

  }
}

=>

 

Servlet24.java

// 쿠키(cookie) 읽기 - 사용 범위가 지정된 쿠키 읽기
package eomcs.servlet.ex10;

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

@WebServlet("/ex10_1/s24")
@SuppressWarnings("serial")
public class Servlet24 extends HttpServlet {

  @Override
  protected void service(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

    // 테스트 방법:
    // => http://localhost:8080/java-web/ex10_1/s24
    //

    Cookie[] cookies = request.getCookies();

    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();

    if (cookies != null) {
      for (Cookie c : cookies) {
        out.printf("%s=%s\n", c.getName(), c.getValue());
      }
    }

  }
}

=>

=>

ㄴ v3 는 / 경로 아래에서 요청할 때 보내짐

 

 

ㄴ eomcs.servlet.ex11 패키지 생성하기

=>

ㄴ /Users/사용자명/git/eomcs-java/eomcs-servlet/app/src/main/java/com/eomcs/web/ex11 에 존재하는 파일 모두 복사하기

=>

ㄴ 복사한 모든 파일을 인텔리제이에 붙여넣기

 

세션(session)

 세션
     => 클라이언트를 식별하는 기술이다.
     => HTTP 프로토콜은 Stateless 방식으로 통신을 한다.
        즉 연결한 후 요청하고 응답을 받으면 연결을 끊는다.
        그래서 서버는 클라이언트가 요청할 때 마다 누구인지 알 수 없다.
     => 이를 해결하기 위해
        클라이언트가 접속하면 웹 서버는 그 클라이언트를 위한
        고유 번호를 발급(쿠키 이용)한다.
        이 고유 번호를 '세션 아이디'라 부른다.
     => 웹 브라우저는 세션 아이디를 쿠키에 보관해 두었다가
        그 서버에 요청할 때 마다 세션 아이디를 보낸다.
        왜? 세션 아이디는 쿠키이다.
     => 서버에서 클라이언트로 세션 아이디를 쿠키로 보낼 때 유효기간을 설정하지 않았기 때문에
        웹 브라우저를 종료하면 세션 아이디 쿠키는 삭제된다.
     => 세션 아이디 쿠키의 사용 범위는 웹 애플리케이션 경로에 한정된다.
        예) /eomcs-java-web
        따라서 같은 웹 애플리케이션의 서블릿을 실행할 때는
        무조건 세션 아이디를 보낸다.

     세션 아이디는 언제 발급하는가?
     => 새 세션을 생성할 때 세션 아이디를 발급한다.

     언제 새 세션을 생성하는가?
     => 세션이 없거나 유효기간이 지난 경우, 
        request.getSesssion()을 호출할 때 생성한다.
     => 새로 세션을 생성하면 그 세션 ID를 쿠키로 웹브라우저에게 보낸다.
     => 세션이 없는 경우?
        클라이언트가 세션 아이디를 보내지 않을 때
     => 세션 유효기간이 지난 경우?
        세션을 생성한 후 서버에 설정된 시간이 지나도록
        클라이언트의 요청이 않으면
        서버는 세션을 무효화시킨다.
     => HTTP 응답 프로토콜

     HTTP/1.1 200
     Set-Cookie: JSESSIONID=5801C115615A2C9074AC0B78E31C5F21; Path=/eomcs-java-web; HttpOnly
     Content-Type: text/plain;charset=UTF-8
     Content-Length: 44
     Date: Wed, 08 Apr 2020 03:10:58 GMT
     Keep-Alive: timeout=20
     Connection: keep-alive

Servlet01.java (ex11)

// 세션(session)
package eomcs.servlet.ex11;

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 javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/ex11/s1")
@SuppressWarnings("serial")
public class Servlet01 extends HttpServlet {

  @Override
  protected void service(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

    // 테스트 방법:
    // => http://localhost:8080/java-web/ex11/s1

    // 세션 생성하기 : getSession() 호출
    //
    // 1) 클라이언트가 세션 아이디를 쿠키로 전송
    //    - 서버에서는 해당 아이디의 세션을 찾는다.
    //    - 있으면, 그 세션을 리턴한다.
    //    - 있는데 세션의 유효 기간이 지났다면, 새로 세션을 만들어 리턴한다.
    //    - 없다면, 새로 세션을 만들어 리턴한다.
    // 2) 클라이언트가 세션 아이디를 보내지 않은 경우
    //    - 서버는 새 세션을 만들어 리턴한다.
    //
    // 새로 세션을 만들면, 무조건 응답할 때 새 세션의 아이디를 쿠키로 보낸다.
    //
    HttpSession session = request.getSession();

    // 세션에 데이터 보관하기
    session.setAttribute("v1", "aaa");

    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();

    out.println("/ex11/s1 - 세션을 생성하였습니다!");
  }
}

ㄴ getSession() 을 호출하여 세션을 생성할 수 있음

=>

=>

ㄴ 응답 헤더에 JSESSIONID 생성하여 전달됨

=>

ㄴ 리프레시 시 Request 값에 JSESSIONID 포함됨

=>

세션(session)의 활용

Servlet11.java

// 세션(session)의 활용
package eomcs.servlet.ex11;

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 java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/ex11/s11")
@SuppressWarnings("serial")
public class Servlet11 extends HttpServlet {

  @Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

    response.setContentType("text/html;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("<html><head><title>페이지1</title></head><body>");
    out.println("<form action='s12' method='post'>");
    out.println("이름: <input type='text' name='name'><br>");
    out.println("<button>다음</button>");
    out.println("</form>");
    out.println("</body></html>");
  }
}

=>

=>

세션(session)의 활용 - 페이지2

Servlet12.java

// 세션(session)의 활용 - 페이지2
package eomcs.servlet.ex11;

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 javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/ex11/s12")
@SuppressWarnings("serial")
public class Servlet12 extends HttpServlet {

  @Override
  protected void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

    request.setCharacterEncoding("UTF-8");

    // 세션을 준비한다.
    HttpSession session = request.getSession();

    // 클라이언트가 보낸 데이터를 세션에 보관한다.
    session.setAttribute("name", request.getParameter("name"));

    response.setContentType("text/html;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("<html><head><title>페이지2</title></head><body>");
    out.println("<form action='s13' method='post'>");
    out.println("나이: <input type='text' name='age'><br>");
    out.println("<button>다음</button>");
    out.println("</form>");
    out.println("</body></html>");
  }
}

=>

=>

세션(session)의 활용 - 페이지3

Servlet13.java

// 세션(session)의 활용 - 페이지3
package eomcs.servlet.ex11;

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 javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/ex11/s13")
@SuppressWarnings("serial")
public class Servlet13 extends HttpServlet {

  @Override
  protected void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

    // 세션을 준비한다.
    HttpSession session = request.getSession();

    // 클라이언트가 보낸 데이터를 세션에 보관한다.
    session.setAttribute("age", request.getParameter("age"));

    response.setContentType("text/html;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("<html><head><title>페이지3</title></head><body>");
    out.println("<form action='s14' method='post'>");
    out.println("전화: <input type='text' name='tel'><br>");
    out.println("<button>다음</button>");
    out.println("</form>");
    out.println("</body></html>");
  }
}

=>

=>

세션(session)의 활용 - 페이지4

Servlet14.java

// 세션(session)의 활용 - 페이지4
package eomcs.servlet.ex11;

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 javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/ex11/s14")
@SuppressWarnings("serial")
public class Servlet14 extends HttpServlet {

  @Override
  protected void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

    // 세션을 준비한다.
    HttpSession session = request.getSession();

    // 클라이언트가 보낸 데이터를 세션에 보관한다.
    String tel = request.getParameter("tel");

    response.setContentType("text/html;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("<html><head><title>페이지4</title></head><body>");

    // 이전 서블릿에서 세션에 보관했던 값을 꺼내기
    // => 이것이 세션 보관소를 사용하는 이유이다.
    // => 여러 서블릿이 수행한 작업을 공유할 수 있다.
    // => 단 같은 클라이언트일 경우에만 사용할 수 있다.
    //
    out.printf("이름: %s<br>\n", session.getAttribute("name"));
    out.printf("나이: %s<br>\n", session.getAttribute("age"));

    out.printf("전화: %s<br>\n", tel);
    out.println("</body></html>");
  }
}

=>

 

세션(session)의 타임아웃 설정

Servlet21.java

// 세션(session)의 타임아웃 설정
package eomcs.servlet.ex11;

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 javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/ex11/s21")
@SuppressWarnings("serial")
public class Servlet21 extends HttpServlet {

  @Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

    HttpSession session = request.getSession();

    // 세션의 유효 시간(초)을 설정한다.
    // => 클라이언트가 요청하는 순간부터 세션 시간을 카운트 한다.
    // => 만약 10초 이내에 클라이언트의 요청이 없으면
    //    10초를 초과하는 순간 HttpSession 객체를 무효화시킨다.
    //    (어떤 서블릿을 요청하는 상관없다)
    // => 10초 이내에 다시 클라이언트 요청이 있다면
    //    카운트를 0부터 다시 시작한다.
    // => 예) 인터넷 뱅킹 에서 보통 세션 타임아웃을 10분으로 설정한다.
    //        클라이언트가 어떤 링크를 누르면 카운트는 다시 10분으로 초기화된다.
    session.setMaxInactiveInterval(10);

    session.setAttribute("v1", "aaa");

    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("/ex11/s21 실행함!");
  }
}

ㄴ setMaxInactiveInterval() 메서드를 이용하여 세션의 유효 시간(초)을 설정할 수 있음

=>

=>

ㄴ 10초 안에 /ex11/s22 요청 시 v1 값 aaa 를 가져옴

=>

ㄴ 10초가 지난 시점에서 /ex11/s22 요청 시 v1 값을 가져오지 못해 null 이 출력됨

 

 

세션(session) 무효화시키기

Servlet31.java

// 세션(session) 무효화시키기
package eomcs.servlet.ex11;

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 javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/ex11/s31")
@SuppressWarnings("serial")
public class Servlet31 extends HttpServlet {

  @Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

    HttpSession session = request.getSession();
    session.setAttribute("v1", "aaa");

    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("/ex11/s31 실행함!");
  }
}

=>

=>

세션(session) 무효화시키기 - 값 꺼내기

Servlet32.java

// 세션(session) 무효화시키기 - 값 꺼내기
package eomcs.servlet.ex11;

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 javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/ex11/s32")
@SuppressWarnings("serial")
public class Servlet32 extends HttpServlet {

  @Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

    // 클라이언트가 세션 아이디 쿠키를 서버에 보냈다 하더라도
    // 해당 세션이 무효화 되었다면
    // getSession()은 새 세션 객체를 만들어 리턴한다.
    //
    HttpSession session = request.getSession();

    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.printf("v1=%s\n", session.getAttribute("v1"));
  }
}

=>

=>

세션(session) 무효화시키기 - 세션 무효화하기

Servlet33.java

// 세션(session) 무효화시키기 - 세션 무효화하기
package eomcs.servlet.ex11;

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 javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/ex11/s33")
@SuppressWarnings("serial")
public class Servlet33 extends HttpServlet {

  @Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

    HttpSession session = request.getSession();
    session.invalidate(); // 세션을 무효화시킨다.

    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("세션을 무효화시켰습니다.");
  }
}

ㄴ invalidate() 메서드를 이용하여 세션을 무효화 시킬 수 있음

=>

=>

ㄴ 세션 무효화 후 다시 값 꺼내기 실행 시 null 출력됨을 확인