유효성 검사기

import java.util.Collection;
import java.util.List;
import javax.validation.Validation;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindingResult;
import org.springframework.validation.Errors;
import org.springframework.validation.ObjectError;
import org.springframework.validation.SmartValidator;
import org.springframework.validation.beanvalidation.SpringValidatorAdapter;

@Component
public class CollectionValidator implements SmartValidator {
    private SpringValidatorAdapter validator;

    public CollectionValidator() {
        this.validator = new SpringValidatorAdapter(Validation.buildDefaultValidatorFactory().getValidator());
    }

    @Override
    public boolean supports(Class<?> clazz) {
        return true;
    }

    @Override
    public void validate(Object target, Errors errors) {
        if (target instanceof Collection) {
            Collection<?> collection = (Collection<?>) target;
            for (Object object : collection) {
                validator.validate(object, errors);
            }
        } else {
            validator.validate(target, errors);
        }
        checkError((BindingResult)errors);
    }

    public void validate(Object target, Errors errors, Object... validationHints) {
        if (target instanceof Collection) {
            Collection<?> collection = (Collection<?>) target;
            for (Object object : collection) {
                validator.validate(object, errors, validationHints);
            }
        } else {
            validator.validate(target, errors, validationHints);
        }
        checkError((BindingResult)errors);
    }
    
    public void checkError(BindingResult result) {
        if (result.hasErrors()) {
            throw new SampleException(result.getAllErrors().get(0).getDefaultMessage());
        }
    }
}

유효성 검사기 등록

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.InitBinder;

@ControllerAdvice
public class ValidationConfig {
    @Autowired
    private CollectionValidator collectionValidator;

    @InitBinder
    public void bind(WebDataBinder binder) {
        binder.setValidator(collectionValidator);
    }
}

데이터 모델(유효성 그룹 생성 및 필수 항목 정의)

import javax.validation.constraints.AssertTrue;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.validator.constraints.NotEmpty;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;

@Data
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(value = JsonInclude.Include.NON_NULL)
public class SampleDTO implements Serializable {
    private static final long serialVersionUID = 1L;

    /**
     * Model 유효성 그룹
     */
    public interface Search {}    // 샘플 조회
    public interface Save{}       // 샘플 저장
    public interface Remove {}    // 샘플 삭제

    @NotEmpty(message = "var1 정보가 없습니다.", groups = { Search.class, Save.class })
    private String var1;

    @NotEmpty(message = "var2 정보가 없습니다.", groups = { Search.class, Remove.class })
    private String var2;

    private String var3;

    private String var4;

    @Min(value = 1, message = "var5 정보가 없습니다.", groups = { Save.class, Remove.class })
    private long var5;

    @JsonIgnore
    @AssertTrue(message = "필수 정보가 없습니다.", groups = { Search.class })
    public boolean isValidMultipleParams() {
        if (StringUtils.isEmpty(var3)) return false;
        if (StringUtils.isEmpty(var4)) return false;
        if (var5 == 0) return false;
        return true;
    }
}

Controller의 Request 모델에 유효성 검사기 적용

import org.springframework.validation.annotation.Validated;

@RestController
@RequestMapping("/sample")
@Api(description="샘플 API")
public class SampleApiController {
    @Autowired
    private SampleService sampleService;

    @ApiOperation(value = "샘플 조회")
    @GetMapping
    public ResponseEntity<List<SampleDTO>> sampleSearch(
        @Validated(SampleDTO.Search.class)
        @ModelAttribute SampleDTO sample) throws SampleException {
        List<SampleDTO> list = sampleService.findSampleList(sample);
        return new ResponseEntity<>(list, HttpStatus.OK);
    }
    
    @ApiOperation(value = "샘플 저장")
    @PostMapping
    public ResponseEntity<ResultMsg> sampleSave(
        @Validated(SampleDTO.Save.class)
        @RequestBody List<SampleDTO> sampleList) throws SampleException {
        sampleService.saveSampleList(sampleList, result);
        return new ResponseEntity<>(new ResultMsg("Y", "정상"), HttpStatus.OK);
    }

    @ApiOperation(value = "샘플 삭제")
    @DeleteMapping
    public ResponseEntity<ResultMsg> sampleRemove(
        @Validated(SampleDTO.Remove.class)
        @RequestBody List<SampleDTO> sampleList) throws SampleException {
        sampleService.removeSampleList(sampleList);
        return new ResponseEntity<>(new ResultMsg("Y", "정상"), HttpStatus.OK);
    }
}

비즈니스 로직 내 유효성 확인

@Service
public class SampleServiceImpl implements SampleService {
    @Autowired
    private CollectionValidator collectionValidator;

    public void saveSampleList(List<SampleDTO> list, BindingResult result) {
        collectionValidator.validate(list, result, SampleDTO.Save.class);
        for (SampleDTO item : list) {
            saveSample(item);
        }
    }
}

'#Tech. > Spring Boot' 카테고리의 다른 글

RestTemplate 로그 출력  (0) 2020.05.09
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기