인터셉터 (Interceptor)

Back-End/Spring 2019. 6. 27. 17:56
728x90
반응형

- Interceptor (인터셉터) -



  클라이언트의 요청 전,후에 특정 작업을 처리하고자 할 때 사용하는 기능 (간단하게 컨트롤러 같은 계층이라고 생각하면 됨)


  매개변수 - HttpServletRequest, HttpServletResponse

  

  용도 - 로그인 처리, pc웹 / 모바일웹 분기 처리 등

  

  


  Filter : 인코딩 처리할때 사용 (예를 들면 한글 인코딩 필터), 필터는 선처리만 된다.

  

  Interceptor : AOP의 @Around와 비슷한 성격이다, 하지만 AOP는 메소드 단위 (코드)로 설정하고, 인터셉터는 특정한 URL 단위로 설정한다.

  

  html 페이지는 웹서버에서 별도의 처리를 하지 않고, 그대로 클라이언트에게 전달된다.


  jsp 페이지는 JspServlet를 경유하여 html로 변환된 후 클라이언트에게 전달됩니다.

 

  Spring Framework에서는 DispatchereServlet을 경유하여 처리됩니다.


  인터셉터는  Filter (필터) - DispatcherServlet 이전에 실행되며 선처리만 가능합니다.

  

  

  AOP - @Around => ProceedingJoinPoint


@Before, @After => JoinPoint


  실행순서 : 1. Filter > 2. DispatcherServlet > 3. Interceptor > 4. AOP



-예제 1. 특정한 url에 대해서 인터셉터가 실행되는지 확인.-

  

SampleInterceptor.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
33
34
35
36
37
38
39
40
41
42
package com.example.spring02.interceptor;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
 
// HandlerInterceptorAdapter 를 상속받음(추상클래스)
public class SampleInterceptor 
    extends HandlerInterceptorAdapter {
    //로깅을 위한 변수
    private static final Logger logger
        = LoggerFactory.getLogger(SampleInterceptor.class);
    
    
    //선처리와  후처리는 필수가 아니므로 원하는곳에서 작업을 하면 된다.
    
    
    
//선처리
    @Override
    //preHandle는 메인 요청 전에 경유하는 메소드
    public boolean preHandle(HttpServletRequest request
            , HttpServletResponse response, Object handler) 
                    throws Exception {
        logger.info("pre handle...");
        return true//true이면 계속 진행, false이면 멈춤
    }
//후처리
    @Override
    //postHandle는 메인 요청이 끝난 다음에 경유하는 메소드 
    public void postHandle(HttpServletRequest request
            , HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
        logger.info("post handle..."); 
    }
}
 
 
cs



servlet - context 인터셉터 관련 설정



  먼저 인터셉터를 bean으로 설정한 후


  <beans : bean id = "인터셉터의 아이디" class = "인터셉터의 경로" />




  

  어떤 url을 호출했을 때 인터셉터를 작동시킬 것인지 설정해야 합니다.


  <interceptors>

  <interceptor>

  <mapping path = "/shop/**"/>

  <beans:ref bean = "인터셉터의 아이디"/>

  </interceptor>

  </interceptors>




servlet-context.xml

(인터셉터 관련 빈을 등록하고 shop 하위 모든 url에 인터셉터를 적용)

=> 즉, shop 하위 url이 실행될때 인터셉터 빈에 등록된 클래스가 실행된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 
<!-- 인터셉터 빈을 등록 -->
 
<beans:bean id = "sampleInterceptor" class = "com.example.spring02.interceptor.SampleInterceptor" />
    <interceptors>
        <interceptor>
 
        <!-- 인터셉터의 매핑 정보 -->
    
        <!-- shop 하위 url에 인터셉터를 적용 -->
 
            <mapping path="/shop/**" />
            <beans:ref bean="sampleInterceptor" /> //아이디를 참조하는 것이기 때문에 bean id와 ref bean은 같아야 한다.
    </interceptor>
</interceptors>
cs



코드를 추가하고 서버를 돌리고 로그를 확인해보면 pre handle와  post handle 사이에 인터셉터가 실행된 것을 확인할 수 있다.



==============================================================================================



예제 2. 


views / include / session_check.jsp


인터셉터를 사용하지 않고 세션의 존재 여부를 체크하는 코드를 작성할 경우 아래와 같이 처리한다.


  

  shop하위의 페이지로 넘어갈때 서블릿에 인터셉터를 빈으로 등록해놓으면 장바구니를 클릭할때 


  인터셉터에서 로그인 여부를 판단해서 작업을 처리한다.




원래는 컨트롤러에서 처리를 해도 된다

관리자 전용 페이지의 세션 체크

http://localhost:8080/spring02/shop/product/write.do


write.jsp파일에 다음 코드를 추가



  

  <%@ page language = "java" contentType = "text/html; charset=UTF-8" pageEncoding = "UTF-8"%>

  <!--views/include/session_check.jsp -->

  <%@ taglib prefix = "c" uri = "http://java.sun.com/jsp/jstl/core" %>

  <c:if test = "${sessionScope.admin_userid == null}" >   // 세션을 체크했을때 null값과 같으면 (로그인을 안했다면)..

      <script>

           alert("로그인 하신 후 사용하세요.");                  // 다음 메시지를 출력함..

           location.href = "${path}/admin/login.do";          // 로그인 페이지로 이동시켜주는 코드

      </script>

  </c:if>




LoginInterceptor.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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package com.example.spring02.interceptor;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
 
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
 
 
//HandlerInterceptorAdapter 추상클래스 상속
// preHandle(), postHandler() 오버라이딩
 
public class LoginInterceptor 
    extends HandlerInterceptorAdapter {
    
    
    //로그인을 하기전에 로그인이 되어있는 상태인지 검사하고 로그인이 되어있으면
    //메인 액션으로 이동하고, 로그인이 안되어있으면 로그인 페이지로 이동시킨다.
    //메인 액션이 실행되기 전 실행되는 메소드

    @Override
    public boolean preHandle(HttpServletRequest request
            , HttpServletResponse response, Object handler) 
                    throws Exception {
        //세션 객체 생성
        HttpSession session=request.getSession();
        
        //세션이 없으면(로그인되지 않은 상태)
        if(session.getAttribute("userid"== null) {
            
            //login 페이지로 이동
            response.sendRedirect(request.getContextPath()
                    +"/member/login.do?message=nologin");
            return false//메인 액션으로 가지 않음
        }else {
            return true//메인 액션으로 이동
        }
    }
    
    //메인 액션이 실행된 후 실행되는 메소드
    @Override
    public void postHandle(HttpServletRequest request
            , HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
        super.postHandle(request, response, handler, modelAndView);
    }
}
cs


이 인터셉터를 적용하기 위해 태그를 선언해야 한다.


servlet - context.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
26
27
28
29
30
31
<!-- 인터셉터 빈을 등록 -->
    <beans:bean id="sampleInterceptor" //id에는 클래스이름에다가 첫글자만 소문자로 된 것을 많이 사용한다.
class="com.example.spring02.interceptor.SampleInterceptor"> //클래스에는 정확한 경로를 적어야 한다.
    </beans:bean>
    <beans:bean id="loginInterceptor"
class="com.example.spring02.interceptor.LoginInterceptor">
    </beans:bean>
    <beans:bean id="adminInterceptor"
class="com.example.spring02.interceptor.AdminInterceptor" />
 
<!-- 인터셉터 호출을 위한 url mapping -->
 
    <interceptors>
        <interceptor>
        <!-- 인터셉터의 매핑 정보 -->    
        <!-- shop 하위 url에 인터셉터를 적용 -->
            <mapping path="/shop/**" />
            <beans:ref bean="sampleInterceptor" />
        </interceptor>

        <interceptor>
//그러니까 아래와 같은 url로 (list.do, insert.do) 접속했을때 loginInterceptor를 적용시키라는 의미.
            <mapping path="/shop/cart/list.do"/>
            <mapping path="/shop/cart/insert.do"/>
            <beans:ref bean="loginInterceptor"/>
        </interceptor>

    <!-- 관리자 세션 체크를 위한 인터셉터 설정 -->

        <interceptor>
            <mapping path="/shop/product/write.do"/>
            <mapping path="/shop/product/insert.do"/>
            <beans:ref bean="adminInterceptor" />
        </interceptor>

    </interceptors>
cs



인터셉터를 만들어놓으면 컨트롤러마다 세션을 만들지 않아서 되서 편리하다.



3. 관리자 로그인을 체크할 수 있는 인터셉터 만들기


AdminInterceptor.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
33
34
35
36
37
38
39
40
41
42
package com.example.spring02.interceptor;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
 
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

// HandlerInterceptorAdapter 추상클래스 상속
// preHandle(), postHandle() 오버라이딩

public class AdminInterceptor 
    extends HandlerInterceptorAdapter {
    
    //로그인 실행전 처리하는 메소드
    //세션에 저장되어있는 id가 null이면 로그인 페이지로 이동하고,
    //세션에 저장되어 있는 id가 있으면 메인 액션으로 이동함

    @Override
    public boolean preHandle(HttpServletRequest request
            , HttpServletResponse response, Object handler) 
                    throws Exception {
        //세션 객체 생성
        HttpSession session=request.getSession();
        //세션변수 admin_userid가 없으면
        if(session.getAttribute("admin_userid")==null) {
            //로그인 페이지로 이동
            response.sendRedirect(request.getContextPath()
                    +"/admin/login.do?message=nologin");
            //메인 액션으로 이동하지 않음
            return false;
        }else {
            //세션 변수가 있으면 메인 액션으로 이동
            return true;
        }
    }

    //후처리
    @Override
    public void postHandle(HttpServletRequest request
            , HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
        super.postHandle(request, response, handler, modelAndView);
    }
}
cs



servlet-context.xml 중 일부 (인터셉터 매핑 url 추가, chart랑 jchart도 관리자만 사용할 수 있게끔)

1
2
3
4
5
6
7
8
9
10
       <!-- 관리자 세션 체크를 위한 인터셉터 설정 -->
 
        <interceptor>
            <mapping path="/pdf/list.do"/>
            <mapping path="/shop/product/write.do"/>
            <mapping path="/shop/product/insert.do"/>
            <mapping path="/chart/**" />
            <mapping path="/jchart/**" />
            <beans:ref bean="adminInterceptor" />
        </interceptor>
cs



프로젝트를 실행하면 관리자 로그인을 한 상태에서만 차트와 j차트를 볼 수 있게끔 하고, 관리자 로그인이 안되어 있으면 관리자 로그인창이 출력된다.

728x90
반응형
: