
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:/";
}
실행 결과

@Around가 적용되어 PostMapping이 실행될 때 메서드가 작동된다.

throw new Exception400(errMsg);
오류 발생 시 400에러를 터트려 alert창을 띄운다.
Share article