Spring MVC 세션, 인터셉터, 쿠키

김정훈·2024년 7월 15일

Spring

목록 보기
12/24

1. 세션

@SessionAttribute
세션값 조회 및 주입

@Slf4j
@Controller
@RequestMapping("/member")
@RequiredArgsConstructor
public class MemberController {
	/* 세션값을 위해 형변환을 해야한는 번거로움 발생
	@GetMapping("/login")
    public String login(@ModelAttribute RequestLogin form, HttpSession session) {
        Member member = (Member) session.getAttribute("member");
        if(member != null) {
            log.info(member.toString());
        }
        return "member/login";
    }
    */


    @GetMapping("/login")
    public String login(@ModelAttribute RequestLogin form, @SessionAttribute(name="member", required = false) Member member) {
        if(member != null) {
            log.info(member.toString());
        }
        return "member/login";
    }
}

@SessionAttributes

  • Model로 해당 이름으로 값을 속성으로 추가하면 세션에도 동일한 이름으로추가
  • 세션에 해당 이름의 값이 있으면 Model에 자동 추가
  • Magic Form : 여러 페이지의 양식 ex) 설문조사 페이지
  • SessionStatus
    • setComplete() : @SessionAttributes에 지정된 이름의 세션값을 완료 상태 플래그
  • HttpSession - removeAttribute("이름") : 에 지정된 이름의 세션값을 제거

Mageic form 설문조사 페이지 구성
SurveyController

@Controller
@RequestMapping("/survey")
@SessionAttributes("requestSurvey") //모델속성 RequestSurvey을 세션속성으로 유지함으로써 세션으로 데이터를 유지할수있다.
public class SurveyController {

    @ModelAttribute 
    public RequestSurvey requestSurvey() {
        return new RequestSurvey();
    }
    
    @GetMapping
    public String step1() { //첫번째 설문조사 페이지

        return "survey/step1";
    }

    @PostMapping//1번에서 2번으로 양식데이터를 넘김
    public String step2(RequestSurvey form) { //두번째 설문조사 페이지
        return "survey/step2";
    }

    @PostMapping//2번에서 3번으로 양식데이터를 넘김
    public String step3(RequestSurvey form) { //세번째 설문조사 페이지
        return "survey/step3";
    }
}

2. 인터셉터

1) HandlerInterceptor 인터페이스

특정 컨트롤러가 요청을 처리하기 전, 후, 그리고 완료된 이후에 추가적인 처리.

1. preHandle()

컨트롤러 호출 전에 호출되는 메소드이다. preHandle()의 반환타입은 boolean 이다. 만약 preHandle() 이 false 를 반환한다면, 다음 HandlerInterceptor 혹은 컨트롤러를 실행하지 않는다.

세션을 통해 로그인여부를 확인하고 여부에 따라 빈메서드를 통제

MemberOnlyInterceptor

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    log.info("유입");
    HttpSession session = request.getSession();
    if(session.getAttribute("member") != null) {//로그인 상태인경우
        return true; //컨트롤러 빈 메서드 실행
    }
    response.sendRedirect(request.getContextPath() + "/member/login"); ////로그인 상태가 아닐경우 : 로그인페이지로 페이지 이동
    return false; //로그인 상태가 아닐경우 : 컨트롤러 빈 메서드 실행 X 
}

2. postHandle()

컨트롤러가 정상적으로 실행된 이후에 실행되는 메소드이다. 컨트롤러에서 예외가 발생한다면, postHandle() 메소드는 실행되지 않는다.

ModelAndView을 통해 속성을 추가하고, 뷰페이지에서 접근이 가능하다.

MemberOnlyInterceptor

@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    modelAndView.addObject("message", "postHandle!"); //속성을 추가, 뷰페이지에서 접근이 가능.
    log.info("postHandle");
}

main.jsp

<%@ page contentType="text/html; charset=UTF-8" %>
<h1>마이페이지!</h1>
<h2>${message}</h2>

3. afterCompletion()

뷰가 클라이언트에 응답을 전송한 뒤에 실행된다. 컨트롤러 실행과정에서 예외가 발생한 경우 해당 예외가 afterCompletion() 메소드의 4번째 파라미터로 전달되어, 로그로 남기는 등 후처리를 위해 사용될 수 있다.

boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception;
void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception;

2) addInterceptors(InterceptorRegistry registry)

WebMvcConfigurer 인터페이스
인터셉터를 설정할수 있음. 설정없이 인터셉터만 등록할경우 모든 컨트롤러에 적용됨.

InterceptorConfig

@Configuration
@RequiredArgsConstructor
public class InterceptorConfig implements WebMvcConfigurer {

    private final MemberOnlyInterceptor memberOnlyInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(memberOnlyInterceptor) //인터셉터 등록
                .addPathPatterns("/mypage/**"); //정적경로등록(해당경로에만 적용)
    }
}

3) Ant 경로 패턴

  • * : 0개 또는 그 이상의 글자
  • ** 0개 또는 그 이상의 폴더 경로
  • ? : 1개 글자

3. 쿠키

@CookieValue
@CookieValue(name="savedEmail", required = false) String savedEamil
LoginService

@Service
@RequiredArgsConstructor
public class LoginService {

    private final MemberMapper mapper;
    private final HttpSession session;
    private final HttpServletResponse response;

    public void process(String email) {
        /**
         * 1.email로 회원조회
         * 2. 세션에 회원 정보 유지
         */
        Member member = mapper.get(email);
        if(email==null){
            return;
        }
        session.setAttribute("member", member);
    }

    public void process(RequestLogin form) {
        process(form.getEmail()); //로그인처리

        /* 이메일 기억하기 처리 */
        Cookie cookie = new Cookie("savedEmail", form.getEmail());
        if(form.isSaveEmail()){ //쿠키등록
            cookie.setMaxAge(60 * 60 * 24 * 7); //7일간 쿠키유지
        }else{
            cookie.setMaxAge(0); //쿠키제거
        }

        response.addCookie(cookie); //해당 쿠키가 삭제 or 등록
    }
}

MemberController

@Slf4j
@Controller
@RequestMapping("/member")
@RequiredArgsConstructor
public class MemberController {

    @GetMapping("/login")
    public String login(@ModelAttribute RequestLogin form, @CookieValue(name="savedEmail", required = false) String savedEamil, @SessionAttribute(name="member", required = false) Member member) {
        if(member != null) {
            log.info(member.toString());
        }

        if(savedEamil != null){
            form.setSaveEmail(true);
            form.setEmail(savedEamil);
        }
        return "member/login";
    }
}
profile
안녕하세요!

0개의 댓글