- 서블릿 프로그래밍
- 보관소 사용법: 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 출력됨을 확인