✏️ Rq 계층
- Http Servlet 의 Request 와 Response 관련 로직을 별도의 Class 인 Rq 로 분리했다.
package com.ll.basic1.cookie;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.web.context.annotation.RequestScope;
@Component
@RequestScope
@RequiredArgsConstructor
public class Rq {
private final HttpServletRequest req;
private final HttpServletResponse resp;
📍 Session 생성
- Session 이름과 value 를 매개변수로 받아 Session 을 생성한다.
- 지금은 공부하는 단계라 Session 이름은 “
loginedMemberId
" 로 통일해서 작업할 예정이다.
- value 는 클라이언트의 id 를 사용한다.
- ⚠️ id 는 int 타입으로 사용할 수 없다.
- 간단한 실습일줄 알고 Entity 에서 int 로 선언했다 논리에러가 발생해 한참 고생했다..
- 아무리 간단한 프로젝트여도 long 으로 선언해주자..
public void setSession(String name, long value) {
HttpSession session = req.getSession();
session.setAttribute(name, value);
}
📍 Session 조회
- 세션의 이름과 클라이언트의 id 값을 매개변수로 받는다.
- V1, V2 버전이 있는데 V1 은 id 를 반환하고, V2 는 String 타입을 반환한다.
- Controller 에서는 long 값에 0 을 넣어 전달하고,
Session 을 찾지 못할경우 0 을 그대로 반환해 Session 이 없는 클라이언트를 식별하고,
Session 이 있다면 세션 값을 반환해 id 값으로 클라이언트를 식별하는 방식이다.
public long getSessionAsLong(String name, long defaultValue) {
try {
long value = (long) req.getSession().getAttribute(name);
return value;
} catch (Exception e) {
return defaultValue;
}
}
private String getSessionAsStr(String name, String defaultValue) {
try {
String value = (String) req.getSession().getAttribute(name);
if (value == null) return defaultValue;
return value;
} catch (Exception e) {
return defaultValue;
}
}
📍 Session 간편 확인
- getSession 의 반환 값을 통해 Session 을 갖고있는 클라이언트인지를 확인하는 로직
public boolean isLogined() {
long loginedMemberId = getSessionAsLong("loginedMemberId", 0);
return loginedMemberId > 0;
}
📍 Session 삭제
- 세션 이름을 매개변수로 받아 세션을 찾지 못하면 false ,
찾는다면 삭제후 ture 를 반환하는 로직이다.
public boolean removeSession(String name) {
HttpSession session = req.getSession();
if (session.getAttribute(name) == null)
return false;
session.removeAttribute(name);
return true;
}
✏️ Controller 계층
- 지난시간에 만든 Cookie 로 구현했던 로직을 Session 으로 변경하면 된다.
📍 Log in - Session 생성
- 매개변수의 @RequestParam 을 생략했다.
- Service 의 login 기능이 완료된뒤 참조했던 쿠키생성 대신 세션 생성을 참조한다.
- 처음 로직을 만들 때 쿠키와 세션 작업을 할 줄 몰랐고,
SSR 도 할 지 몰랐기 때문에 Service 로직의 반환값이 DTO 로 되어있다.
- 시간관계상 리팩토링을 하지못해 매끄럽지 못했다.
@PostMapping("/member/login")
public String doLogin(String username, int password, Model model) {
MemberDto dto = service.login(username, password);
Member member = dto.getMember();
rq.setSession("loginedMemberId", member.getId());
model.addAttribute("member", member);
return "usr/member/login";
}
📍 개인정보 확인하기 - Session 조회
- 세션의 존재여부를 확인하고, 없다면 “F-1” 을 반환한다.
- 있다면 Service 로 회원정보를 조회해 반환한다.
@GetMapping("/member/me")
@ResponseBody
public MemberDto showMe() {
long loginedMemberId = rq.getSessionAsLong("loginedMemberId", 0);
boolean isLogined = loginedMemberId > 0;
if (!isLogined)
return new MemberDto("F-1", "로그인후 이용해 주세요.");
Member member = service.findOne(loginedMemberId);
return new MemberDto("S-1", "당신의 username(은)는 " + member.getName() +" 입니다.");
}
📍Log out - Session 삭제
- 세션이 없다면 “S-2” 있다면 종료후 “S-1” 을 반환
@GetMapping("/member/logout")
@ResponseBody
public MemberDto logout() {
boolean result = rq.removeSession("loginedMemberId");
if (!result)
return new MemberDto("S-2", "이미 로그아웃 상태입니다.");
else {
return new MemberDto("S-1", "로그아웃 되었습니다.");
}
}