Spring/Spring MVC

Spring MVC - Interceptor

jddng 2022. 1. 3. 22:21
728x90
반응형

Interceptor

  • AOP를 적용한 Spring MVC의 요소
  • Interceptor는 요청이 발생하면 Controller의 해당 메서드를 호출하기 전, 후에 Interceptor하여
    다른 메서드를 호출할 수 있도록 가로 채는 개념이다.
  • 여러 메서드들이 코드가 중복 되는 부분이 있을 때 Interceptor를 이용하면 유용하다.
  • 로그인 여부 확인, 등급별 서비스, 사용 권한 확인 등에 쓰인다.

 

 Java로 설정하는 방법과 XML로 설정하는 방법이 있다.


 

방법 1 - Java

 

Interceptor 구현

 따로 Interceptor 패키지를 만들어줘서 관리하자.

 

TestInterceptor1.java         

public class TestInterceptor1 implements HandlerInterceptor{
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		System.out.println("TestInterceptor1 - prehandle ");
		return true;
	}
	
//	Controller의 메소드가 호출되고 난 후에 호출
	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		
		System.out.println("TestIntercepter1 - postHandle");
	}
	
//	View 처리까지 완료되면 호출
	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {

		System.out.println("TestIntercepter1 - afterCompletion");
	}
}
public class TestInterceptor1 implements HandlerInterceptor{
 - preHandle, postHandle, afterCompletion를 override 하기 위해 HandlerInterceptor를 상속받는다.
 - 필요한 메서드만 override하면 된다.

preHandle
 - Controller의 메서드가 호출되기 전 호출
 - false를 반환하면 코드의 흐름이 중단된다. Controller의 메서드로 가지도 않고, postHandle, afterCompletion,
또 다른 Intercepter들 모두 중단된다.

postHandle
 - Controller의 메서드가 호출된 후 호출

afterCompletion
 - View 처리까지 완료되고 응답 결과가 브라우저로 전달하기 전에 호출

 

 

ServletAppContext.java에 Interceptor 등록

ServletAppContext.java

....
public class ServletAppContext implements WebMvcConfigurer{
	
    .....
	
//	인터셉터를 등록한다.
	public void addInterceptors(InterceptorRegistry registry) {
		WebMvcConfigurer.super.addInterceptors(registry);
		
		TestInterceptor1 inter1 = new TestInterceptor1();
		TestInterceptor2 inter2 = new TestInterceptor2();
		TestInterceptor3 inter3 = new TestInterceptor3();
		TestInterceptor4 inter4 = new TestInterceptor4();
		TestInterceptor5 inter5 = new TestInterceptor5();
		
		InterceptorRegistration reg1 = registry.addInterceptor(inter1);
		InterceptorRegistration reg2 = registry.addInterceptor(inter2);
		InterceptorRegistration reg3 = registry.addInterceptor(inter3);
		InterceptorRegistration reg4 = registry.addInterceptor(inter4);
		InterceptorRegistration reg5 = registry.addInterceptor(inter5);
		
		reg1.addPathPatterns("/test1");
		reg2.addPathPatterns("/test1");
		reg3.addPathPatterns("/test2"); 
		// 둘다 적용 - 방법1
//		reg4.addPathPatterns("/test1");
//		reg4.addPathPatterns("/test2");
		// 방법2
		reg4.addPathPatterns("/test1", "/test2");
		
//		reg5.addPathPatterns("/sub1/test3", "/sub1/test4");
		reg5.addPathPatterns("/sub1/*");
		
//		설정된 경로중 제외할 경로
		reg5.excludePathPatterns("/sub1/test3");
		
		
	}
}
public void addInterceptors(InterceptorRegistry registry) {
        WebMvcConfigurer.super.addInterceptors(registry);
 - Interceptor 등록을 위해 addInterceptors 메서드를 override 해주면 된다.

TestInterceptor1 inter1 = new TestInterceptor1();
 - Interceptor 등록을 위해 위에서 작성한 TestInterceptor1 객체 생성

InterceptorRegistration reg1 = registry.addInterceptor(inter1);
 - Interceptor 등록

reg1.addPathPatterns("/test1");
 - 등록한 interceptor가 적용할 URI 설정

Interceptor를 적용할 URI 설정 방법 
 - addPathpatterns를 이용하여 여러 URI 설정
        reg4.addPathPatterns("/test1");
        reg4.addPathPatterns("/test2");
 - addPathPattorns를 이용하여 여러 URI 설정 방법2
        reg4.addPathPatterns("/test1", "/test2");
        reg4.addPathPatterns("/sub1/*");
 - excludePathPatterns()를 이용하여 설정된 특정 URI를 제외
        reg5.excludePathPatterns("/sub1/test3");

 결과 화면
/test1 요청 시

/test2 요청 시
/sub1/test3 요청 시
 실행된 Interceptor가 없다.

/sub1/test4 요청 시

 


 

방법 2 - XML

 

Interceptor 등록하는 방법만 다르므로 다른 부분은 제외하겠다.

 

Interceptor 구현

servlet-context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
			 ....>
			 					 
	<!-- 스캔한 패지키 내부의 클래스 중 Controller 어노테이션을 가지고 있는 클래스들을 Controller로 로딩하도록 한다 -->
	<annotation-driven/>
	
	<!-- 스캔할 bean들이 모여있는 패키지를 지정한다. -->
	<context:component-scan base-package="kr.co.softcampus.controller"/>
	
	<!-- Controller의 메서드에서 반환하는 문자열 앞 뒤에 붙힐 경로 정보를 셋팅한다. -->
	<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<beans:property name="prefix" value="/WEB-INF/views/"/>
		<beans:property name="suffix" value=".jsp"/>
	</beans:bean>
	
	<!-- 정적파일(이미지, 사운드, 동영상, JS, CSS 등등) 경로 셋팅 -->
	<resources mapping="/**" location="/resources/"/>
	
	<!-- Interceptor 들을 Bean으로 등록한다. -->
	<beans:bean class='kr.co.softcampus.interceptor.TestInterceptor1' id='inter1'/>
	
	<interceptors>
		<interceptor>
			<mapping path="/test1"/>
			<beans:ref bean='inter1'/>
		</interceptor>
		<interceptor>
			<mapping path="/test2"/>
			<beans:bean class='kr.co.softcampus.interceptor.TestInterceptor2'/>
		</interceptor>
		<interceptor>
			<mapping path="/test2"/>
			<beans:ref bean="inter1"/>
		</interceptor>
		<interceptor>
			<mapping path="/**"/>
			<exclude-mapping path="/*"/>
			<beans:bean class='kr.co.softcampus.interceptor.TestInterceptor3'/>
		</interceptor>
	</interceptors>
			 
</beans:beans>
<beans:bean class='kr.co.softcampus.interceptor.TestInterceptor1' id='inter1'/>
 - 여러 경로에 Interceptor가 필요한 경우 bean을 주입하고 필요할 때마다 가져온다.

<interceptor>     
      <mapping path="/test2"/>
      <beans:bean class='kr.co.softcampus.interceptor.TestInterceptor2'/>
</interceptor>
 - 한 경로에만 Interceptor가 필요한 경우 이 안에서만 사용하도록 bean을 주입할 수 있다.


 한 요청 주소에 대해 Interceptor 1개밖에 등록을 못하므로 불편함이 있다.

 

 

 

 

728x90
반응형