データバインド抽象(1):PropertyEditor


1. PropertyEditor
DataBinder
org.springframework.validation.DataBinder
技術的観点:Property値をターゲットオブジェクトに設定する機能
ユーザーの観点:ユーザー入力値をアプリケーションドメインモデルに動的に変換する機能.入力値の多くは「文字列」で、オブジェクトが持つint、long、Boolean、Dateなどのドメインタイプに変換したり、イベント、Bookなどのドメインに入れたりすることができます.
PropertyEditor
  • スプリング3.0の前に、DataBinderは変換インタフェース
  • を使用する.
  • 「安全ではありません」(ステータス情報を保存しているので、モノクロで空にして登録して使用すると...)
  • オブジェクトとStringオブジェクトの間でのみ変換でき、使用範囲は限られています.(でも、ほとんどの場合そうなので、ずっとよく使っていますので、気をつけて...)
  • ドメインクラス
    package com.example.spring9;
    
    public class Event {
        private Integer id;
        private String title;
    
        public Event(Integer id){
            this.id = id;
        }
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getTitle() {
            return title;
        }
    
        public void setTitle(String title) {
            this.title = title;
        }
    
        @Override
        public String toString() {
            return "Event{" +
                    "id=" + id +
                    ", title='" + title + '\'' +
                    '}';
        }
    }
    @RestController
    public class EventController {
       
        @GetMapping("/event/{event}")
        public String getEvent(@PathVariable Event event){ // PathVariable에 해당하는 부분을 Event 도메인으로 받음
            System.out.println(event);
            return event.getId().toString();
        }
    }
    テストコード
    @RunWith(SpringRunner.class)
    @WebMvcTest
    public class EventControllerTest {
    
        @Autowired
        MockMvc mockMvc;
    
        @Test
        public void getTest() throws Exception{
            mockMvc.perform(get("/event/1"))
                    .andExpect(status().isOk())
                    .andExpect(content().string("1"));
        }
    }
    しかし、このテストは失敗しました.1という数字をイベントタイプに変更することはできません.次にPropertyEditorを作成します.
    public class EventEditor extends PropertyEditorSupport {
        @Override
        public String getAsText() {
            Event event = (Event) getValue();
            return event.getId().toString();
        }
    
        @Override
        public void setAsText(String text) throws IllegalArgumentException {
            setValue(new Event(Integer.parseInt(text)));
        }
    }
    ただし、このPropertyEditorが共有する「value」はステータス共有であり、静的であるため、スレッドのセキュリティ保護は行われません.したがって、PropertyEditorは、次のように「空」(Singleton)に登録することは絶対にできません.
    @Component
    public class EventEditor extends PropertyEditorSupport {
        @Override
        public String getAsText() {
            Event event = (Event) getValue();
            return event.getId().toString();
        }
    
        @Override
        public void setAsText(String text) throws IllegalArgumentException {
            setValue(new Event(Integer.parseInt(text)));
        }
    }
    したがって、PropertyEditorは空ではなく、コントローラに登録して使用します.
    @RestController
    public class EventController {
        
        @InitBinder
        public void init(WebDataBinder webDataBinder){
            webDataBinder.registerCustomEditor(Event.class, new EventEditor());
        }
    
        @GetMapping("/event/{event}")
        public String getEvent(@PathVariable Event event){
            System.out.println(event);
            return event.getId().toString();
        }
    }
    PropertyEditorはオブジェクトからStringへの変換のみをサポートしており、実現するのは面倒であり、スレッドも必要ないため、空登録して使用することはできません.このためSpring 3.0以降は主にConverterとFormateが用いられる.
    リファレンス
  • インフラストラクチャ:スプリングフレームキーテクノロジー(白旗線)
  • https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/validation/DataBinder.html
  • https://docs.oracle.com/javase/7/docs/api/java/beans/PropertyEditor.html