티스토리 뷰

728x90

0. Date를 변환하고 싶은 경우는 아래 링크를 참고한다.

 

 

Spring Basic : Form을 Date, LocalDate로 변환하기

0. Form에서 전송한 데이터를 Date로 변환이 필요한 경우가 많다. 워낙 다양하기 때문에 생각 날 때마다 추가할 예정 form에서 Parmater로 받아 Controller에서 Date로 변환하는 방법 (LocalDate에도 사용가능�

kogle.tistory.com

 

1. InitBinder는 스프링 MVC가 나오면서 부터 지원한 오래된 기술이다.

 

2. 현재는 나중에 나온 Converter를 많이 사용하기는 하지만 여전히 유용한 기술이다.

 

3. @InitBinder의 목적은 View에서 입력한 Form에 객체정보를 Controller의 객체로 변환할 때 

  3-1 적절한 변환이 필요한 경우 전처리를 하기 위해서 사용 된다.

 

4. 사용을 위해서는 우선 어떤 수정작업을 할지를 등록을 해야 한다.

  4-1 데이터 타입 변환이 필요한 Controller 클래스에서 정의를 하고

  4-2 내부에는 form에 지정된 name 속성과 타입에 따라서 어떻게 변환할지를 설정해야 한다.

    4-2-1 아래의 코드는 문자열이 들어온  경우 공백의 경우는 삭제하고 공백만 있을 경우는 null을 반환한다.

 

  @InitBinder
  public void initBinder(WebDataBinder dataBinder) {
    StringTrimmerEditor stringTimmerEditor = new StringTrimmerEditor(true);
    dataBinder.registerCustomEditor(String.class, stringTimmerEditor);
  }
  

 

    4-2-2 아래의 코드의 경우 변환 대상 Date타입의 속성을 지정된 타입으로 변환하여 매핑되도록 하고 있다.

 

  @InitBinder
  public void initBinder(WebDataBinder binder) {
    log.info("initBinder in TodoController \n");
    SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
    binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false));
  }

 

    4-2-3 위의 두 예제는 registerCustomEditor에 등록할 때 타입만 사용하고 있지만

      4-2-3-1 두번째인자로 name 속성값을 줄 수 있다. 이 경우 명확해 진다.

 

    4-2-4 위의 Date format과 관련된 예제는 결국 표출부에서 어떤 형식으로 표출되는지도 중요하다.

      4-2-4-1 jsp의 경우는 fmt 테그를 사용하여 적절한 형태로 표현하게 된다. 아래와 같은 형식이다.

 

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>

<table class="table table-striped">
  <caption>${ username }'s' todos are</caption>
  <thead>
    <tr>
      <th>Description</th>
      <th>Target Date</th>
      <th>Is it Done?</th>
      <th></th>
      <th></th>
    </tr>
  </thead>
  <tbody>
    <c:forEach items="${todos}" var="todo">
      <tr>
        <td>${todo.desc}</td>
        <!-- <td>${todo.targetDate}</ud> -->
        <td>
          <fmt:formatDate value="${todo.targetDate}" pattern="dd/MM/yyyy" />
        </td>
        <td>${todo.done}</td>
        <td><a type="button" class="btn btn-success" href="/update-todo?id=${todo.id}">Update</a></td>
        <td><a type="button" class="btn btn-warning" href="/delete-todo?id=${todo.id}">Delete</a></td>
      </tr>
    </c:forEach>
  </tbody>

 

  4-3 Player가 Skill 리스트를 가지고 있는 경우에 어떻게 skill id로 Skill 리스트를 만드는 예제

    4-3-1 CustomeCollectionEditor는 collection을 생성하는데 편리한 클래스이다.

    4-3-2 이 클래스에는 두개의 편리한 함수가 있는데, createCollection과 convertElement 두개가 있다.

      4-3-2-1 아래의 예제의 경우는 createCollection이 사실 더 적합하지만 간단하게 하려면 convertElement가 낫다.

      4-3-2-2 List에는 Long 타입의 id값들이 들어있는데 convertElement에서 이 값들을 받아서 cast하여 값을 가져온다.

      4-3-2-3 return 값은 목적인 Skill Set에 들어갈 Skill 객체가 된다.

 

  @InitBinder
  public void initBinder(WebDataBinder binder) {
    binder.registerCustomEditor(List.class, "skills", new CustomCollectionEditor(List.class) {

      protected Object convertElement(Object element) {
        log.info("convertElement in CustomeCollectionEditor " + element.toString());
        if (element != null) {
          Long skillId = Long.parseLong(element.toString());
          Skill skill = skillRepository.findById(skillId).get();

          log.info("convertElement in CustomCollectionEditor :: " + skill);
          return skill;
        }
        return element;
      }
    });
  }

 

  4-4 위에서 사용한 것은 모두 org.springframework.beans.propertyeditors 패키지가 제공하는 것들이다.

    4-4-1 이것들만으로 사실 구현하는데 충분하다. 굳이 아래 5번 방식으로 만들 필요는 없다.

 

5. 가장 자유도가 높은 구현은 PropertyEditorSupport를 상속하여 Custom Class를 만드는 것이다. 

  5-1 사용법은 완전동일하다. 단순히 외부에서 클래스를 정의한 것만 차이가 난다.

    5-1-1 즉 binder.registerCustomEditor(결과 타입, 변환 클래스) 로 등록하는 것이 동일하다는 의미이다.

 

6. 위의 Player예제를 Converter로 구현하면 아래와 같다. 이 경우는 별도의 클래스를 반드시 만들어야 한다.

 

Component
class LongToSkillConverter implements Converter<String, Skill> {

  @Autowired
  private SkillRepository skillRepository;

  @Override
  public Skill convert(String id) {
    return this.skillRepository.findById(Long.valueOf(id)).get();
  }
}
728x90
댓글