Filter / Interceptor / AOP
필터 | 서블릿을 가로챔 | 서블릿 API : 메서드가 실행되기 전에 사용되는 방식 (웹서버) |
인터셉터 | 컨트롤러를 가로챔 | Spring API (스프링) |
AOP | 메서드를 가로챔 | 외부 라이브러리 |
사용방법
@Filter
1. springBootApplication 에서 서블릿 API를 사용하겠다 선언 ( ServletComponentScan )
※ @ServletComponentScan // 서블릿 API를 사용한다고 선언 - 서블릿 관련 애노테이션을 스캔한다.
※ @WebServlet @Filter @WebListener 주로 모델2 작업시 사용한 애노테이션을 사용하려면
@ServletComponentScan을 선언해야지만 사용할 수 있다.
@SpringBootApplication
@ServletComponentScan // 서블릿 API를 사용한다고 선언 - 서블릿 관련 애노테이션을 스캔한다.
// @WebServlet @Filter @WebListener 주로 모델2 작업시 사용한 애노테이션을 사용하려면 @ServletComponentScan을 선언해야지만 사용할 수 있다.
public class Ex2Application {
public static void main(String[] args) {
SpringApplication.run(Ex2Application.class, args);
}
}
2. Filter 구현 및 (doFilter을 기준으로 실행된다.)
@WebFilter("/admin/*") // @WebFilter : 서블릿 API, 요청을 가로챔 , 인터셉트 처럼 요청을 가로챈다.
public class Filter implements jakarta.servlet.Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// goFilter 위에는 요청전 실행되는 코드 부분
System.out.println("MyFilter 실행 - doFilter 이전");
chain.doFilter(request, response);
// goFilter 아래에는 응답전 실행되는 코드 부분
System.out.println("MyFilter 실행 - doFilter 이후");
}
}
※ 실행결과
MyFilter 실행 - doFilter 이전 ---------------------------------/admin/hello/------------------------------------------ MyFilter 실행 - doFilter 이후 |
@Interceptor
1. HandlerInterceptor 구현
@Component // spring bean 등록 대상
public class MyInterceptor implements org.springframework.web.servlet.HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
// 요청 전 실행되는 코드
System.out.println("MyInterceptor 실행 = preHandle");
return HandlerInterceptor.super.preHandle(request, response, handler);
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
// 응답 전 실행되는 코드
System.out.println("MyInterceptor 실행 = postHandle");
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}
}
2. springBootApplication 에서 WebMvcConfigurer 구현
@SpringBootApplication
public class Ex2Application implements WebMvcConfigurer {
@Autowired MyInterceptor myInterceptor;
public static void main(String[] args) {
SpringApplication.run(Ex2Application.class, args);
}
// WebMvcConfigurer 구현 및 registry 등록
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(myInterceptor).addPathPatterns("/admin/**");
WebMvcConfigurer.super.addInterceptors(registry);
}
}
@AOP 라이브러리 사용
1. 라이브러리 추가
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
2. Aspect 애노테이션 선언 클래스 생성 및 Bean Pool에 등록 ( 포인트컷 세팅 및 빈 등록 )
@Component
@Aspect //import org.aspectj.lang.annotation.Aspect;
public class MyAspect {
// implement를 하지 않으므로, 부모에 어떤 메서드를 오버라이딩을 해야하는지 알 수 없다. -> 메서드 이름 제한이 없음
@Before("execution(* com.example.ex2.TargetController.hello(..))")
public void pre() {
System.out.println("MyAspect 실행 = @Before");
}
@After("execution(* com.example.ex2.TargetController.hello(..))")
public void post() {
System.out.println("MyAspect 실행 = @After");
}
}
// "excution(* com.example.ex2.TargetController.hello(..))"
// 표현식 : AOP 매핑 패턴 검색
// 1) * = 접근제어자 상관없다.
// 2) (..) = param값 상관없다.
AOP: Aspect Oriented Programming
공통 관심 사항(cross-cutting concern) vs 핵심 관심 사항(core concern) 분리
- 공통 관심 사항 : 메서드가 실행되는데 실행되는 시간을 측정
- 핵심 관심 사항 : 비즈니스 로직
AOP를 사용하지 않으면, try catch 절에 비즈니스 로직과 시간을 측정하는 로직 등을 섞어서 써야한다.
공통 관심사항과 핵심 관심사항이 섞이면 유지보수가 어려움. (공통 관심사항 로직을 바꾸려면 모든 로직을 찾아가면서 변경해야함)
※ filter interceptor AOP 동시에 쓸때의 실행결과
MyFilter 실행 - doFilter 이전 MyInterceptor 실행 - preHandler AOP 실행 - 요청전 ---------------------------------/admin/hello/------------------------------------------ AOP 실행 - 요청후 MyInterceptor 실행 - postHandler MyFilter 실행 - doFilter 이후 |
논리적 크기는 서블릿 > 컨트롤러 > 메서드 이므로 (필터 실행 -> 인터셉터 실행 -> AOP 실행) 순서대로 실행되고 요청후에는 반대로 실행이 된다.
'SPRING' 카테고리의 다른 글
[Rest API] JSON과 XML로 반환 방법 (0) | 2024.12.10 |
---|---|
DI / Bean(@ComponentScan) (0) | 2024.12.09 |
POST-Redirect-GET (PRG) 패턴 (0) | 2024.11.30 |
[Service & MySQL 에러] SQLIntegrityConstraintViolationException (0) | 2024.11.13 |
[java 에러] row cannot be resolved to a variable (0) | 2024.11.13 |