@Controller
또는 @ControllerAdvice
클래스는 @InitBinder
메서드를 사용하여 WebDataBinder
인스턴스를 초기화할 수 있으며, 이는 다음을 수행할 수 있습니다.
요청 매개변수를 모델 객체에 바인딩합니다.
요청 값을 문자열에서 객체 속성 유형으로 변환합니다.
HTML 양식을 렌더링할 때 모델 객체 속성의 형식을 문자열로 지정합니다.
@Controller
에서 DataBinder
사용자 정의는 컨트롤러 내에서 로컬로 적용되거나 annotation을 통해 이름으로 참조되는 특정 모델 속성에도 적용됩니다. @ControllerAdvice
에서 사용자 정의는 컨트롤러 전체 또는 일부에 적용될 수 있습니다.
유형 변환을 위해 DataBinder
에 PropertyEditor
, Converter
및 Formatter
구성 요소를 등록할 수 있습니다. 또는 MVC 구성을 사용하여 전역적으로 공유되는 FormattingConversionService
에 Converter
및 Formatter
구성 요소를 등록할 수 있습니다.
@InitBinder
메소드는 @ModelAttribute
를 제외하고 @RequestMapping
메소드와 동일한 인수를 많이 가질 수 있습니다. 일반적으로 이러한 메서드에는 WebDataBinder
인수(등록용)와 void
반환 값이 있습니다. 예를 들면 다음과 같습니다.
@Controller
public class FormController {
@InitBinder // (1)
public void initBinder(WebDataBinder binder) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
dateFormat.setLenient(false);
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false));
}
// ...
}
(1) @InitBinder
메소드를 정의합니다.
또는 공유 FormattingConversionService
를 통해 Formatter
기반 설정을 사용하는 경우 다음 예제와 같이 동일한 접근 방식을 재사용하고 컨트롤러별 Formatter
구현을 등록할 수 있습니다.
@Controller
public class FormController {
@InitBinder // (1)
protected void initBinder(WebDataBinder binder) {
binder.addCustomFormatter(new DateFormatter("yyyy-MM-dd"));
}
// ...
}
(1) 사용자 정의 포맷터에 @InitBinder
메소드를 정의합니다.
웹 요청에 대한 데이터 바인딩에는 요청 매개변수를 모델 개체에 바인딩하는 작업이 포함됩니다. 기본적으로 요청 매개 변수는 모델 개체의 모든 공개 속성에 바인딩될 수 있습니다. 이는 악의적인 클라이언트가 모델 개체 그래프에 존재하지만 설정될 것으로 예상되지 않는 속성에 대한 추가 값을 제공할 수 있음을 의미합니다. 이것이 모델 객체 설계에 세심한 고려가 필요한 이유입니다.
[Tip]
모델 개체 및 해당 중첩 개체 그래프는 명령 개체, 양식 지원 개체 또는 POJO(Plain Old Java 개체)라고도 합니다.
웹 데이터 바인딩을 위해 JPA 또는 Hibernate 엔터티와 같은 도메인 모델을 노출하는 대신 전용 모델 개체를 사용하는 것이 좋습니다. 예를 들어 이메일 주소를 변경하는 양식에서 입력에 필요한 속성만 선언하는 ChangeEmailForm
모델 객체를 생성합니다.
public class ChangeEmailForm {
private String oldEmailAddress;
private String newEmailAddress;
public void setOldEmailAddress(String oldEmailAddress) {
this.oldEmailAddress = oldEmailAddress;
}
public String getOldEmailAddress() {
return this.oldEmailAddress;
}
public void setNewEmailAddress(String newEmailAddress) {
this.newEmailAddress = newEmailAddress;
}
public String getNewEmailAddress() {
return this.newEmailAddress;
}
}
또 다른 좋은 방법은 생성자 인수에 필요한 요청 매개변수만 사용하고 다른 입력은 무시하는 생성자 바인딩을 적용하는 것입니다. 이는 일치하는 속성이 있는 모든 요청 매개변수를 기본적으로 바인딩하는 속성 바인딩과 대조됩니다.
전용 모델 객체나 생성자 바인딩 모두 충분하지 않고 속성 바인딩을 사용해야 하는 경우 예기치 않은 속성이 설정되는 것을 방지하기 위해 WebDataBinder
에 allowedFields
패턴(대소문자 구분)을 등록하는 것이 좋습니다. 예를 들어:
@Controller
public class ChangeEmailController {
@InitBinder
void initBinder(WebDataBinder binder) {
binder.setAllowedFields("oldEmailAddress", "newEmailAddress");
}
// @RequestMapping methods, etc.
}
disallowedFields
패턴을 등록할 수도 있습니다(대소문자 구분 안 함). 그러나 "허용" 구성은 "허용되지 않음"보다 더 명확하고 실수할 가능성이 적기 때문에 선호됩니다.
기본적으로 생성자와 속성 바인딩이 모두 사용됩니다. 생성자 바인딩만 사용하려는 경우 컨트롤러 내에서 로컬로 또는 @ControllerAdvice
를 통해 전역적으로 @InitBinder
메서드를 통해 WebDataBinder
에 declarativeBinding
플래그를 설정할 수 있습니다. 이 플래그를 켜면 생성자 바인딩만 사용되며 allowedFields
패턴이 구성되지 않은 한 속성 바인딩은 사용되지 않습니다. 예를 들어:
@Controller
public class MyController {
@InitBinder
void initBinder(WebDataBinder binder) {
binder.setDeclarativeBinding(true);
}
// @RequestMapping methods, etc.
}