인터셉터 (Interceptor)
Back-End/Spring 2019. 6. 27. 17:56- 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차트를 볼 수 있게끔 하고, 관리자 로그인이 안되어 있으면 관리자 로그인창이 출력된다.
'Back-End > Spring' 카테고리의 다른 글
Spring 자바 코드 난독화 (Java Code Obfuscation) (0) | 2019.06.28 |
---|---|
Spring 자바스크립트 난독화 (0) | 2019.06.28 |
AOP와 트랜잭션 처리 실습 (코드로 테스트) (0) | 2019.06.26 |
http 응답 코드와 method의 종류 (0) | 2019.06.26 |
AOP와 트랜잭션 처리 실습 (데이터베이스로 테스트) (0) | 2019.06.24 |