본문으로 바로가기

인터셉터는 중간에서 가로챈다는 의미를 가진다. 스프링에서도 말 그대로 중간에 요청을 가로채서 어떠한 일을 하는 것을 말한다. 인터셉터의 정식 명칭은 핸들러 인터셉터(Handler Interceptor)이다. 클라이언트의 요청이 컨트롤러에 가기 전에 가로채고, 응답이 클라이언트에게 가기전에 가로챈다. 즉, 인터셉터는 DispatcherServlet이 컨트롤러를 요청하기 전,후에 요청과 응답을 가로채서 가공할 수 있도록 해준다.


예를 들어 로그인 기능이 있을 때, 로그인을 한 사람만 보이는 페이지가 있고, 로그인 한 사람만 글을 작성할 수 있다고 하자. 그러면 페이지 컨트롤러에서도 로그인 확인 로직이 들어가고, 글 작성 컨트롤러에서도 로그인 확인 로직이 들어가야 한다. 인터셉터를 사용하면 컨트롤러에 로직이 로그인 확인 로직이 없어도 컨트롤러에 들어가기전에 인터셉터에서 로그인 확인을 하고 컨트롤러로 보낸다. 즉, 하나의 인터셉터로 프로젝트 내의 모든 요청에 로그인 여부를 확인할 수 있다. 


인터셉터를 만들려면 HandlerInterceptorAdaptor 클래스를 상속받아야 한다. HandlerInterceptorAdaptor 클래스를 상속받으면 사용할 수 있는 3가지의 메서드들이 있다. perHandle(), postHandle(), afterHandel()이 있다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class Intercepter extends HandlerInterceptorAdapter{
 
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        // TODO Auto-generated method stub
        return super.preHandle(request, response, handler);
    }
 
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
        // TODO Auto-generated method stub
        super.postHandle(request, response, handler, modelAndView);
    }
 
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        // TODO Auto-generated method stub
        super.afterCompletion(request, response, handler, ex);
    }
 
}
cs

- 4행 : 전처리기는 클라이언트에서 컨트롤러로 요청할 때 가로채는 것이다. 쉽게 말해 컨트롤러가 호출되기 전에 실행되는 메서드이다.

- 11행 : 후처리기는 컨트롤러에서 클라이언트로 요청할 때 가로채는 것이다. 쉽게 말해 컨트롤러가 호출되고 난 후에 실행되는 메서드이다.

- 18행 : 컨트롤러의 처리가 끝나고 화면처리까지 모두 끝나면 실행되는 메서드이다.



지금 하는 설정은 하나의 요청에 대한 컨트롤러 처리의 시작과 끝을 표시해 줄 것이다. 시작해보자.


1. src/main/java에 tody.lovely.common 패키지 생성 - interceptor 패키지 생성

레벨1, 레벨2 패키지명은 알아서 해주면 된다. common패키지와 interceptor패키지를 만들어 주면 된다.


2. CommonInterceptor.java 생성


1
2
3
4
5
6
7
package tody.lovely.common.interceptor;
 
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
 
public class CommonInterceptor extends HandlerInterceptorAdapter{
 
}
cs

HandlerInterceptorAdaptor 클래스를 상속했는데 @Override가 뜨지 않는다!!! 뭐야 뭐야!!


2-1. Alt+Shift+S 누르면 Override/Implements Methods... 클릭


2-2. preHandle(), postHandle() 체크 - OK


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package tody.lovely.common.interceptor;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
 
public class CommonInterceptor extends HandlerInterceptorAdapter{
 
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        // TODO Auto-generated method stub
        return super.preHandle(request, response, handler);
    }
 
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
        // TODO Auto-generated method stub
        super.postHandle(request, response, handler, modelAndView);
    }
     
}
cs

그럼 이렇게 오버라이드 메소드들이 보일 것이다!



3. CommonInterceptor.java 수정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package tody.lovely.common.interceptor; 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
 
public class CommonInterceptor extends HandlerInterceptorAdapter{
     
    protected Log log = LogFactory.getLog(CommonInterceptor.class);
 
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        if (log.isDebugEnabled()) {
            log.debug("===================       START       ===================");
            log.debug(" Request URI \t:  " + request.getRequestURI());
        }
        return super.preHandle(request, response, handler);
    }
 
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
        if (log.isDebugEnabled()) {
            log.debug("===================        END        ===================\n");
        }
    }
     
}
cs

- 18행 : 전처리기에서 컨트롤러가 시작됨을 알리는 START 로그를 출력한다.

- 19행 : 현재 호출되는 URL을 알려준다.

- 28행 : 후처리기에서 컨트롤러가 끝남을 알리는 END 로그를 출력한다.



4. interceptor-servlet.xml 생성

interceptor-servlet.xml을 따로 만들지 않고 action-servlet.xml에 추가해도 상관없다. 다만 Interceptor가 DispatcherSevlet과 같은 위치에 등록되어야 된다는 것만 유의하자. action-servlet.xml에 추가하는 것도 같은 위치에 등록한 것이고, action-servlet.xml과 같은 폴더인 appServlet에 interceptor-servlet.xml을 만들어서 추가하는 것도 같은 위치에 등록한 것이다. web.xml에 가면 알 수 있을 것이다.


interceptor-sevlet.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    
    <interceptors>
       <interceptor>
           <mapping path="/**"/>
           <beans:bean id="commonInterceptor" class="tody.lovely.common.interceptor.CommonInterceptor"/>
       </interceptor>
    </interceptors>
     
    <beans:bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/>
      
    <beans:bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
      <beans:property name="order" value="0"/>
    </beans:bean>
     
    <beans:bean id="jsonView" class="org.springframework.web.servlet.view.json.MappingJacksonJsonView"/>
       
</beans:beans>
cs

- 12행 : 예외 URL(exclude-mapping)을 제외한 모든 URL에 적용하고 싶을때 /** 를 쓰면 된다. 특정 URL을 쓰고싶으면 URL을 적으면 된다. 지금 우리가 사용할 것은 모든 Logger에 적용되야 하기에 /** 를 썼다.

- 20행 : ViewResolver의 순서를 정해주는 것이다. 우선 순위는 작은 값부터이다. 인터셉터가 가장 먼저 보여야 하기 때문에 0으로 설정했다.


4-1. action-servlet.xml 수정

1
2
3
4
5
6
7
    <beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <beans:property name="prefix" value="/WEB-INF/views/" />
        <beans:property name="suffix" value=".jsp" />
        <beans:property name="order" value="1"/>
    </beans:bean>
    
    <context:component-scan base-package="tody" />
cs

- 4행 : interceptor-servlet.xml에서 프로퍼티의 순서를 0으로 했기에 여기선 그 다음 1로 해준다.

- 7행 : 최상위 패키지명으로 바꿔주자. 나는 tody.lovely로 레벨1이 tody여서 tody로 했다.



5. src/main/java에 tody.lovely.common 패키지 - controller 패키지 생성


6. TestController.java 생성


TestController.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package tody.lovely.common.controller;
 
import org.apache.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
 
@Controller
public class TestController {
     
    Logger log = Logger.getLogger(this.getClass());
     
    @RequestMapping(value="/interceptorTest")
    public ModelAndView interceptorTest() throws Exception{
         
        ModelAndView mv = new ModelAndView("");
        log.debug("인터셉터 테스트입니다!");
         
        return mv;
    }
     
}
cs

- 9행 : 컨트롤러가 실행되고 log4j가 동작하는 지 확인하려 한다.



7. pom.xml에 jsonView 추가

1
2
3
4
5
6
7
8
9
10
11
12
13
<!-- MappingJacksonJsonView -->
<dependency>
    <groupid>org.codehaus.jackson</groupid>
        <artifactid>jackson-mapper-asl</artifactid>
    <version>1.9.13</version>
</dependency>
 
<dependency>
    <groupid>org.codehaus.jackson</groupid>
        <artifactid>jackson-core-asl</artifactid>
    <version>1.9.13</version>
</dependency>
<!--  -->
cs

interceptor-servlet.xml에 jsonView를 bean등록했다.



8. 서버실행 - 주소창에 /interceptorTest 입력

404 에러가 뜨는 게 정상이다. 왜냐면 view 부분에 jsp를 주지 않았기 때문!


콘솔창을 보자. 

START와 END 그리고 인터셉터 테스트입니다! 가 뜨면 인터셉터 설정이 끝난 것이다. 어떤 URL이 요청되었고 요청한 URL의 컨트롤러 정보, 그리고 컨트롤러의 시작과 끝을 콘솔창에서 쉽게 확인할 수 있게 되었다. 안해도 될 거 같지만, 한번 해 놓으면 정말 편하다.


******* 혹시 여기서 아래와 같은 에러가 뜬다면 http://to-dy.tistory.com/22?category=700248 여기 참고!!

org.springframework.beans.factory.BeanDefinitionStoreException: Failed to read candidate component class: URL [jar:file:/C:/Program%20Files/Java/jre1.8.0_161/lib/ext/jfxrt.jar!/com/sun/glass/ui/Accessible.class]; nested exception is java.lang.ArrayIndexOutOfBoundsException: 3805021



에고 에러때문에 고생 좀 했다ㅠㅠ


댓글을 달아 주세요

  1. hoho 2019.02.17 22:41

    3번 CommonInterceptor.java 수정에서 log 객체 접근이 안 되는데 이거 어떻게 해결해야 할까요? ㅠㅠ
    설정에서 제가 뭔가 건너뛰어서 log 객체에 접근이 안 되는 걸까요? ㅠㅠㅠ
    --> common-logging.jar 파일 아파치에서 다운로드해서 넣으니까 되네요!

  2. ydh5026 2019.02.28 10:44

    log 객체 접근이 안되요
    hoho 님처럼 아파치에서 common-logging.jar 다운받아서 넣어봐도 log 접근이 안되네요

  3. 렝켄 2019.03.15 11:49

    commoninterceptor.java에서 log.isDebugEnabled()가 실행이 안되는 분들은

    log4j.xml에서
    <logger name="패키지이름" additivity="false">
    <level value="debug" />
    <appender-ref ref="console"/>
    </logger>
    에다가 패키지이름을 적어주니 나오네용

  4. BlogIcon 쥬니준 2019.04.09 20:06 신고

    20:06:29.477 [http-nio-8090-exec-2] DEBUG o.s.web.servlet.DispatcherServlet - DispatcherServlet with name 'appServlet' processing GET request for [/interceptorTest]
    20:06:29.477 [http-nio-8090-exec-2] DEBUG o.s.w.s.m.m.a.RequestMappingHandlerMapping - Looking up handler method for path /interceptorTest
    20:06:29.477 [http-nio-8090-exec-2] DEBUG o.s.w.s.m.m.a.RequestMappingHandlerMapping - Returning handler method [public org.springframework.web.servlet.ModelAndView com.popo.controller.TestController.interceptorTest() throws java.lang.Exception]
    20:06:29.477 [http-nio-8090-exec-2] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'testController'
    20:06:29.477 [http-nio-8090-exec-2] DEBUG o.s.web.servlet.DispatcherServlet - Last-Modified value for [/interceptorTest] is: -1
    20:06:29.477 [http-nio-8090-exec-2] DEBUG c.popo.interceptor.CommonInterceptor - ================== START ==================
    20:06:29.477 [http-nio-8090-exec-2] DEBUG c.popo.interceptor.CommonInterceptor - Request URI : /interceptorTest
    20:06:29.477 [http-nio-8090-exec-2] DEBUG com.popo.controller.TestController - 인터셉터 테스트 입니다.
    20:06:29.477 [http-nio-8090-exec-2] DEBUG c.popo.interceptor.CommonInterceptor - ================== END ==================
    20:06:29.477 [http-nio-8090-exec-2] DEBUG o.s.w.s.view.BeanNameViewResolver - No matching bean found for view name 'interceptorTest'
    20:06:29.477 [http-nio-8090-exec-2] DEBUG o.s.web.servlet.DispatcherServlet - Rendering view [org.springframework.web.servlet.view.JstlView: name 'interceptorTest'; URL [/WEB-INF/views/interceptorTest.jsp]] in DispatcherServlet with name 'appServlet'
    20:06:29.477 [http-nio-8090-exec-2] DEBUG o.s.web.servlet.view.JstlView - Forwarding to resource [/WEB-INF/views/interceptorTest.jsp] in InternalResourceView 'interceptorTest'
    20:06:29.479 [http-nio-8090-exec-2] DEBUG o.s.web.servlet.DispatcherServlet - Successfully completed request


    이렇게 뜨는데 혹시 이건 정상인가요...?

    • BlogIcon #에게 2019.04.09 20:12 신고

      네! 에러도 안떴고 인터셉터 디버그 부분이 있네요! 정상작동입니당! log4j 에서 3rdparty loggers 부분을 지우면 저처럼 인터셉터 부분만 보일거에요!

  5. 5 2019.04.20 15:28

    WARN : org.springframework.web.servlet.PageNotFound - No mapping found for HTTP request with URI [/interceptorTest] in DispatcherServlet with name 'appServlet'

    이건무슨문제일까요..

  6. OJ 2019.05.20 23:20

    상세한 설명 감사드립니다. 질문이 있습니다!
    hoho님과 ydh5026님 처럼 clean 시켜보고 maven update도 했지만 import가 안되서 common-logging.jar, org.apache.log4j.Logger.jar 파일을 다운받아서 maven - lib 폴더에 저장했는데 똑같은 현상이 일어나서 build path에 add External JARs로 추가 하니 import 시킬수 있었습니다. 이렇게 build path를 이용해서 추가하는게 맞는건가요?

    • BlogIcon #에게 2019.05.21 08:32 신고

      네 추가된거면 상관없습니당! 근데 혹시나 해서 찾아보니 절대경로로 저장되기 때문에 다른 컴퓨터에 셋팅할때 문제가 있을 수도 있다고 하네요 https://emflant.tistory.com/m/129 이 블로그 한번 참고해주세용

    • OJ 2019.05.21 14:00

      와우..감사합니다. 절대경로 상대경로 차이가 있었네요.

  7. 2019.05.27 11:32

    비밀댓글입니다

  8. 코머 2019.05.27 13:46

    선생님 블로그 항상 좋은정보 잘보고있습니다.
    프로젝트 세팅을 처음부터 다시해보려고 새로만드는데 항상
    윗분들처럼 Log 클래스? 가 없어서 이클립스에서 수정하라는대로
    선언을 protected Logger log = LoggerFactory.getLogger(CommonInterceptor.class); 이렇게하고
    import를 아래 2줄을 추가하였는데 이렇게 해도되는건가요? 아니면 common-logging.jar를 아파치해서 다운로드 따로해야되나요??
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;

  9. darre 2019.06.23 22:13

    로그가 아예 안뜹니다..

  10. 2019.07.01 16:28

    비밀댓글입니다

    • BlogIcon #에게 2019.07.01 17:52 신고

      6번 컨트롤러 만드셨나요?

    • 제발.. 2019.07.02 09:20

      네 6번 컨트롤러도 그대로따라했습니다ㅠㅠ 버전차이인지 log가 안돼서 그 것 변경하였는데 혹시 그 문제일까요?? 도와주세요.. 여태 해결 못했습니다ㅠ

    • BlogIcon #에게 2019.07.02 09:44 신고

      음 저건 경로를 못찾는 거 같아요! https://to-dy.tistory.com/m/15 이 글의 마지막 6번보시고.. 다시 한번 해보시겠어요? 아니면 testController에 @controller 설정을 안했거나, 해당 글의 4-1에 back-package 설정을 잘 못 했을 수도 있어요!

    • 2019.07.02 10:31

      비밀댓글입니다

    • BlogIcon #에게 2019.07.02 10:34 신고

      이걸 이용해서 콘솔로그에 데이터가 찍히는 걸 확인하는 용도라서ㅠㅠ 콘솔에 데이터 찍히는 게 필요없으시면 안해도 됩니당.. https://github.com/todyDev/spring-sign-up-and-in/tree/master/01%20spring%20project 여기 깃허브 보시고 비교해보시겠어요???

  11. Practicing 2019.09.23 18:09

    안녕하세요. 올려주신 강의보고 따라서 진행 중인데
    404오류가 뜨면서 페이지는 안뜨긴하는데...설정한 로그도 출력이 안되네요.
    인터셉터에서 문제인건지 아니면 debugenable에서 문제인건지 몰라서 디버깅을 돌렸는데
    아예 오버라이딩한 함수에 들어오질 않습니다.....(인터셉터가 안되는거 같아요..)
    이럴 경우 어디를 보고 수정해야할지 알 수 있을까요?
    이게 처음부터 다시 따라해봐도 계속 같네요.
    그럼 답변 기다리겠습니다.

    • BlogIcon #에게 2019.09.23 18:33 신고

      딱히 에러가 없다면 servlet설정이나 log4j설정을 확인해보세용 우선순위(order)가 제대로 되어있는지, 패키지이름이 제대로 되어 있는 지, 등등을 봐야할 것 같아요

    • BlogIcon #에게 2019.09.23 18:34 신고

      윗댓글에 있는 깃허브 주소로 들어가셔서 소스 비교해보시는 것도 추천드려요!

  12. 2020.02.14 09:21

    안녕하세요~ 검색하다 들어오게 되어서 한번 적용을 해 보았는데 전혀 오류사항 같은건 뜨질 않아서 되는줄 알았습니다만.. 로그도 같이 안뜨네요. 혹시 짐작되는 이유가 있을까요? 임포트는 올려주신 소스와 동일하게 되어있습니다.

    • BlogIcon #에게 2020.02.14 11:56 신고

      톰캣을 구동했는데도 로그가 뜨지 않는 건가요?! 톰캣이든 뭐든 디버깅하면 구동이 되면 로그는 뜨는 게 정상인데... 혹시 콘솔 로그를 제한 해 두신거 아닐까요? 구글에 ‘이클립스 콘솔 로그 안나옴’ 라고 검색하셔서 옵션을 손 보셔야 할 듯 싶어요

  13. cm 2020.10.08 18:58

    인터셉터 테스트입니다만 뜨네요 ㄷㄷ
    찾아봐도 원인을 모르겠어요