[Servlet
] --HTML코드 출력 문제--> JSP
--스파게티 코드 문제--> JSP MVC
-> Spring MVC
-> SpringBoot
WAS에서는 요청에 의해 실행된 Servlet 객체는 실행하며 응답한 뒤에 바로 소멸한다. 그래서 Servlet끼리 정보를 주고 받는 것이 불가능하다.
조각나있는 서버 프로그램인 Servlet들이 종료된 후에도 유지할 수 있는, 공유할 수 있는 데이터가 필요하다면 상태 유지가 필요하다. 상태 유지를 위해서 Servlet은 다음과 같은 객체를 이용한다.
- Application 객체
- Session 객체
- Cookie 객체
Application객체, Servlet Context라고도 부르며 Servlet끼리 정보를 주고 받게 해주는 저장소로서 이용할 수 있다.
Java 코드 내에서는 ServletContext객체로서 존재하며 request.getServletContext()
로 호출 가능하다.
(이전 글 참고)
public String getInitParameter(String name) | 파라미터 name에 대한 파라미터 값을 반환한다. |
public Enumeration getInitParameterNames() | 컨텍스트의 초기화 파라미터의 name값들을 String객체의 Enumeration으로 반환한다. |
public void setAttribute(String name,Object object) | 어플리케이션범위에 주어진 객체를 설정한다. |
public Object getAttribute(String name) | 명시된 name에 대한 object를 반환한다.. |
public void removeAttribute(String name) | ServletContext부터 주어진 name에 대한 속성을 제거한다. |
Session객체 또한 Application과 개념은 비슷하다.
(코드또한ServletContext객체 -> HttpSession객체
교환하면 사용 가능)
다만, Application객체는 Applicaion 범주 안에서 / Session객체는 Session 범주 안에서 사용이 가능하다.Application 범주 : 전체 Servlet 범위 전역 Session 범주 : 사용자 (현재 접속자, 프로세스) 범위
따라서 Session객체는 접속하는 브라우저가 달라지면 다른 Session이기에(다른 프로세스이기에) Context 공유가 불가능하다.
Chrome 다른 창이지만 같은 SID(Session ID)를 가지고 있음을 확인할 수 있다. 이건 MicroSoft Edge로 접속했는데 SID가 다르다.참고할 점은
- 처음 서버에 접속할 때에는 SID가 따로 없다.
- 접속 후에는 서버에서 해당 요청에 대해 SID를 부여하게 되고 Respond한다.
- 서버에 요청을 보낼 때 부여 받은 SID를 같이 보내면 서버는 SID에 해당하는 Session 저장소를 사용하게 한다.
Calc_session.java
@WebServlet("/calc")
public class Calc_session extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
HttpSession session = request.getSession();
String _value = request.getParameter("value");
String op = request.getParameter("op");
int result = 0;
int value = (_value!= null && !_value.equals(""))
? Integer.parseInt(_value) : 0;
if(op.equals("=")) {
int sum = (int) session.getAttribute("value");
String prevOp = (String) session.getAttribute("op");
if (prevOp.equals("+"))
result = sum + value;
else
result = sum - value;
response.getWriter().printf("Result is %d",result);
} else {
session.setAttribute("value", value);
session.setAttribute("op", op);
}
}
}
String getId() | 세션의 ID 출력 |
void setAttributes(String name, Object value) | name으로 Object객체 매핑 |
Object getAttribute(String name) | name으로 매핑된 Object객체 반환 |
void invalidate | 세션에서 사용되는 객체들을 바로 해제 |
void getMaxInactiveInterval() | 세션 타임아웃을 초 단위로 출력 (defaut 30분) |
void setMaxInactiveInterval(int interval) | 세션 타임아웃을 interval로 설정 (defaut 30분) |
boolean isNew() | 세션이 새로 생성됐는지 확인 |
long getCreateionTime() | 세션이 시작된 시간을 반환, 1970.01.01을 시작으로 하는 ms |
long getLastAccessedTime() | 마지막 요청 시간, 1970.01.01을 시작으로 하는 ms |
Cookie 객체 또한 상태 유지를 위해 사용될 수 있는 저장소이다.
Application 객체, Session 객체와는 다르게 브라우저에 저장되며, Client에서 보내는Request
와 Client로 보내는Respond
의 Header정보에 담아서 주고 받는다.
Calc_cookie.java
@WebServlet("/calc")
public class Calc_cookie extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Cookie[] cookies = request.getCookies();
response.setContentType("text/html; charset=UTF-8");
response.setCharacterEncoding("UTF-8");
String _value = request.getParameter("value");
String op = request.getParameter("op");
int result = 0;
int value = (_value!= null && !_value.equals(""))
? Integer.parseInt(_value) : 0;
if(op.equals("=")) {
int sum = 0;
String prevOp = "";
for(Cookie c : cookies) {
if (c.getName().equals("value"))
sum = Integer.parseInt(c.getValue());
if (c.getName().equals("op"))
prevOp = c.getValue();
}
if (prevOp.equals("+"))
result = sum + value;
else
result = sum - value;
response.getWriter().printf("Result is %d",result);
} else {
Cookie valueCookie = new Cookie("value", String.valueOf(value));
Cookie opCookie = new Cookie("op", op);
response.addCookie(valueCookie);
response.addCookie(opCookie);
}
}
}
실제로 요청 헤더에 Cookie가 담겨서 전송되고, Cookie안에 입력했던 value와 op가 그대로 전송됨을 확인할 수 있다.
실제로 Chrome 브라우저에 Cookie가 저장됐고
입력했던 정보가 저장됐다.
그렇다면 Cookie객체는 Application객체와 Session객체처럼 어느 범위에서 사용이 가능할까?? 또한 수명은 어떻게 될까??
- Cookie객체의 경로 설정
- Cookie객체의 maxAge 설정
Chrome에 저장된 Cookie를 자세히 보면
모든 경로(/
)에서 이 Cookie를 사용할 수 있게 돼있다.
Cookie의 경로를 설정해주지 않으면, 모든 Servlet에서 Cookie호출이 가능해지게 되고, 이는 Cookie에 대한 관리도 어려울 뿐더러 원하지 않았던 Cookie로 정보를 주고 받게될 수도 있다.
Cookie를 생성할 때
valueCookie.setPath("/calc");
opCookie.setPath("/calc";
경로 설정을 /calc
로 해주면
Cookie 경로가 /calc
로 바뀐 것을 확인할 수 있다. (이제 Calc로 매핑된 Servlet에서만 호출이 가능하다.)
Cookie는 현재 Session이 만료될 때 같이 삭제된다. 하지만 수명을 설정해줄 수 있다.
valueCookie.setMaxAge(60*60);
opCookie.setMaxAge(60*60);
이렇게 수명 설정이 되고나면 해당 Cookie를 File로 저장하게 된다.
C:\Users\s_rudwhd515\AppData\Local\Google\Chrome\User Data\Default\Cookies
파일로 존재한다.
void setMaxAge(int expiry) | 쿠키의 유효 시간 설정 (0으로 할 경우 무효화) |
int getMaxAge() | 쿠키의 유효 시간 반환 (default 세션 만료시 삭제) |
void setPath(String uri) | 쿠키 사용의 유효 디렉토리 설정 |
String getPath() | 설정된 유효 디렉토리 반환 |
void setValue(String newValue) | 쿠키의 값을 수정 |
String Cookie.getName() | 쿠키의 이름 반환 |
void setVersion(int v) | 쿠키의 버전 정보 설정 |
int getVersion() | 쿠키의 버전 정보 반환 |
void setComment(String purpose) | 쿠키에 코멘트 설정 |
String getComment() | 쿠키의 코멘트 반환 |
Servlet이 종료된 뒤에는 빈 페이지만 남게 된다. Servlet 코드 마지막에 Redirection처리를 해주면,
Servlet이 종료되고 처리된 페이지로 경로를 전환(Redirection)하게 된다.
response.sendRedirect("calc.html");
Servlet코드 마지막에 추가해주면 Servlet 로직을 마치고 다시 calc.html로 페이지를 전환해주게 된다.