Interceptor 설정
개념정리
핸들러 인터셉터는 DispatcherServlet 이 컨트롤러를 호출하기 전과 후에 요청과 응답을 참조하거나 가공할 수 있는 일종의 필터다. 서블릿 필터와 유사한 개념이라고 보면 된다.
핸들러 매핑의 역할은 URL 로부터 컨트롤러만 찾아 주는 것이 아니다. 핸들러 매핑은 DispatcherServlet 으로 부터 매핑 작업을 요청받으면 그 결과로 핸들러 실행 체인(HandlerExecutionChain) 을 돌려준다. 이 핸들러 실행 체인은 하나 이상의 핸들러 인터셉터를 거쳐서 컨트롤러가 실행될 수 있도록 구성되어 있다.
핸들러 인터셉터를 전혀 등록해주지 않았다면 바로 컨트롤러가 실행된다. 반면에 하나 이상의 핸들러 인터셉터를 지정했다면 순서에 따라 인터셉터를 거친 후에 컨트롤러가 호출된다.
핸들러 인터셉터는 서블릿 필터와 그 쓰임새가 유사하다. 하지만 핸들러 인터셉터는 HttpServletRequest, HttpServletResponse 뿐 아니라, 실행될 컨트롤러 빈 오브젝트, 컨트롤러가 돌려주는 ModelAndView, 발생한 예외 등을 제공받을 수 있기 때문에 서블릿 필터보다 더 졍교하고 편리하게 인터셉터를 만들 수 있다. 또한 핸들러 인터셉터 자체가 스프링의 빈이기 때문에 DI 통해 다른 빈을 활용할 수도 있다.
HandlerInterceptor는 HandlerInterceptorAdapter를 상속받아 구현하면 되는데, 상속받아 구현하게 되면 처리방법에 따라 3가지의 메소드를 사용할 수 있다.
- preHandle() : Controller가 수행되기 전 호출
(이후 Controller를 수행할지 여부를 boolean으로 return 함)
- postHandle() : Controller가 수행된 후 View를 호출하기 전 호출
- afterCompletion() : View 작업까지 완료한 후 호출
(responseBody를 이용할 경우 UI에 이미 값을 전달한 후 해당부분이 호출 됨)
public interface HandlerInterceptor { boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception; void postHandle( HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception; void afterCompletion( HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception; }
가장 흔하게 쓰이는 메소드는 preHandle()이다. 컨트롤러를 실행하기전 수행하기 때문에 페이지 이동 혹은 Ajax를 호출하여 데이터를 처리하기전 해당 사용자의 세션체크를 하는데 용이하다.
Interceptor를 사용하기 위해서 servlet-Context.xml에 Interceptor를 등록해야한다.
CommonSessionInterceptor.java파일을 등록하였다.
servlet-Context.xml
< ?xml:namespace prefix = "mvc" /> <mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/**"></mvc:mapping> <BEAN class=com.Interceptor.util.CommonSessionInterceptor /> </mvc:interceptor> </mvc:interceptors>
이제 다음차례는 CommonSessionInterceptor.java파일에 preHandle()메소드를 작성한다.
CommonSessionInterceptor.java
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; public class CommonSessionInterceptor extends HandlerInterceptorAdapter{ static final Logger logger = LoggerFactory.getLogger(CommonSession.class); public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception{ boolean result = false; String webRoot = request.getContextPath(); try { logger.info("======= call /sessionIntercepter start ======="); //이동하는 url이 예외url 일경우 if(excludeUrl(request)){ logger.info("======= call /sessionIntercepter url is no session check ======="); result = true; }else{ //세션값이 널일경우 if(request.getAttribute("sessionId") == null ){ //Ajax 콜인지 아닌지 판단 if(isAjaxRequest(request)){ logger.info("======= call /sessionIntercepter session is null ======="); response.sendError(HttpServletResponse.SC_UNAUTHORIZED); return false; }else{ // Ajax 콜이 아닐경우 login페이지로 이동. response.sendRedirect(webRoot + "/login.do"); result = false; } }else{ logger.info("======= call /sessionIntercepter session is not null ======="); result = true; } } } catch (Exception e) { e.printStackTrace(); logger.debug(e.getMessage()); return false; } //널이 아니면 정상적으로 컨트롤러 호출 logger.info("======= call /sessionIntercepter session is not null ======="); return result; } private boolean excludeUrl(HttpServletRequest request) { String uri = request.getRequestURI().toString().trim(); logger.info("======= call /sessionIntercepter request Url = " + uri + "======="); if (uri.indexOf("/login.do") > -1 || uri.indexOf("/common") > -1 || uri.indexOf("/logout.do") > -1){ return true; } else return false; } private boolean isAjaxRequest(HttpServletRequest req) { String ajaxHeader = "AJAX"; logger.info("======= call /sessionIntercepter req.getHeader(ajaxHeader) : " + req.getHeader(ajaxHeader) + "======="); return req.getHeader(ajaxHeader) != null && req.getHeader(ajaxHeader).equals(Boolean.TRUE.toString()); } }
excludeUrl 메소드는 로그인페이지, 로그아웃페이지등 session체크가 필요없는 예외 페이지들을 바로 컨트롤러가 수행할수 있도록 분기처리 해준 부분.
isAjaxRequest 메소드는 Ajax Header에 담겨있는 값을 판단하여 컨트롤러 호출이 Ajax인지 아닌지를 판단한다. session이 null이면서 Ajax 콜이 되었다면 로그인페이지로 이동한다.
function selectTestList() { var param = "param1=" + $("#param1").val(); $.ajax({ type:"POST", url : "/test/selectTList.do", data : param, dataType: 'json', beforeSend : function(xmlHttpRequest){ xmlHttpRequest.setRequestHeader("AJAX", "true"); // ajax 호출을 header에 기록 }, success:function(result) { resultTestList(result); }, error : AjaxError }) ; }
jsp에서 Ajax 콜 할때 xmlHttpRequest.setRequestHeader("AJAX", "true"); Header값에 true를 넣어서 보내준다.
참고 블로그 : http://seongilman.tistory.com/109
참고 블로그 : http://springsource.tistory.com/4
'Programming > Spring' 카테고리의 다른 글
Spring @RequestBody, @ResponseBody (0) | 2017.01.23 |
---|---|
java.lang.NoClassDefFoundError: org/apache/commons/pool/impl/GenericObjectPool 오류 (0) | 2017.01.23 |
WRITTEN BY