Junit Test Application-14-회원가입 컨트롤러 AOP 처리, 유효성 검사

jaegeunsong97·2023년 8월 4일
0

Junit Bank Application 깃허브

Junit Bank Application 기록 노션

AOP 개념 정리와 유효성 검사의 중요성

AOP

  • pointcut : 어떤 메소드에 자동으로 adivce코드를 구현하고 싶은데?
  • advice : 어떤 코드를 구현할 건데?
  • joinpoint : pointcut 어노테이션이 붙은 메소드들 의미
package shop.mtcoding.bank.handler.aop;

import java.util.HashMap;
import java.util.Map;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;

import shop.mtcoding.bank.handler.ex.CustomValidationException;

@Aspect // 관점
@Component // 메모리에 띄우기
public class CustomValidationAdvice {

     @Pointcut("@annotation(org.springframework.web.bind.annotation.PostMapping)")
     public void postMapping() {
     }

     @Pointcut("@annotation(org.springframework.web.bind.annotation.PutMapping)")
     public void putMapping() {
     }

     // Before, After
     @Around("putMapping() || postMapping()") // jointpoint 전, 후 제어
     public Object validationAdvice(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
          Object[] args = proceedingJoinPoint.getArgs(); // joinpoint 매개변수
          for (Object arg : args) {
               if (arg instanceof BindingResult) { // 매소드에 BindingResult가 존재하면
                    BindingResult bindingResult = (BindingResult) arg;

                    if (bindingResult.hasErrors()) { // 에러가 존재하면
                         Map<String, String> errorMap = new HashMap<>();

                         for (FieldError error : bindingResult.getFieldErrors()) {
                              errorMap.put(error.getField(), error.getDefaultMessage());
                         }
                         throw new CustomValidationException("유효성검사 실패", errorMap);
                    }
               }
          }
          return proceedingJoinPoint.proceed(); // 진행시켜~
     }

}

@Around : 이거일 경우만 ProceedingJoinPoint를 받을 수 있다.
@Before
@After

putMapping() || postMapping() 가 있는 모든 메소드가 실행 전에 동작

코드 추가

package shop.mtcoding.bank.handler.ex;

import java.util.Map;

import lombok.Getter;

@Getter
public class CustomValidationException extends RuntimeException {

     private Map<String, String> errorMap;

     public CustomValidationException(String message, Map<String, String> errorMap) {
          super(message);
          this.errorMap = errorMap;
     }
}

코드 추가

package shop.mtcoding.bank.handler;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import shop.mtcoding.bank.dto.ResponseDto;
import shop.mtcoding.bank.handler.ex.CustomApiException;
import shop.mtcoding.bank.handler.ex.CustomValidationException;

@RestControllerAdvice
public class CumstomExceptionHandler {

     private final Logger log = LoggerFactory.getLogger(getClass());

     @ExceptionHandler(CustomApiException.class)
     public ResponseEntity<?> apiException(CustomApiException e) {
          log.error(e.getMessage());
          return new ResponseEntity<>(new ResponseDto<>(-1, e.getMessage(), null), HttpStatus.BAD_REQUEST);
     }

     @ExceptionHandler(CustomValidationException.class)
     public ResponseEntity<?> validationApiException(CustomValidationException e) {
          log.error(e.getMessage());
          return new ResponseEntity<>(new ResponseDto<>(-1, e.getMessage(), e.getErrorMap()), HttpStatus.BAD_REQUEST);
     }
}

만약 postMapping을 @Around에서 제거하면

아직 길이 제한에 대한 유효성 검사가 필요, 반드시 각 레이어는 본인의 책임을 가져야한다.

정리

  • AOP
  • 유효성 검사
profile
블로그 이전 : https://medium.com/@jaegeunsong97

0개의 댓글