kenzi
HandlerInterceptor(preHandle, postHandle등) 본문
HandlerInterceptorAdapter를 상속받으면 preHandle(), postHandle(), afterCompletion을 오버라이딩할 수 있는데
차이가 뭔지 모르겠다
강사님은
preHandle은 조인포인트 전에 실행
postHandle은 조인 포인트 전에 실행, ModelAndView를 사용해서 조인포인트에 영향을 주는 것
이라고 하셨다
pre는 전이고 post는 후인데......????
그래서 스프링 공식문서를 찾아보았다
https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#spring-web
Web on Servlet Stack
Spring Web MVC is the original web framework built on the Servlet API and has been included in the Spring Framework from the very beginning. The formal name, “Spring Web MVC,” comes from the name of its source module (spring-webmvc), but it is more com
docs.spring.io
1.1.7. Interception
All HandlerMapping implementations support handler interceptors that are useful when you want to apply specific functionality to certain requests — for example, checking for a principal.
Interceptors must implement HandlerInterceptor from the org.springframework.web.servlet package with three methods that should provide enough flexibility to do all kinds of pre-processing and post-processing:
- preHandle(..): Before the actual handler is run
- postHandle(..): After the handler is run
- afterCompletion(..): After the complete request has finished
The preHandle(..) method returns a boolean value. You can use this method to break or continue the processing of the execution chain. When this method returns true, the handler execution chain continues. When it returns false, the DispatcherServlet assumes the interceptor itself has taken care of requests (and, for example, rendered an appropriate view) and does not continue executing the other interceptors and the actual handler in the execution chain.
See Interceptors in the section on MVC configuration for examples of how to configure interceptors. You can also register them directly by using setters on individual HandlerMapping implementations.
Note that postHandle is less useful with @ResponseBody and ResponseEntity methods for which the response is written and committed within the HandlerAdapter and before postHandle. That means it is too late to make any changes to the response, such as adding an extra header. For such scenarios, you can implement ResponseBodyAdvice and either declare it as an Controller Advice bean or configure it directly on RequestMappingHandlerAdapter.
일단 preHandle()은 handler 실행 전
postHandle()은 handler 실행 후 (요청이 아예 완료된거랑은 다름)
afterCompletion이 요청이 아예 완료된 것
handler 실행 후와 요청완료단계 사이에서 ModelAndView로 객체를 보내서 요청을 완료시키는건가?
공식문서를 봐도 뭔가 찜찜하다
구글링을 해보았다
https://kimvampa.tistory.com/127
[spring] Spring Interceptor 란?(HandlerInterceptor, HandlerInterceptorAdapter)
목표 Interceptor 란 무엇인지 알아본다. Interceptor를 직접 구현해본다. 순서 1. 인터셉터(Interceptor) 1.1 인터셉터란? 1.2 왜 사용하는가? 1.3 구현 수단 1.4 어떤 메서드를 가지고 있는가? 2...
kimvampa.tistory.com
preHandle()
- 컨트롤러가 실행 이전에 처리해야 할 작업이 있는 경우 혹은 요청정보를 가공하거나 추가하는 경우에 사용합니다.
- 실행되어야 할 '핸들러'에 대한 정보를 인자 값으로 받기 때문에 '서블릿 필터'에 비해 보다 세밀하게 로직을 구성할 수 있습니다.
postHandle()
- 핸들러가 실행은 완료되었지만 아직 View가 생성되기 이전에 호출됩니다.
- ModelAndView 타입의 정보를 인자 값으로 받습니다. 따라서 Controller에서 View에 정보를 전달하기 위해 작업한 Model 객체의 정보를 참조하거나 조작할 수 있습니다.
afterCompletion()
- 모든 View에서 최종 결과를 생성하는 일을 포함한 모든 작업이 완료된 후에 실행됩니다.
- 요청 처리 중에 사용한 리소스를 반환해주기 적당한 메서드입니다.
즉,
사용자가 url로 request를 보내면
1) 서블릿이 handlerMapping을 통해 요청을 처리할 핸들러(url을 처리할 메서드 in 컨트롤러) 찾아서 요청
2) 컨트롤러 실행전 (== 핸들러 처리전) 인터셉터가 preHandle()의 boolean value가 참이면 컨트롤러를 실행해서 서비스 로직을 수행
3) 다시 인터셉터가 postHandle()로 서블릿에 ModelAndView 인자값을 보냄
4) 서블릿은 afterCompletion()로 만들어진 view를 response로 보낸다
자 그럼 interceptor라는 건 정확히 뭘까? 가로채다라는 의미는 알겠다
서버에 들어온 Request 객체를 컨트롤러의 핸들러로 도달하기 전 후에 끼어들어 추가적인 작업을 하여 Controller에 관한 요청과 응답에 관여하는 것이다.
간단하게 Servlet과 Controller사이에 중간다리가 하나 더 생긴거다
또 궁금한게 생겼다
Interceptor와 @advice...@around...랑은 뭐가 다른거지?
Spring Filter, Interceptor, AOP 비교
이글에서는 3개를 간단하게 비교하고 다른 포스팅에서 각각을 자세히 설명하고 코드로 실습해보겠습니다. 이글에서는 가볍게 봐주세요. 순서는 Filter -> Interceptor -> AOP -> Interceptor -> Filter 순으로
wellbell.tistory.com
Spring AOP는 컨트롤러 처리 이후 비지니스 로직에서 실행되는 것이다
가장 큰 차이는 파라미터의 차이로,
@Advice의 경우에는 JoinPoint와 ProceedingJoinPoint 등을 활용하여 호출하고.
Interceptor의 경우는 HttpServletRequest, HttpServletResponse를 파라미터로 사용한다.
이해한 예제
//dispatcher-servlet.xml
<mvc:interceptor>
<mvc:mapping path = "/acl/**" />
<bean class = "service.AdminInterceptor" />
</mvc:interceptor>
public class AdminInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
HttpSession session = request.getSession();
//로그인 컨트롤러에서 세션에 auth란 이름으로 auth를 넣어놓음 -- 그것을 가져옴
Auth auth = (Auth) session.getAttribute("auth");
if(auth != null && auth.getId().equals("m1") ) {// auth로 로그인된 유저가 있고 id가 m1이면 참
return true;
} else { //auth로 로그인된 유저가 없거나 id가 m1이 아니면
//url한글 깨짐 방지
String msg = URLEncoder.encode("사용이 허용되지 않습니다","UTF-8");
//msg를 뷰에서 자바스크립트로 alert 띄우고 auth/login에 의해 index.jsp로 보냄
response.sendRedirect(request.getContextPath()+"/auth/login?msg="+ msg);
}
System.out.println("1)admin : preHandle()");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("2)admin : postHandle()");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
System.out.println("3)admin : afterCompletion()");
}
}
//Controller
public class AclController {
@RequestMapping("/acl/list")
public String list(Model model) {
model.addAttribute("aclList",aclService.getAclList());
return "acl/aclList";
}
}
서블릿에 /acl/** url요청이 들어오면 AclController에 가기전에 AdminInterceptor를 거치게 됨
AdminInterceptor에서 preHandle()가 참이면 postHandle() - > afterCompletion()을 거쳐
서블릿에 /acl/aclList.jsp라는 뷰를 보내주게 된다
'Spring' 카테고리의 다른 글
pom.xml에서 dependency 안 붙을 때 (0) | 2022.04.21 |
---|---|
http.converter.HttpMessageNotWritableException (0) | 2022.04.19 |
스프링 인코딩 필터 (0) | 2022.04.14 |
java.lang.classnotfoundexception (0) | 2022.04.14 |
@Component? @Controller? (0) | 2022.04.13 |