내가 보려고 정리하는/Spring

웹 : H/V로 검증하기 : 0329

보동이용용 2023. 3. 29. 08:53
반응형

🚩오전 : 

페이징, 검색 : 상품목록 : 조건 - 상품분류, 상품 거래처, 상품 이름 - 상세검색

 

🚩오후 : 어떻게 검증을 없애고, H/V을 사용할 것인가

검증도구 중 H/V 선택한 이유 : simple(어노테이션사용) ,  범용성(spring)


<< H/V 사이트 >>

https://hibernate.org/validator/

 

The Bean Validation reference implementation. - Hibernate Validator

Express validation rules in a standardized way using annotation-based constraints and benefit from transparent integration with a wide variety of frameworks.

hibernate.org

원래는 레이어마다 검증을 하는 코드가 들어간다.

 

모든 레이어에 영향을 주는 D.L에 H/V를 사용하여 검증 코드를 한번에 한다.

메이븐 프로젝트를 사용하기 있기 때문에 dependency만 가져와서 pom.xml에 설치하면 아래와 같이 파일이 추가된 것을 볼 수 있다.

jdk가 있는 곳이면 모두 사용 가능, 자바에서 기본적으로 사용하는 것...

이렇게 javax로 되어있는 패키지는 자바에서 기본적으로 사용하는 패키지라고 생각하면 될 것 같다.

https://desperategirl.tistory.com/37

 

2020-02-17 javax의 정의

자바의 초기버전인 1.02와 1.1에서는 자바에 내장된 클래스가 모두 java로 시작한는 이름을 가진 패키지에 들어있었습니다. 하지만 표준 라이브러리에 속하지 않는 다른 다양한 패키지가 등장하기

desperategirl.tistory.com

H/V는 어노테이션의 형태로 사용한다.

H/V는 DB 의 제약사항을 Domain Layer에 적용시켜 검증을 위한 처리를 하는 도구이다.

	private int rnum;
	@NotBlank(groups = InsertGroup.class)
	private String memId;
	@NotBlank(groups = {Default.class, DeleteGroup.class})
	@JsonIgnore
	private transient String memPass;
	@NotBlank(groups = InsertGroup.class)
	private String memName;
	@Size(min = 6, max = 6)
	@JsonIgnore
	private transient String memRegno1;
	@Size(min = 7, max = 7)
	@JsonIgnore
	private transient String memRegno2;
	
//	private Timestamp memBir;
	private LocalDateTime memBir; //UTC방식 
	@NotBlank
	private String memZip;
	@NotBlank
	private String memAdd1;
	@NotBlank
	private String memAdd2;
	@Pattern(regexp = "\\d{2,3}-\\d{3,4}-\\d{4}")
	private String memHometel;
	@Pattern(regexp = "\\d{2,3}-\\d{3,4}-\\d{4}")
	private String memComtel;
	@Pattern(regexp = "010-\\d{3,4}-\\d{4}")
	private String memHp;
	@NotBlank //마크 어노테이션
	@Email
	private String memMail;
	private String memJob;
	private String memLike;
	private String memMemorial;
	
//	private Date memMemorialday;
	private LocalDate memMemorialday; //UTC방식 
	@Min(0) // single value 어노테이션
	private Integer memMileage;
	private boolean memDelete;
}

 @NotBlank : not null

@Pattern : 정규식으로 패턴을 설정할 수 있다.

@Email : 이메일 양식을 검증할 수 있다.

@NoBlank (groups = {}) :  그룹힌트. 사용될 디폴트 그룹을 설정하고 특정 그룹은 이 그룹어노테이션으로 설정해줄 수도있다.

⛑️마커인터페이스 : body가 없고 인터페이스만 생성한 것. ex)serializable

약간... omr카드에 마킹하듯이 그냥 표시한다는 느낌인 것 같다.

왜냐하면 insertGroup이름으로 마커 인터페이스 만들었는데, 디폴트 그룹으로 설정하기 위해서 그냥 표시만하는 용도로 사용중이다.

// 정말 이 코드가 끝이다.
public interface InsertGroup extends Default{}

저렇게 Default를 상속받아서 기본 그룹으로 설정한다.

그리고 도메인 레이어에서 이 그룹힌트를 주지 않으면 Default를 상속받은 그룹에서만 사용한다는 뜻이고, 설정을 새로 해준다면 그 설정한 그룹에서만 사용한다는 것이다.

public class ValidateUtils {
	// 검증도구 Validator 선언
	private static Validator validator;
	// class가 로딩되고 제일 먼저 자동으로 실행되는 유일한 static블럭 
	static {
		//Factory method pattern으로 공장 생성.
		ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
		validator = factory.getValidator();
	}
	// Generic타입(<T>)으로 생성하여 여러 곳에서 사용할 수 있도록 한다.
	// 결과를 참과 거짓으로 리턴 받는다.
	// 파라미터로 target을 받고
	// 하나의 대상에 여러 에러메세지들을 담을 Map<String, List<String>>을 받고
	// 어느 상황에 사용할지 groupHints들을 받는다.
	public static <T> boolean validate(T target, Map<String, List<String>> errors, Class<?>...groupHints){ 
		Set<ConstraintViolation<T>> violations = validator.validate(target, groupHints);
		// 에러 메세지가 비어있다면? 검증에 통과한것.
		boolean valid = violations.isEmpty();
		//통과하지 못했다면
		if(! valid){
			// 반복문 안에서 키와 메세지로 나누어 받아 리스트에 추가한다.
			for( ConstraintViolation<T> single: violations) {
				String propertyName = single.getPropertyPath().toString();
				String message = single.getMessage();
				// 이미 리스트가 있는지 확인하는 작업
				List<String> already = errors.get(propertyName);
				// 아직 없다면 새로 생성
				if(already==null) {
					already = new ArrayList<>();
				}
				already.add(message);
				errors.put(propertyName, already);
			}
		}
		//결과 리턴
		return valid;
	}

먼저 계속 반복되는 검증 내용을 Util로 만들어보자.

 

//update할때 사용한 예
Map<String, List<String>> errors = new LinkedHashMap<>();
req.setAttribute("errors", errors);
ValidateUtils.validate(buyer, errors, UpdateGroup.class);

일단, validator를 이용하여 검증을 하면 에러 메세지가 나오는데 하나의 데이터에 여러 검증 항목과 메세지가 있을 수 있으므로 키를 String, 값을 List로 하는 Map을 생성한다. 

그리고 미리 만들어 놓은 ValidateUtils의 validate에 조건에 맞는 인수들을 넣어 실행한다. update를 할 것이므로 updateGroup.class를 넣는데, 이렇게 되면 Default그룹인 대상들이랑 updateGroup대상들이 검증된다.

 

💊어노테이션 문법구조 ( 3가지 )

- 마커 어노테이션(속성들이 기본값)

- 멀티벨류 어노테이션(속성이름 생략 불가)

- 싱글벨류 어노테이션(속성의 이름이 value일때만, 생략가능)


Call By Reference / Call By Value

참조 주소 호출 / 값 호출

BuyerVO buyer = new BuyerVO();
req.setAttribute("buyer", buyer);

BuyerVO의 참조 주소를 호출하여 그 주소의 값을 변경할 수 있다.

< 내일 지영씨한테 자세히 더 물어보기 !! >


https://www.tutorialspoint.com/index.htm

 

Online Tutorials Library

1.2 M+ Certificates Delivered

www.tutorialspoint.com

자바 공부하기

 

https://www.baeldung.com/

스프링과 자바 공부하기


오늘의 과제 : 스프링 관련 다이어그램 보기 

📖시퀀스 다이어그램

📖클래스 다이어그램

 

반응형