[스프링부트 blogV3] 7. AOP적용하기 - validation

silver's avatar
Feb 03, 2025
[스프링부트 blogV3] 7. AOP적용하기 - validation
notion image
 

Aspect

: @Aspect → 해당 클래스를 AOP 관리 클래스로 지정하는 어노테이션! @Aspect만으로는 메모리에 뜨지 않아 @Component를 붙여서 띄워준다
import com.example.blogv11._core.error.ex.Exception400; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; import org.springframework.validation.Errors; @Component @Aspect public class MyValidationAspect { // method 실행 전 before, method 실행 후 after @Before("@annotation(org.springframework.web.bind.annotation.PostMapping)") public void validationCheck(JoinPoint jp) { Object[] args = jp.getArgs(); for (Object arg : jp.getArgs()) { // 매개변수에 Errors 존재하는지 체크 if(arg instanceof Errors){ Errors errors = (Errors) arg; // 다운캐스팅 if(errors.hasErrors()) { // 에러 존재하면 true가 뜬다 -> 성공 시 작동 안함 String errMsg = errors.getFieldErrors().get(0).getField()+":"+errors.getFieldErrors().get(0).getDefaultMessage(); throw new Exception400(errMsg); // } } } } // method 실행 전 후 around // @Before과는 다르게 object 타입 return 필수, JoinPoint -> ProceedingJoinPoint @Around("@annotation(org.springframework.web.bind.annotation.PostMapping)") public Object validationCheck(ProceedingJoinPoint jp) throws Throwable { Object[] args = jp.getArgs(); for (Object arg : jp.getArgs()) { if(arg instanceof Errors){ Errors errors = (Errors) arg; if(errors.hasErrors()) { String errMsg = errors.getFieldErrors().get(0).getField()+":"+errors.getFieldErrors().get(0).getDefaultMessage(); throw new Exception400(errMsg); // } } } System.out.println("직전"); Object ob = jp.proceed(); // controller의 save 메서드->proceed , ob-> return값 redirect:/ System.out.println("직후"); return ob; } }
@Before("@annotation(org.springframework.web.bind.annotation.PostMapping)")
:org.springframework.web.bind.annotation.PostMapping 는 pointcut이다 → PostMapping 시 실행
 

Request

import jakarta.validation.constraints.NotBlank; import lombok.Data; public class BoardRequest { @Data public static class SaveDTO{ @NotBlank(message = "야 비우지마") // NotBlank는 공백,띄어쓰기도 안됨 private String title; @NotBlank(message = "내용 공백 안됨") // -> Controllerd에서 @validation을 붙여줘야 작동한다. private String content; public Board toEntity(){ Board board = new Board(null,title,content,null); return board; } } @Data public static class UpdateDTO { @NotBlank private String title; @NotBlank private String content; } }

Controller

@PostMapping("/board/save") public String save(@Valid BoardRequest.SaveDTO saveDTO, Errors errors) { // Valid를 붙여줘야 SaveDTO에 가서 @NotBlank를 작동시킨다. // saveDTO에서 validation을 체크하고 난 오류를 바.로 옆에 있는 Errors에 넣어준다. -> 그래서 꼭 바로 옆에 Errors 넣어줘야한다. boardService.게시글쓰기(saveDTO); return "redirect:/"; }
 

실행 결과

notion image
@Around가 적용되어 PostMapping이 실행될 때 메서드가 작동된다.
 
notion image
throw new Exception400(errMsg);
오류 발생 시 400에러를 터트려 alert창을 띄운다.
 
Share article

silver