Date 를 원하는 형식을 변경
String birth 를 Data 타입으로 변경
User.java
package com.jcy.usedhunter;
import java.util.Date;
public class User {
private String id;
private String pwd;
private String name;
private String email;
private Date birth;
private String sns;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Date getBirth() {
return birth;
}
public void setBirth(Date birth) {
this.birth = birth;
}
public String getSns() {
return sns;
}
public void setSns(String sns) {
this.sns = sns;
}
@Override
public String toString() {
return "User [id=" + id + ", pwd=" + pwd + ", name=" + name + ", email=" + email + ", birth=" + birth + ", sns="
+ sns + "]";
}
}
RegisterController.java
save 메서드 파라미터에 BindingResult 추가
BindingResult 추가 시 주의 점은
바인딩할 객체 바로 뒤에 코드를 추가해 주어야 한다.
BindingResult 는 스프링이 제공하는 검증 오류를 보관하는 객체이기 때문에
데이터 유효성 검사를 실패하면 ConstranitViolationException 을 발생시키고
데이터가 유효하지 않은 속성이 있으면 에러 정보를 BindingResult 에 담는다.
정상적인 동작에서는 BindingResult 에 담은 오류 정보를 가지고 컨트롤러를 호출한다.
BindingResult 에 검증 오류를 적용하는 방법은 3가지가 있다.
1. @ModelAttribute 의 객체에 타입 오류 등으로 바인딩이 실패하는 경우 스프링이 FieldError 을 생성해서 BindingResult 에 넣어준다.
2. new FieldError 를 만들어서 직접 넣는다.
3. Vaildator 를 사용(@Valid, @Validated)
BindingResult 메서드 | 설명 |
boolean hasError() | 에러의 유무를 판단한다. |
boolean hasGlobalError() | 글로벌 에러의 유무를 판단한다. |
void addError(ObjectError error) | field, type, value 등의 에러를 출력할 수 있다. |
void rejectValue() | field, errorCode, defaultMessage 등을 받아서 reject 되면 데이터를 남길수 있다. |
BindingResult 파라미터 | 설명 |
objectName | 오류가 발생한 객체의 이름 |
field | 오류 필드 |
rejectedValue | 사용자가 입력한 값(거절된 값) |
bindingFaliure | 타입 오류 같은 바인딩 실패인지, 검증 실패인지 구분 값 |
codes | 메시지 코드 |
arguments | 메시지에서 사용하는 인자 |
defaultMessage | 기본 오류 메시지 |
package com.jcy.usedhunter;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
@Controller
public class RegisterController {
// @RequestMapping("/register/add")
// @RequestMapping(value="/register/save", method= {RequestMethod.GET, RequestMethod.POST})
@GetMapping("/register/add")
public String register() {
return "registerForm";
}
// @RequestMapping(value="/register/save", method=RequestMethod.POST)
@PostMapping("/register/save") // Spring 4.3 부터 추가
public String save(User user, BindingResult result, Model m) throws Exception {
// 1. 유효성 검사
if (!isValid(user)) {
String msg = URLEncoder.encode("id를 잘못입력하셨습니다.", "utf-8");
m.addAttribute("msg", msg);
// return "redirect:/register/add?msg="+msg; // URL 재작성(rewriting)
return "redirect:/register/add";
}
// 2. DB에 신규회원 정보를 저장
return "registerInfo";
}
private boolean isValid(User user) {
// TODO Auto-generated method stub
return true;
}
}
을
회원가입 페이지에서 등록을 해보자
birth 값이 null 로 변환실패다
형식 지정
RegisterController 에 다음 코드 추가
SimpleDateFormat("yyyy-MM-dd") 형식으로 들어온 데이터를
Date 형식으로 출력한다
new CustomDateEditor 의 false 는 빈 공간 유무를 정하는 역할이다.
변환 실패 없이 잘 출력 되었다.
@InitBinder
public void toDate(WebDataBinder binder) {
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
binder.registerCustomEditor(Date.class, new CustomDateEditor(df, false));
}
String 배열을 구분자를 설정해서 입력받기
StringArrayPropertyEditor("#") 을 추가
@InitBinder
public void toDate(WebDataBinder binder) {
SimpleDateFormat df = new SimpleDateFormat("yyyy-mm-dd");
binder.registerCustomEditor(Date.class, new CustomDateEditor(df, false));
binder.registerCustomEditor(String[].class, new StringArrayPropertyEditor("#"));
}
@DateTimeFormat 어노테이션 사용
@DateTimeFormat(pattern="yyyy-MM-dd") 추가
CustomDateEditor 주석 처리
@DateTimeFormat(pattern="yyyy-MM-dd")
private Date birth;
@InitBinder
public void toDate(WebDataBinder binder) {
// SimpleDateFormat df = new SimpleDateFormat("yyyy-mm-dd");
// binder.registerCustomEditor(Date.class, new CustomDateEditor(df, false));
binder.registerCustomEditor(String[].class, new StringArrayPropertyEditor("#"));
}
PropertyEditor
양방향 타입 변환(String -> 타입, 타입 -> String) 특정 타입이나 이름의 필드에 적용가능
디폴트 PropertyEditor - 스프링이 기본적으로 제공
커스텀 PropertyEditor - 사용자가 직접 구현. PropertyEditorSupport 를 상속하면 편리
모든 컨트롤러 내에서의 변환 - WebBindingInitializer 를 구현 후 등록
특정 컨트롤러 내에서의 변환 - 컨트롤러에 @InitBinder 가 붙은 메서드를 작성
Converter 와 ConversionService
package com.jcy.usedhunter;
import org.springframework.core.convert.converter.Converter;
public class StringToStringArrayConverter implements Converter<String, String[]>{
@Override
public String[] convert(String source) {
return source.split("#"); // String -> String[]
}
}
단방향 타입 변환(타입A -> 타입B) PropertyEditor 의 단점을 개선(stateful -> stateless)
디폴트 PropertyEditor - 스프링이 기본적으로 제공
커스텀 PropertyEditor - 사용자가 직접 구현. PropertyEditorSupport 를 상속하면 편리
ConversionService - 타입 변환 서비스를 제공. 여러 Converter 를 등록 가능
WebDataBinder 에 DefaultFormattingConversionService 이 기본 등록
모든 컨트롤러 내에서의 변환 - WebBindingInitializer 를 구현 후 등록
특정 컨트롤러 내에서의 변환 - 컨트롤러에 @InitBinder 가 붙은 메서드를 작성
Formatter
양방향 타입 변환(String -> 타입, 타입 -> String) 바인딩할 필드에 적용 - @NumberFormat, @DateTimeFormat
public interface Formatter<T> extends Printer<T>, Parse<T>{}
public interface Printer<T> {
String print(T object, Locale locale); // Object -> String
}
public interface Parse<T> {
T parse(String text, Locale locale) throws ParesException; // String -> Object
}
@DateTimeFormat(pattern="yyyy-MM-dd")
private Date birth;
@NumberFormat(pattern="###,###")
BigDecimal salary;
'프로젝트 > 중고헌터' 카테고리의 다른 글
중고헌터 - DAO(Data Access Object) 작성 2 (0) | 2022.09.29 |
---|---|
중고헌터 - 데이터 변환과 검증 2 (0) | 2022.09.28 |
중고헌터 - DAO(Data Access Object) 작성 (0) | 2022.09.27 |
중고헌터 - TDD(Test-Driven-Development) (0) | 2022.09.27 |
중고헌터 - STS, DB(MySQL ) 연결 (0) | 2022.09.27 |