티스토리 뷰
- @InitBinder
스프링프레임워크에서의 바인딩이란 모델 클래스(오브젝트)의 프로퍼티(메서드 set)에 값을 넣는 것을 말한다.
두가지 바인딩을 제공하는데..
첫 번째는 xml설정 파일을 통해 <bean>의 <property>에 값을 넣는 것이다. 하지만 xml자체가 문자열이기 때문에 해당 빈클래스의 property값이 기본형 타입이나 String이라면 괜찮지만 그 외의 타입이라면 바인딩 하기전에 적절한 변환이 필요하다.
두번째는 Http를 통해 전달되는 헤더, 쿠키, 파라미터 같은 정보인데 이런 것들도 전부 문자열로 전달되는 값이다. 해서 이 경우에도 특정 타입으로 매칭시키려면 바인딩 과정 중에 적절한 변환이 필요하다.
컨트롤러 메서드에서는 @RequestParam, @PathVariable, @ModelAttribute등이 메서드의 매개변수에 지정되어 있다면 WebDataBinder라는 인스턴스를 만든다.
WebDataBinder는 여러가지 기능을 제공하고, 그 중에서도 요청 파라미터의 문자열을 컨트롤러 메서드의 매개변수에 지정된 변수 타입과 같은 형태로 변환하는 기능도 포함되어 있다.
WebDataBinder의 바인딩 적용대상은 다음과 같다.
@RequestParam파라미터
@RequestHeader파라미터
@CookieValue파라미터
@PathVariable파라미터
@ModelAttribute파라미터
이 변환작업을 입맛에 맞게 수행하려면 하려면 PropertyEditor라는 인터페이스의 도움이 필요하다.
PropertyEditor의 도움을 받아서 오브젝트 클래스를 만들고 나면 그 다음에는 WebDataBinder에 등록이 필요하다.
PropertyEditor인터페이스를 구현하는 클래스인 PropertyEditorSupport를 이용해서 클래스를 작성해 보겠다.
public class CustomPropertyEditor extends PropertyEditorSupport { @Override public void setAsText(String text) throws java.lang.IllegalArgumentException { System.out.println("text pre : "+text); char[] cArr = text.toLowerCase().toCharArray(); boolean b = true; for(char c : cArr){ if(c > 'a' && c < 'z'){ System.out.println("문자열 숫자로 형변환 목함"); b = false; break; } } if(b == false){ this.setValue(text); return; } int i = Integer.parseInt(text); if(i > 19){ i=19; } System.out.println("text next : "+i); this.setValue(i); } /*@Override public String getAsText() { return "ss"; }*/ }
위의 오버라이딩 메서드인 setAsText를 요청 파라미터 문자열이 거치게 되면 해당 클래스(PropertyEditorSupport)의 인스턴스 변수인 Object 타입인 변수명 value에 파라미터가 저장되고, 이 value가 해당 모델 클래스(Student)에 저장된다.
테스트 해 볼 대상이 되는 POJO스타일 모델 오브젝트이다.
public class Student { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
다음은 @InitBinder어노테이션이 적용된 메서드와 테스트 해 볼 컨트롤러 메서드이다.
@InitBinder public void initBinding(WebDataBinder b){ CustomPropertyEditor cpe = new CustomPropertyEditor(); b.registerCustomEditor(String.class, cpe); b.registerCustomEditor(int.class, cpe); //b.registerCustomEditor(int.class, "age", new CustomPropertyEditor()); //(필드의 타입, 적용할 변수 이름, 프로퍼티에디터 구현체 오브젝트) } @RequestMapping(value="testBinder") public String testBinder(@ModelAttribute Student student){ System.out.println("name >>> "+student.getName()); System.out.println("age >>> "+student.getAge()); return "/home"; }
@InitBinder메서드는 요청 파라미터를 바인딩 하기전에 자동으로 호출되며, 이곳에 registerCustomEditor메서드를 이용해서 WebDataBinder에 직접 정의한 PropertyEditor구현 클래스를 등록할 수 있다.
*타입에 따라서 적용되는 프로퍼티 에디터 등록방식(Student의 String타입과 int타입에 CustomPropertyEditor가 적용됨)
CustomPropertyEditor cpe = new CustomPropertyEditor();
b.registerCustomEditor(String.class, cpe);
b.registerCustomEditor(int.class, cpe);
*특정 필드의 프로퍼티에만 프로퍼티 에디터 등록방식(Student의 int타입이고 필드명이 age인 프로퍼티에 CustomPropertyEditor 적용)
b.registerCustomEditor(int.class, "age", new CustomPropertyEditor());
@InitBinder메서드는 사용자의 요청 파라미터를 컨트롤러 메서드에 던져주기 전에 호출 된다. 그리고 @InitBinder메서드에서는 PropertyEditorSupport클래스를 상속받는 클래스의 인스턴스를 생성해서 파라미터의 적절한 변환을 위해 에디터를 등록해야 한다.
여기에서 PropertyEditorSupport클래스를 상속받는 클래스의 인스턴스를 생성해야 하기 때문에 new를 이용하여 매번 인스턴스를 생성함을 알 수 있을 것이다.
이렇게 생각해서 코딩하는 사람들도 있을 것이다.
"new를 이용해 객체를 매번 새로 생성하는 대신에 해당 프로퍼티 에디터를 스프링 컨텍스트에 싱글톤빈으로 등록해 놓고 사용하면 안될까?"
결론적으로는 안된다.
'SPRING > 정리' 카테고리의 다른 글
Spring 빈의 등록 방법 (0) | 2016.08.11 |
---|---|
[SpringSecurity] 스프링 시큐리티 jquery ajax사용시 로그인 하게 하기 (1) | 2016.07.29 |
JUnit 테스트 (0) | 2016.04.22 |
[spring] google recapcha 자동가입방지 (0) | 2016.03.24 |
@ControllerAdvice로 전역 예외 관리하기 (0) | 2016.01.15 |