레알윙 2020. 9. 6. 16:18
반응형

HandlerInterceptor

  • 핸들러 맵핑에 설정할 수 있는 인터셉터
  • 핸들러를 실행하기 전, 후(아직 랜더링 전) 그리고 완료(랜더링까지 끝난 이후) 시점에 부가 작업을 하고 싶은 경우에 사용할 수 있다.
  • 여러 핸들러에서 반복적으로 사용하는 코드를 줄이고 싶을 때 사용할 수 있다.
    • 로깅, 인증 체크, Locale 변경 등...

 

 

boolean preHandle(request, response, handler)

  • 핸들러 실행하기 전에 호출 됨
  • “핸들러"에 대한 정보를 사용할 수 있기 때문에 서블릿 필터에 비해 보다 세밀한 로직을 구현할 수 있다.
  • 리턴값으로 계속 다음 인터셉터 또는 핸들러로 요청,응답을 전달할지(true) 응답 처리가 이곳에서 끝났는지(false) 알린다.

 

 

void postHandle(request, response, modelAndView)

  • 핸들러 실행이 끝나고 아직 뷰를 랜더링 하기 이전에 호출 됨
  • “뷰"에 전달할 추가적이거나 여러 핸들러에 공통적인 모델 정보를 담는데 사용할 수도 있다.
  • 이 메소드는 인터셉터 역순으로 호출된다.
  • 비동기적인 요청 처리 시에는 호출되지 않는다.

 

 

void afterCompletion(request, response, handler, ex)

  • 요청 처리가 완전히 끝난 뒤(뷰 랜더링 끝난 뒤)에 호출 됨
  • preHandler에서 true를 리턴한 경우에만 호출 됨
  • 이 메소드는 인터셉터 역순으로 호출된다.
  • 비동기적인 요청 처리 시에는 호출되지 않는다.

 

 

vs 서블릿 필터

  • 서블릿 보다 구체적인 처리가 가능하다.
  • 서블릿은 보다 일반적인 용도의 기능을 구현하는데 사용하는게 좋다.

 

 

예제

핸들러 구현

@RestController
public class SampleController {

	// preHandle
	// 요청처리
	// postHandler
	// 뷰 랜더링
	// afterCompletion
	
	@GetMapping("/hello")
	public String hello() {
		return "hello ";
	}
}

 

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

public class AnotherInterceptor implements HandlerInterceptor {
	
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		System.out.println("preHandle 2");
		return true;
	}

	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		System.out.println("postHandle 2");
	}

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		System.out.println("afterCompletion 2");
	}
}

 

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

public class GreetingInterceptor implements HandlerInterceptor {
	
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		System.out.println("preHandle 1");
		return true;
	}

	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		System.out.println("postHandle 1");
	}

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		System.out.println("afterCompletion 1");
	}
}

 

핸들러 등록

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {
	
	@Override
	public void addInterceptors(InterceptorRegistry registry) {
		// add 한 순서대로 적용이된다.
		registry.addInterceptor(new GreetingInterceptor()).order(0);
		registry.addInterceptor(new AnotherInterceptor());
		
		/*
		 * 아래와같이 순서와 path를 지정할 수 있다.
		 */
//		registry.addInterceptor(new GreetingInterceptor()).order(0);
//		registry.addInterceptor(new AnotherInterceptor()).addPathPatterns("/jinseok").order(-1);
	}
}

 

테스트

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;

import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;

@RunWith(SpringRunner.class)
@WebMvcTest
public class SampleControllerTest {

	@Autowired
	MockMvc mockMvc;

	@Test
	public void hello() throws Exception {
		this.mockMvc.perform(get("/hello"))
			.andDo(print())
			.andExpect( content().string("hello"));
	}
}

 

 

참고

반응형