[Springboot] 스프링부트 AOP, Filter, Interceptor 각 특징 및 사용법
- -
▶ AOP (Aspect Oriented Programming) : 공통적으로 적용될 모듈을 만든 후 적용하고자 하는 부분의 코드 밖에서 삽입하는 방법
=> 사용 분야 : Method 의 성능 테스트, Transaction 처리, Execption 반환, 로깅 / 인증 / 권한 처리 등
=> Filter, Interceptor 방식 활용이 불가능할 때 사용
1. 사용 용어와 설명
2. execution() : 적용할 메소드를 세부적으로 명시
3. Aspect (Advice + Pointcut)
package com.example.basic.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Aspect // AOP 기능 활성화
@Component // 자동 Bean 등록
public class ControllerAspect {
long start = 0L;
long end = 0L;
@Before(value = "execution (* com.example.basic.Controller.*.*(..))") // controller 안의 모든 클래스(*) 안의 모든 메소드(*) 안의 모든 매개변수(..)
public void onBeforeHandler(JoinPoint joinPoint) {
log.warn("@Before run");
start = System.currentTimeMillis();
}
@After(value = "execution (* com.example.basic.Controller.*.*(..))")
public void onAfterHandler(JoinPoint joinPoint) {
log.warn("@After run");
end = System.currentTimeMillis();
log.warn(end - start + "");
}
@AfterThrowing(value = "execution (* com.example.basic.Controller.AuthController.*(..))")
public void afterThrowing(JoinPoint joinPoint) {
log.warn("오류 발생");
}
@AfterReturning(value = "execution (* com.example.basic.utill.*.*(..))", returning = "data")
public void onAfterReturningHandler(JoinPoint joinPoint, Object data) {
if (data != null) {
log.warn(data.toString());
}
log.debug("@AfterReturning run");
}
}
4. ControllerAdvice : Controller에서 발생되는 오류를 감지하고 처리해주는 기능
(1) 사용 이유
1) 예외처리를 한 곳에 묶어서 편하게 관리
2) 처리가 제대로 되지 못한 부분에 예외가 발생되는 경우 브라우저에 Exception Message가 노출되어 버리는데 모든 예측하지 못한 예외도 한꺼번에 처리 가능
(2) 기본 구조
@ControllerAdvice // @ControllerAdvice의 옵션으로 특정 패키지, 특정 클래스만 지정 가능
public class MyControllerAdvice {
@ExceptionHandler // @ExceptionHandler의 옵션으로 특정 Exception에 대해서만 동작 가능
[@ResponseStatus] // @ResponseStatus의 옵션으로 응답 코드 지정 가능
[@ResponseBody]
public String handle(RuntimeException e, WebRequest request) {
return [view]; // 메소드의 리턴 타입은 컨트롤러에서 사용하는 것과 동일
}
}
▶ Filter : HTTP 요청과 응답을 변경할 수 있는 기능
=> 스프링보다 더 먼저 동작
=> 사용 분야 : XSS (Cross Site Scripting) 방지, 로깅, 인코딩, IP 검사
// filter/IPCheckFilter.java //
package com.example.basic.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class IPCheckFilter implements Filter {
@Override
public void doFilter(
ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
log.warn("filter begin");
HttpServletRequest req = (HttpServletRequest) request;
String ip = request.getRemoteAddr();
log.warn("ip : " + ip);
chain.doFilter(req, response);
log.warn("filter end");
}
}
// config/FilterConfig.java //
package com.example.basic.config;
import javax.servlet.Filter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.example.basic.filter.IPCheckFilter;
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean<Filter> getFilterRegistrationBean() {
FilterRegistrationBean<Filter> bean = new FilterRegistrationBean<>(new IPCheckFilter());
bean.addUrlPatterns("/*");
return bean;
}
}
▶ Interceptor : Controller에 들어오는 요청과 응답을 가로채는 기능
=> Filter와 매우 유사하지만 동작하는 시기가 다름
=> AOP, Filter 보다 더 많이, 자주 사용함
=> 주요 메소드
- preHandler() : Controller의 메소드가 실행되기 전 (요청)
- postHandler() : Controller의 메소드가 실행된 후 (응답)
- afterCompletion() - View가 Rendering 된 이후
// interceptor/SignInCheckInterceptor.java //
package com.example.basic.interceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.catalina.User;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import lombok.extern.slf4j.Slf4j;
@Component
@Slf4j
public class SignInCheckInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(
HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
log.debug("preHandle");
HttpSession session = request.getSession();
User user = (User) session.getAttribute("name");
if (user == null) {
response.sendRedirect("/auth/signin");
return false;
}
return true;
}
@Override
public void postHandle(
HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView modelAndView) throws Exception {
log.debug("postHandle");
}
@Override
public void afterCompletion(
HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) throws Exception {
log.debug("afterCompletion");
}
}
// config/InterceptorConfig.java //
package com.example.basic.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import com.example.basic.interceptor.SignInCheckInterceptor;
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Autowired
private SignInCheckInterceptor signInCheckInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(signInCheckInterceptor).addPathPatterns("/**");
WebMvcConfigurer.super.addInterceptors(registry);
}
}
'Framework > Springboot' 카테고리의 다른 글
[Springboot] 스프링부트 JPA (0) | 2023.11.13 |
---|---|
[Springboot] 스프링부트 파일 업로드 및 파일 다운로드 (0) | 2023.10.06 |
[Springboot] 스프링부트 비밀번호 암호화 설정(SpringSecurity, PasswordEncoder) (0) | 2023.10.05 |
[Springboot] 스프링부트 Session 세션 사용법 (0) | 2023.10.04 |
[Springboot] 스프링부트 Thymeleaf 타임리프 (0) | 2023.10.04 |
소중한 공감 감사합니다🤗