지금까지는 회원가입이나 강의등록시 올바른 데이터인지 검증하지 않았습니다.
사실 기능은 몇개 넣었는데 잘 모르고 사용했습니다.
Validation을 학습하고 실무에서 많이쓰는 방법으로 제 프로젝트에 적용해 보겠습니다.
2021.10.10 - [Web/MVC2] - EP3. 검증1 - Validation
EP3. 검증1 - Validation
지금까지 만든 웹 어플리케이션은 사용자가 입력하는 모든 상황을 대비할 수 없습니다. 예를들어, 사용자가 가격을 입력하는 곳에 알파벳을 입력하거나 그냥 입력 창에 공백을 넣게되면 에러페
ksabs.tistory.com
2021.10.14 - [Web/MVC2] - EP4. 검증2 - Bean Validation
EP4. 검증2 - Bean Validation
EP3. 검증1 에서 검증로직 구현은 개발자가 직접 작성했습니다. 사실 이 검증 로직은 여러 프로젝트에서 공통적으로 쓰이는 로직입니다. 그래서 검증 로직을 모든 프로젝트에서 공통적으로 쓰일
ksabs.tistory.com
검증 적용 계획
회원가입
필드 | 검증 |
이름 | @NotBlank |
나이 | @NotNull |
성별 | @NotNull -> enum 타입은 NotNull로 판단한다. |
직업 | @NotBlank |
강의등록
필드 | 검증 |
강의제목 | @NotBlank |
강의자이름 | @NotBlank |
강의 내용 소개 | 필요없음 |
강의 대표 사진 | 이미지파일만 -> 추후 파일업로드 수정시 반영 |
강의 사이트 이름 | @NotBlank |
강의 사이트 주소 | @URL -> URI타입에 적용불가 -> String타입에 적용후 변환필요 |
Bean Validation 적용순서
- implementation 'org.springframework.boot:spring-boot-starter-validation' 추가
- Form 객체에서 검증 어노테이션 적용하기
- 컨트롤러에서 @ModelAttribute 앞에 @Validated 넣어주고 뒤에 BindingResult 넣어주기
- 오브젝트 오류검증은 컨트롤러 안에서 자바코드로 넣어주기
- templates 수정하기
1. 의존성 추가
저번에 따라친게 있어서 적용되어있습니다.
dependencies {
...
implementation 'org.springframework.boot:spring-boot-starter-validation'
...
}
2. Form객체에서 검증 어노테이션 적용하기
MemberForm
package dongho.classflix.controller;
import dongho.classflix.domain.Gender;
import lombok.Getter;
import lombok.Setter;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
@Getter
@Setter
public class MemberForm {
@NotBlank(message = "회원 이름을 입력해 주세요.")
private String name;
@NotNull(message = "나이를 입력해 주세요.")
private Integer age;
@NotNull(message = "성별을 선택해 주세요.")
private Gender gender;
@NotBlank(message = "직업을 입력해 주세요.")
private String career;
}
LectureForm
@URL로 uri를 검증하기 위해서는 String타입이어야 합니다.
그래서 form객체에서는 uri를 String타입으로 선언해 검증한 후, 실제 lecture객체에 넣어줄 때는 convertStrToUri 메서드를 이용해 URI타입으로 넣어주도록 구현했습니다.
package dongho.classflix.controller;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.validator.constraints.URL;
import org.springframework.web.multipart.MultipartFile;
import javax.validation.constraints.NotBlank;
import java.net.URI;
@Getter
@Setter
public class LectureForm {
@NotBlank(message = "강의 제목을 입력해 주세요.")
private String lectureName;
@NotBlank(message = "강의자 이름을 입력해 주세요.")
private String teacherName;
private String content;
private MultipartFile image;
@NotBlank(message = "강의가 올려져 있는 사이트를 입력해 주세요.")
private String siteName;
@NotBlank(message = "URL을 입력해주세요.")
@URL(message = "URL을 제대로 입력했는지 확인해 주세요.")
private String uri;
URI convertStrToUri(String url) {
return URI.create(url);
}
}
3. 컨트롤러에서 @ModelAttribute 앞에 @Validated 넣어주고 뒤에 BindingResult 넣어주기
4. 오브젝트 오류는 없어서 안넣었습니다.
5. templates 수정하기
memberForm.html
성별오류는 bord를 빨간색으로 만들 부분이 없기 때문에 빨간글자만 추가되도록 바꿨습니다.
<form role="form" action="/members/new" th:object="${memberForm}" method="post">
<div class="form-group">
<label th:for="name" th:text="#{label.member.name}">이름</label>
<input type="text" th:field="*{name}"
th:errorclass="fieldError" class="form-control" placeholder="이름을 입력하세요">
<div class="fieldError" th:errors="*{name}">
이름 오류
</div>
</div>
<div class="form-group">
<label th:for="age" th:text="#{label.member.age}">나이</label>
<input type="text" th:field="*{age}"
th:errorclass="fieldError" class="form-control" placeholder="나이를 입력하세요">
<div class="fieldError" th:errors="*{age}">
나이 오류
</div>
</div>
<div>
<div><b th:text="#{label.member.gender}">성별</b></div>
<div class="radio" th:each="gender : ${genderTypes}">
<input type="radio" th:field="*{gender}" th:value="${gender.name()}">
<label th:for="${#ids.prev('gender')}" th:text="${gender.description}"></label>
</div>
<div class="fieldError" th:errors="*{gender}">
성별 오류
</div>
</div>
<div class="form-group">
<label th:for="career" th:text="#{label.member.career}">직업</label>
<input type="text" th:field="*{career}"
th:errorclass="fieldError" class="form-control" placeholder="이름을 입력하세요">
<div class="fieldError" th:errors="*{career}">
직업 오류
</div>
</div>
<div class="text-center">
<button type="submit" class="btn btn-primary" th:text="#{button.save}">등록하기</button>
</div>
</form>
lectureForm.html
URL검증은 @URL을 이용하려면 필드의 타입이 String이어야 했습니다.
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head th:replace="fragments/header :: header" />
<style>
.fieldError {
border-color: #bd2130;
color: #bd2130;
}
.container-center {
max-width: 560px;
}
</style>
<body>
<div th:replace="fragments/bodyHeader :: bodyHeader"/>
<div class="container container-center">
<div class="page-header">
<h1 class="text-center" th:text="#{page.addLecture}">강의등록</h1>
</div>
<form role="form" action="/lectures/new" th:object="${lectureForm}"
method="post", enctype="multipart/form-data">
<div class="form-group">
<label th:for="lectureName" th:text="#{label.lecture.name}">강의제목</label>
<input type="text" th:field="*{lectureName}"
th:errorclass="fieldError" class="form-control" placeholder="강의제목을 입력하세요.">
<div class="fieldError" th:errors="*{lectureName}">
강의명 오류
</div>
</div>
<div class="form-group">
<label th:for="teacherName" th:text="#{label.lecture.teacher}">강의자 이름</label>
<input type="text" th:field="*{teacherName}"
th:errorclass="fieldError" class="form-control" placeholder="강의자를 입력하세요.">
<div class="fieldError" th:errors="*{teacherName}">
강의자명 오류
</div>
</div>
<div class="form-group">
<label th:for="content" th:text="#{label.lecture.content}">강의 내용 소개</label>
<textarea th:field="*{content}" class="form-control" placeholder="강의내용을 입력하세요"> </textarea>
</div>
<div class="form-group">
<label th:for="representImage" th:text="#{label.lecture.representPicture}">강의 대표사진 업로드</label>
<input type="file" multiple="true" th:field="*{image}" accept="image/*" class="form-control" placeholder="강의 대표사진을 업로드해주세요">
</div>
<div class="form-group">
<label th:for="siteName" th:text="#{label.lecture.siteName}">강의 사이트 이름</label>
<input type="text" th:field="*{siteName}"
th:errorclass="fieldError" class="form-control" placeholder="강의 사이트의 이름을 입력해주세요.">
<div class="fieldError" th:errors="*{siteName}">
강의 사이트명 오류
</div>
</div>
<div class="form-group">
<label th:for="uri" th:text="#{label.lecture.siteUrl}">강의 사이트 주소</label>
<input type="text" th:field="*{uri}"
th:errorclass="fieldError" class="form-control" placeholder="강의 사이트의 주소를 입력해주세요.">
<div class="fieldError" th:errors="*{uri}">
강의 사이트 url 오류
</div>
</div>
<div class="text-center">
<button type="submit" class="btn btn-primary" th:text="#{button.save}">등록하기</button>
</div>
</form>
<br/>
</div> <!-- /container -->
<div th:replace="fragments/footer :: footer" />
</body>
</html>
'Project > ClassFlix' 카테고리의 다른 글
[Class Flix] EP 20. messages 적용 (0) | 2021.08.30 |
---|---|
[Class Flix] EP 19. 타임리프 리팩토링 (0) | 2021.08.09 |
[ClassFlix] EP 18. QueryDSL 도입 (검색기능) (0) | 2021.07.23 |
[ClassFlix] EP 17. QueryDSL 도입 (페이징, 정렬) (0) | 2021.07.14 |
[ClassFlix] EP 16. 리팩토링 계획 (0) | 2021.06.17 |