Aspect 를 이용한 공통 BindingResult 처리 방법

validation 을 다음과 같이 처리를 한다.

VO에서 Vaildation 관련 설정
@Data
@JsonInclude(Include.NON_NULL)
public class RolesVO {
    @NotNull(groups={ValidationGroup.Update.class})
    private Long roleSeq;
    @NotBlank(groups={ValidationGroup.Insert.class, ValidationGroup.Update.class})
    private String roleId;
    @NotBlank(groups={ValidationGroup.Insert.class, ValidationGroup.Update.class})
    private String roleName;
    private String roleComment;
    private String regUserId;
    private Date regDate;
    private String modUserId;
    private Date modDate;
}
Controller 에서 Vaild 처리
    @RequestMapping(method = RequestMethod.POST)
    public ResponseEntity add(@RequestBody @Validated(ValidationGroup.Insert.class) RolesVO vo, BindingResult result) throws Exception {
        /* validation */
         if(result.hasErrors()){
            ErrorResponse errorResponse = new ErrorResponse();
            errorResponse.setMessage("Wrong request!");
            errorResponse.setCode("bad.request");
            return new ResponseEntity(errorResponse, HttpStatus.BAD_REQUEST);
        }
        /* validation */
        return new ResponseEntity(modelMapper.map(service.addtRoles(vo), RolesVO.class), HttpStatus.CREATED);
    }

/ validation / 사이에 보이는 값은 대부분 중복 처리가 된다.
이 경우 중복된 코드가 너무 많이 반복되어 다음과 같이 처리 하였다.

Aspect를 이용한 공통 validat 처리

ValidCheckingInterceptor

@Aspect
@Component
public class ValidCheckingInterceptor {

    @Around("execution(* kr.pe.lahuman.*.controller.*.add*(..)) or execution(* kr.pe.lahuman.*.controller.*.modify*(..))")
    public Object anyMethod(ProceedingJoinPoint joinPoint) throws Throwable {
        Object[] objs = joinPoint.getArgs();
        for(Object obj : objs){
            if(obj instanceof BindingResult){
                BindingResult result = (BindingResult)obj;
                if(result.hasErrors()){
                    Map<String, Map<String, String>> userdata = new HashMap<String, Map<String,String>>();
                    Map<String, String> errors = new LinkedHashMap<String, String>();
                    for (FieldError error : result.getFieldErrors()) {
                        errors.put(error.getField(), error.getDefaultMessage());
                    }
                    userdata.put("userdata", errors);
                    return new ResponseEntity(userdata, HttpStatus.BAD_REQUEST);
                }                 
            }
        }
        return joinPoint.proceed(joinPoint.getArgs());
    }
}

Around 어노테이션에서 add와 modify로 시작되는 메소드 중 인자로 BindingResult 가 있을 경우 유효성 체크를 하여 에러가 있을 경우 문제 필드와 기본 메시지를 Map 형식으로 return 한다.

변경후 Controller에서 Vaild 제거 된 소스

    @RequestMapping(method = RequestMethod.POST)
    public ResponseEntity add(@RequestBody @Validated(ValidationGroup.Insert.class) RolesVO vo, BindingResult result) throws Exception {
        return new ResponseEntity(modelMapper.map(service.addtRoles(vo), RolesVO.class), HttpStatus.CREATED);
    }

반복해서 작성 되었던 유효성 처리가 제거 되었다. 이후 Vaild 관련 처리는 ValidCheckingInterceptor에서만 진행 된다.


MD FILE : 

Aspect_BindingResult.md



Posted by lahuman