교재
스프링 코딩 공작소
https://thebook.io/080266/0472/
스프링 코딩 공작소: 13.3 사용자 정의 애너테이션으로 유효성 검사
더북(TheBook): (주)도서출판 길벗에서 제공하는 IT 도서 열람 서비스입니다.
thebook.io
사용자 정의 애너테이션 유효성 검사
JSR-380 제약 사항의 애너테이션으로는 중복 여부를 체크 할 수 없다.
사용자 정의 제약 사항을 선언할 수 있는 인터페이스 제공
1. 사용자 정의 애너테이션 선언
애너테이션 생성 : 제약 사항 및 구성 속성에 설정하는 @interface를 사용하여 사용자 정의 애너테이션을 생성
constraintValidator 구현체 생성 : 생성한 사용자 정의 애너테이션의 유효성 검사 클래스는 javax.validtaion.contstraintValidator인터페이스의 구현체로 생성한다
2. @Valid를 이용하여 유효성 검사
3. <form:errors> 태그로 오류 메시지 출력
사용자 정의 애너테이션 생성
생성 양식
@Constraint(validatedBy=유효성 검사 클래스.class)
@Target(속성)
@Retention(속성)
@Documented
public @interface 사용자 정의 애너테이션 이름 {
String message() default "출력할 오류 메시지";
Class<?>[] groups() default {};
Class<?>[] payload() default {};
}
필수 속성
message, groups, payload 총 3가지 이다.
속성 | 설명 |
message | 유효성 검사에서 오류가 발생하면 반환되는 기본 메시지입니다. |
groups | 특정 유효성 검사를 그룹으로 설정합니다. |
payload | 사용자가 추가한 정보를 전달하는 값입니다. |
@Documented는 자바 문서에 문서화 여부를 결정
@Retention은 애너테이션의 지속 시간을 설정
▼ 표 13-4 @Retention의 속성
속성 | 설명 |
Source | 소스 코드까지만 유지합니다. 즉, 컴파일하면 해당 애너테이션 정보는 사라집니다. |
Class | 컴파일한 .class 파일에 유지합니다. 즉, 런타임을 할 때 클래스를 메모리로 읽어 오면 해당 정보는 사라집니다. |
Runtime | 런타임을 할 때도 .class 파일에 유지합니다. 사용자 정의 애너테이션을 만들 때 주로 사용합니다. |
@Target은 필드, 메소드, 클래스 등 애너테이션을 작성하는 곳
▼ 표 13-5 @Target의 속성
속성 | 애너테이션 적용 시점 |
TYPE | class, interface, enum |
FIELD | 클래스의 멤버 변수 |
METHOD | 메서드 |
PARAMETER | 메서드 인자 |
CONSTRUCTOR | 생성자 |
LOCAL_VARIABLE | 로컬 변수 |
ANNOTATION_TYPE | 애너테이션 타입에만 적용 |
PACKAGE | 패키지 |
TYPE_PARAMETER | 제네릭 타입 변수(예 MyClass<T>) |
TYPE_USE | 어떤 타입에도 적용(예 extends, implements, 객체 생성할 때 등) |
예제 코드
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.validation.Constraint;
@Constraint(validatedBy=MemberIdValidator.class)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MemberId {
String message() default "아이디는 admin 입니다.";
Class<?>[] groups() default {};
Class<?>[] payload() default {};
}
ConstraintValidator 인터페이스의 구현체 생성
javax.validation.ConstraintValidator인터페이스의 구현체 생성
▼ 표 13-6 ConstraintValidator 인터페이스의 메서드
유형 | 설명 |
void initialize(A constraintAnnotation) | 사용자 정의 애너테이션과 관련 정보를 읽어 초기화합니다. 이때 A는 사용자 정의 제약 사항을 설정합니다. |
boolean isValid(T value, ConstraintValidatorContext context) | 유효성 검사 로직을 수행합니다. value는 유효성 검사를 위한 도메인 클래스의 변수 값이고, context는 제약 사항을 평가하는 컨텍스트입니다. |
예제 코드
package com.springmvc.chap13;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
public class MemberIdValidator implements ConstraintValidator<MemberId, String> {
private Member member;
public void initialize(MemberId constraintAnnotation) {
}
public boolean isValid(String value, ConstraintValidatorContext context) {
if (value.equals("admin")) {
return false;
}
return true;
}
}
MemberIdValidator클래스를 사용하는 사용자 정의 애너테이션을 지정
도메인 클래스 Member의 멤버 변수 타입을 설정
initalize()메소드 @MemberId가 속성 값이 없기 때문에 구현 부분없이 메소드 선언만 한다.
isValid()메소드는 유효성 검사하면서 true, false값을 리턴
1. messages.properties 파일에 다음 메시지를 추가합니다.
<messages.properties>
BookId.NewBook.bookId = 도서ID가 이미 존재합니다.
2. Book 클래스에 bookId 속성에 대해 사용자 정의 제약 사항의 애너테이션을 선언합니다.
<Book.java>
package com.springmvc.domain;
...
import com.springmvc.validator.BookId;
public class Book {
@BookId ➊
@Pattern(regexp="ISBN[1-9]+")
private String bookId;
...
}
BookId필드 선언
3. BookMarket/src/main/Java 폴더에 com.springmvc.validator 패키지를 생성합니다. 이 패키지에 BookId 클래스를 생성하고 다음 내용을 작성합니다.
<BookId>
package com.springmvc.validator;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.Retention;
import javax.validation.Constraint;
@Constraint(validatedBy=BookIdValidator.class)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface BookId {
String message() default "";
Class<?>[] groups() default {};
Class<?>[] payload() default {};
}
사용자 정의 애너테이션 @BookId는 METHOD, FIELD, ANNOTATION_TYPE이 정의
@BookId는 message(), groups(), payload가 필수로 필요하다
@Constraint(validatedBy=BookidValidator.class)를 참고? 한다.
4. com.springmvc.validator 패키지에 BookIdValidator 클래스를 생성하고 다음 내용을 작성합니다.
<BookIdValidator.java>
package com.springmvc.validator;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import org.springframework.beans.factory.annotation.Autowired;
import com.springmvc.exception.BookIdException;
import com.springmvc.service.BookService;
import com.springmvc.domain.Book;
public class BookIdValidator implements ConstraintValidator<BookId, String> {
@Autowired
private BookService bookService;
public void initialize(BookId constraintAnnotation) { // @BookId 정보 초기화 메서드
}
public boolean isValid(String value, ConstraintValidatorContext context) {
Book book;
try {
book = bookService.getBookById(value);
} catch (BookIdException e) {
return true;
}
if (book! = null) {
return false;
}
return true;
}
}
initialize를 통해서 BookId의 관련 정보를 읽어 초기화 작업 수행
isValid() 메소드는 도메인 클래스 Book의 bookid 속성 값을 읽어 유효성 검사
bookService.getBookByid(value) :
입력했던 값을 getBookById함수를 통해서 값을 확인
-> 입력 값(ID)이 없다면 null
try-catch문으로 확인한 뒤에 true/false값으로 리턴한다.
5. com.springmvc.controller 패키지의 BookController 클래스에서 유효성 검사를 위해 submitAddNewBook() 메서드의 매개변수 중에서 커맨드 객체에 @Valid가 선언되어 있는지, 오류 처리 내용이 작성되어 있는지 확인합니다.
=> 컨트롤러에서 유효성 검사 한 뒤에 view페이지 리턴 하기
BookController.java
package com.springmvc.controller;
...
import javax.validation.Valid;
@Controller
@RequestMapping("/books")
public class BookController {
...
@PostMapping("/add")
public String submitAddNewBook(@Valid @ModelAttribute("NewBook") Book book, BindingResult result) {
if (result.hasErrors()) {
return "addBook";
}
MultipartFile bookImage = book.getBookImage();
...
}
...
}
6. addBook.jsp 파일에서 유효성 검사에 따른 오류 메시지를 출력할 수 있도록 다음 내용이 작성되어 있는지 확인합니다.
-> <form > 태그 삽입
<%@ page contentType="text/html; charset=utf-8" %>
...
<div class="col-sm-3">
<form:input path="bookId" class="form-control"/>
</div>
<div class="col-sm-6">
<form:errors path="bookId" cssClass="text-danger"/>
</div>
...
7. 서버 실행하고 값을 입력했을 때 오류 메시지가 나오는 지 확인하기
위 사진처럼
"도서 ID가 이미 존재합니다"
라는 오류 메시지가 나온다
13.4 validator 인터페이스로 유효성검사
인터페이스의 구현체 생성
@InitBinder 선언 메소드 추가
@Valid를 이용한 유효성 검사
<Form:errors>태그로 오류 메시지 출력
위 사진 공부하기
Validator 인터페이스의 구현체 생성
▼ 표 13-7 Validator 인터페이스의 메서드
메서드 | 설명 |
boolean supports(Class<?> clazz) | 주어진 객체(class)에 대해 유효성 검사를 수행할 수 있는지 검사할 목적으로 사용됩니다. |
void validate(Object target, Errors errors) | 주어진 객체(target)에 대해 유효성 검사를 수행하고 오류가 발생하면 주어진 Errors 타입의 errors 객체에 오류 관련 정보를 저장합니다. |
Errors : org.springframework.validation 패키지에서 제공
실습 실습
실습이 다임!
'IoT 빅데이터 응용 교육 과정_하계' 카테고리의 다른 글
[IoT 빅데이터 응용 교육 과정]23.07.12 스프링 코딩 공작소 14장 RESTful 방식 (0) | 2023.07.12 |
---|---|
[IoT 빅데이터 응용 교육 과정]23.07.11 14장 장바구니 만들기 (0) | 2023.07.11 |
[IoT 빅데이터 응용 교육과정] 23.07.06 13장 유효성 검사 (0) | 2023.07.06 |
[IoT 빅데이터 응용 교육 과정] 23.07.06 12장 다국어 처리 (0) | 2023.07.06 |
[IoT 빅데이터 응용 교육 과정] 23.07.05 11장 로그 기록 (0) | 2023.07.05 |