loading

새소식

Framework/Springboot

[Springboot] 스프링부트 AOP, Filter, Interceptor 각 특징 및 사용법

  • -
728x90
반응형

▶ 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);
    }
}

 

728x90
반응형
Contents

📝 포스팅 주소를 복사했습니다 📝

이 글이 도움이 되었다면 공감 부탁드립니다👍