변수들의 범위를 scope라 한다.
Page Scope
서블릿이든 jsp든 선언된 그 페이지 내에서만 사용할 수 있는것이 Page Scope이다.
Request Scope
클라이언트가 request를 보내고 서버가 response를 보낼 때 까지 사용할 수 있는 Scope이 Request Scope이다.
servlet1->servlet2로 forwarding을 할 때 두 서블렛의 request영역은 같지만 page 영역은 다르다.
Session Scope
Session 객체가 생성되서 소멸될 때까지
여러개의 요청이 들어와도 계속 남아있다.
상태유지에 사용되는 Scope
Application Scope
하나의 어플리케이션이 생성되서 어플리케이션이 소멸될 때 까지 계속 유지하는 Scope이다.
PageContext 객체는 각 페이지마다 하나씩 생긴다고 생각하면 된다.
servlet1->servlet2로 forwarding 할 때, 먼저 servlet1의 PageContext가 생기고 servlet2로 넘어가면서 servlet1의 PageContext는 소멸하고 servlet2의 PageContext가 생성된다.
그냥 지역변수를 선언하는 거랑 별 다를게 없는데 주로 EL 표기법으로 편하게 사용하기 위해 사용한다.
그냥 PageContext.setAttribute와 PageContext.getAttribute 함수로 사용하면 된다.
WAS는 request가 들어오면 request와 response 객체를 만든다. 이 객체들은 클라이언트 요청 ~ 서버가 클라이언트에게 응답 하는 과정동안 유지되는 Request Scope이다. forwarding 할 때 서블릿->서블릿으로 넘어갈 때 request 객체에 setAttribute로 저장하고 다음 서블릿이 getAttribute로 값을 얻을 수 있는 이유가 이것이다.
서블릿에서는 함수의 인자로 request, response 를 받으니까 그걸 사용하면 된다.
JSP에서는 request 내장변수를 사용하면 된다.
저장은 request의 setAttribute, 참조는 getAttribute를 사용한다.
forwarding 할 때 값을 유지할 때 사용한다.
클라이언트(=브라우저) 마다 Session을 각각 만들어서 관리한다.
브라우저의 탭끼리는 Session 정보를 공유한다.
탭 하나에서 네이버에 로그인하고 다른 탭에서 네이버를 키면 이미 로그인되어 있는 것이 이 때문이다.
JSP에서는 session.setAttribute, getAttribue
서블릿에서는 getSession 메소드로 session 객체를 얻어서 사용해야 한다. 클라이언트의 정보를 알아야 session을 얻을 수 있어서 request.getSession 한다고 생각하면 된다.
마찬가지로 setAttriubute, getAttribute 메소드를 사용한다.
Session 객체는 코딩할 때 시간을 지정해놓거나 브라우저를 닫거나 하면 소멸된다.
서버에는 웹 어플리케이션이 여러개가 있을 수 있다.
firstWeb프로젝트를 통해 만든 firstWeb이 하나의 웹어플리케이션이다.
하나의 웹 어플리케이션 당 객체 하나를 가진다
어떤 클라이언트가 웹 어플리케이션에 접근하더라도 같은 Application Scope에 접근하게 된다. 즉 모든 클라이언트가 공통으로 사용할 데이터를 저장하면 좋다.
jsp에서는 application 내장객체, servlet에서는 getServletContext 메소드로 application 객체를 얻어서 사용한다. 클래스명은 ServletContext임
setAttribute, getAttribute 메소드를 사용해서 값 저장, 참조한다.
package examples;
import java.io.IOException;
import java.io.PrintWriter;
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.ServletContext;
/**
* Servlet implementation class Servlet1
*/
@WebServlet("/Servlet1")
public class Servlet1 extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public Servlet1() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
//import java.io.PrintWriter
PrintWriter out = response.getWriter();
//import javax.servlet.ServletContext
//application 객체를 얻는다.
ServletContext application = getServletContext();
//setAttribute로 데이터를 넣는다
int value = 1;
out.print("<h1>"+value+"</h1>");
application.setAttribute("value", value);
}
}
참고 : ServletContext 객체를 사용하기 위해서 import javax.servlet.ServletContext 해줘야함
Servlet1.java에서는 getServletContext 메소드로 ServletContext 객체, 즉 application 객체를 얻어와서 setAttribute로 값을 넣어줬다.
package examples;
import javax.servlet.ServletContext;
import java.io.PrintWriter;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class Servlet2
*/
@WebServlet("/Servlet2")
public class Servlet2 extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public Servlet2() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
ServletContext application = getServletContext();
//servlet1 실행 이전에 servlet2를 실행하면 아직 value가 application 객체에 저장되지 않은 상태다
//getAttribute의 결과로 null을 반환할테니 예외처리를 해준다.
try {
//application 객체로부터 getAttribute로 값을 얻어온다
//Object 형으로 반환하기 때문에 int로 형변환 필요
int value = (int)application.getAttribute("value");
value+=1;
out.print("<h1>"+value+"</h1>");
//value값에 1 더한후 출력하고 다시 setAttribute로 application 객체에 저장
application.setAttribute("value", value);
}catch(NullPointerException e) {
out.print("value 값이 지정되지 않음");
}
}
}
Servlet2.java에서는 마찬가지로 application 객체를 얻어와서 getAttribute로 value값을 얻어서 화면에 표시하고 다시 setAttribute로 값을 수정해줬다.
주의할 점은 만약 Servlet1.java보다 Servlet2.java를 먼저 서버에서 실행한다면 아직 value값은 setAttribute 되지 않은 상태인데 참조하려고 해서 NullPointerException이 발생한다. 이것을 예외처리 해주기 위해 try-catch 구문을 사용했다.
<%@ page language="java" contentType="text/html; charset=EUC-KR"
pageEncoding="EUC-KR"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="EUC-KR">
<title>Insert title here</title>
</head>
<body>
<%
//jsp 파일에서는 application 내장객체를 이용한다
try { int value = (int)application.getAttribute("value");
value+=2;
%>
<h1><%= value %></h1>
<% application.setAttribute("value",value); }catch(NullPointerException e){
%> value 값이 지정되지 않았습니다
<%} %>
</body>
</html>
Servlet2.java와 같은 일을 jsp 파일에서 하는 것이다.
jsp파일에서는 application객체를 내장객체인 application으로 바로 참조할 수 있다.
마찬가지로 예외처리를 해줬다.
화면에 value를 출력하기 위해서는 <%= %> 를 사용해 html 태그 안에 java 변수 value를 넣어서 표시해줬다.
이렇게 jsp를 실행할 때마다 application scope의 값이 유지되어 증가한 모습이다. chrome에서 실행한 모습인데 edge에서 실행하면 어떨까?
edge에서 실행해도 여전히 같은 application이므로 값이 유지된다.
서버를 재시작하면 다음과 같이 어플리케이션이 종료되었다가 켜지기 때문에 값이 초기화된다.