Table of Contents
Spring Boot – JSTL form validation
Spring Boot 기반으로 JSTL form validation 을 하는 방법을 정리합니다.
의존성 추가
dependencies {
implementation 'org.apache.tomcat.embed:tomcat-embed-jasper'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'javax.servlet:jstl'
}
Form 클래스
DTO 객체와는 별도로 Form 객체가 필요합니다.
@Getter
@Setter
@NoArgsConstructor
public class ItemForm {
private Long itemId;
private Long companyId;
@NotNull(message = "고객사ID 를 입력하세요.")
private Long partnerId;
private String companyName;
private String partnerName;
@NotBlank(message = "상품명을 입력하세요.")
private String itemName;
private String itemOptionName;
private Float weight;
}
Controller
itemForm
은 ItemForm
와 대응해야 합니다.
폼 클래스명에서 첫글자만 소문자로 변경해서 사용합니다.
이름이 다른 경우 오류 메시지가 표시되지 않습니다.
BindingResult
는 폼 클래스 바로 다음에 위치해야 합니다.
오류가 있는 경우 폼 JSP 로 다시 이동시켜 줍니다.
@Controller
@RequiredArgsConstructor
public class ItemController {
@GetMapping("/item/create")
public String create(ModelMap model) {
model.addAttribute("itemForm", new ItemForm());
return "/itemModify";
}
@PostMapping("/item/create")
public String doCreate(ModelMap model, @Valid ItemForm form, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
// List<ObjectError> list = bindingResult.getAllErrors();
// for (ObjectError error : list) {
// System.out.println(error);
// }
model.addAttribute("itemForm", form);
return "/itemModify";
}
service.create(form);
return "redirect:/item/";
}
JSP
오류가 있는 경우 표시해 줍니다.
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%--@elvariable id="itemForm" type="kr.pe.skyer9.warehouseweb.external.dto.ItemForm"--%>
<form:form id="frm" name="frm" modelAttribute="itemForm">
<form:input path="itemName" />
<form:errors path="itemName" />
</form:form>
NumberFormatException
NumberFormatException 의 경우 디폴트 오류 메시지가 나옵니다.
Failed to convert property value of type java.lang.String to required type java.lang.Float for property sizeWidth; nested exception is java.lang.NumberFormatException: For input string: "aa"
오류를 한국어로 바꾸기 위해 다음 설정을 해줍니다.
application.yaml
spring:
messages:
basename: messages
resources/messages.properties
# typeMismatch.itemForm.sizeWidth=가로 사이즈는 숫자만 입력해야 합니다.
typeMismatch.java.lang.Float=숫자로 입력해야 합니다.
typeMismatch.폼이름.필드명
이 있는 경우 그 오류메시지가 표시됩니다.
대응하는 코드가 없는 경우 typeMismatch.java.lang.Float
와 같이 범용 오류메시지가 표시됩니다.
Form 클래스 분리
입력용 클래스 자체를 분리하는 것이 결과적으로는 제일 간단합니다.
public class UserCreateForm {
}
public class UserModifyForm {
}
public class UserChangePasswordForm {
}
Custom Validator
복합 조건과 같은 특수한 체크를 위해 Custom Validator 를 생성할 수 있습니다.
import org.springframework.validation.Validator;
@Component
public class UserCreateValidator implements Validator {
@Override
public boolean supports(Class<?> clazz) {
return UserCreateForm.class.isAssignableFrom(clazz);
}
@Override
public void validate(Object target, Errors errors) {
UserCreateForm dto = (UserCreateForm) target;
if (ObjectUtils.isEmpty(dto.getCompanyId())) {
errors.rejectValue("companyId", "required", "업체ID 를 입력하세요.");
}
if (!Objects.equals(dto.getUserLoginPassword(), dto.getUserLoginPassword2())) {
errors.rejectValue("userLoginPassword2", "passwordNotMatch", "비밀번호가 일치하지 않습니다.");
}
}
}
userCreateForm 은 검증할 클래스 UserCreateForm 에서 첫글자만 소문자로 변경한 것입니다.
@Controller
@RequiredArgsConstructor
public class AdminUserController {
private final UserService service;
private final UserCreateValidator userCreateValidator;
@InitBinder("userCreateForm")
public void initBinder(WebDataBinder webDataBinder) {
webDataBinder.addValidators(userCreateValidator);
}
@PostMapping("/admin/user/create")
public String doCreate(@LoginInfo LoginInfoDto loginInfo, ModelMap model, @Valid UserCreateForm dto, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
setAttribute(loginInfo, model);
model.addAttribute("userCreateForm", dto);
return "/admin/userModify";
}
service.create(loginInfo, dto);
return "redirect:/admin/user/";
}
}