Servlet으로 Session 사용하기
서블릿 HTTP 세션1
⚓️서론
서블릿은 세션 기능을위해 HttpSession
을 제공한다.
앞에서 세션을 직접 만들어서 사용했지만, 여기서는 HttpSession
을 사용하면 고생을 덜어준다.
직접 구현한 것보다 더 좋다.
HttpSession
서블릿에서 제공하는 HttpSession
는 앞서 해왔던 SessionManager
와 비슷한 방식으로 동작한다.
➡️SessionManager
- 세션 생성 : UUID값 생성 → SessionStore에 put → 쿠키 생성
- 세션 조회
- 세션 만료
@Component
public class SessionManager {
public static final String SESSION_COOKIE_NAME = "mySessionId";
private Map<String, Object> sessionStore = new ConcurrentHashMap<>();
/**
* 세션 생성
*/
public void createSession(Object value, HttpServletResponse response) {
//세션 id를 생성하고, 값을 세션에 저장
String sessionId = UUID.randomUUID().toString(); // UUID 만들기
sessionStore.put(sessionId, value);
//쿠키 생성
Cookie mySessionCookie = new Cookie(SESSION_COOKIE_NAME, sessionId); // Cookie(String name, String value)
response.addCookie(mySessionCookie); // response에 쿠키를 넣어준다.
}
/**
* 세션 조회
*/
public Object getSession(HttpServletRequest request) {
Cookie sessionCookie = findCookie(request, SESSION_COOKIE_NAME);
if (sessionCookie == null) {
return null;
}
return sessionStore.get(sessionCookie.getValue());
}
/**
* 세션 만료
*/
public void expire(HttpServletRequest request) {
Cookie sessionCookie = findCookie(request, SESSION_COOKIE_NAME);
if (sessionCookie != null) {
sessionStore.remove(sessionCookie.getValue());
}
}
public Cookie findCookie(HttpServletRequest request, String cookieName) {
if (request.getCookies() == null) {
return null;
}
return Arrays.stream(request.getCookies()) // 배열을 스트림으로 바꿔준다.
.filter(cookie -> cookie.getName().equals(cookieName)) // Loop를 돌리면서 쿠키가 같은지 확인
.findAny()
.orElse(null);
}
}
➡️위와 같은 방식 말고 서블릿에서 제공하는 방법으로 하게된다면?
SessionManager
가 아닌HttpSession
으로 세션 기능 구현
서블릿으로 세션을 생서성 쿠키가 생성되는데 쿠키의 이름은 JSESSIONID
이고, 값은 추정 불가능한 랜덤 값이다.
Cookie : JESSIONID = 추정불가한 랜덤값
- SessionConst : HttpSession에 데이터를 보관하고 조회할 때 , 같은 이름이 중복 되어 사용되므로 상수를 하나 정의했다.
public interface SessionConst {
String LOGIN_MEMBER = "loginMember";
}
- loginController
request.getSession(true)
- 세션이 있으면 기존 세션을 반환한다.
- 세션이 없으면 새로운 세션을 생성해서 반환한다.
request.getSession(false)
- 세션이 있으면 기존 세션을 반환한다.
- 세션이 없으면 새로운 세션을 생성하지 않는다. →
null
을 반환한다.
session.setAttribute(SessionConst.LOGIN_MEMBER, loginMember);
- 세션에 데이터를 보관하는 방법은
request.setAttribute(...)
와 비슷하다. 하나의 세션에 여러 값을 저장할 수 있음.
- 세션에 데이터를 보관하는 방법은
/**
* 로그인 세션 HttpSession으로 처리하기
* @param form
* @param bindingResult
* @param request
* @return
*/
@PostMapping("/login")
public String loginV3(@Valid @ModelAttribute LoginForm form, BindingResult bindingResult, HttpServletRequest request) {
if (bindingResult.hasErrors()) {
return "login/loginForm";
}
Member loginMember = loginService.login(form.getLoginId(), form.getPassword());
log.info("login? {}", loginMember);
if (loginMember == null) {
bindingResult.reject("loginFail", "아이디 또는 비밀번호가 맞지 않습니다.");
return "login/loginForm";
}
//로그인 성공 처리
//세션이 있으면 있는 세션 변환, 없으면 신규 세션 생성
HttpSession session = request.getSession(); // 세션을 생성하려면 -> true (defalut)
//세션에 로그인 회원 정보 보관
session.setAttribute(SessionConst.LOGIN_MEMBER, loginMember);
return "redirect:/";
}
- logout - 로그아웃
invalidate
는 세션과 그 안에 데이터를 지워준다.
/**
* 로그인 처리 - 세션으로 로그아웃 처리 (세션 만료)
*
* @param request
* @return
*/
@PostMapping("/logout")
public String logoutV2(HttpServletRequest request) {
HttpSession session = request.getSession(false);
if(session != null){
session.invalidate();
}
return "redirect:/";
}
- HomeController
request.getSession(false);
세션을 생성할 의도가 없기 떄문에false
@GetMapping("/")
public String homeLoginV3(HttpServletRequest request, Model model) {
//세션이 없으면 home
HttpSession session = request.getSession(false); //false 세션 안만들기 때문에
if (session == null) {
return "home";
}
Member loginMember = (Member) session.getAttribute(SessionConst.LOGIN_MEMBER);
//세션에 회원 데이터가 없으면 home화면으로 이동
if (loginMember == null) {
return "home";
}
//세션이 유지되면 로그인으로 이동
model.addAttribute("member", loginMember);
return "loginHome";
}
- 결과 - JSESSIONID