data bind

사용자가 String 으로 입력한 다양한 도메인타입의 데이터를 변환해주는 녀석 주로 WebMVC 에서 사용하지만 이전에 xml 파일의 데이터를 변환할때도 사용했음.

먼저.. 변환 대상인 Event class

Event.java
package herdin.boot;

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 this.id + " : " + this.title;
	}
}

PropertyEditorSupport 를 사용할 경우.

EventEditor.java
package herdin.boot;

import java.beans.PropertyEditorSupport;

/* Thread safe 하지 않다. 그래서 Bean 으로 등록하지말고
 * Thread Scope 의 Bean 으로 사용 하던지, 아예 Bean 으로 등록하지 않도록 한다.
 * 그리고 String, Objec 간의 변환만이 가능하여 Spring 3.0 이후로는
 * interface Converter, Formatter 가 나왔다. */
public class EventEditor extends PropertyEditorSupport {
	@Override
	public void setAsText(String text) throws IllegalArgumentException {
		setValue(new Event(Integer.parseInt(text))); //이곳의 setValue
	}
	@Override
	public String getAsText() {
		Event event = (Event) getValue(); //이곳의 getValue 는 공유하는 value 가 있다.
		return event.getId().toString();
	}
}

음 Spring Legacy 에선 WebBindingInitializer 를 implements 하여 bean 으로 등록하여 사용하면 되는 것 같다. 안해봤음 찡긋.

EventController.java
package herdin.boot;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class EventController {
	private Logger logger = LoggerFactory.getLogger(EventController.class);
	/* Controller 에서 등록한 Binder 를 사용하여 변환한다. */
	@InitBinder
	public void init(WebDataBinder webDataBinder) {
		webDataBinder.registerCustomEditor(Event.class, new EventEditor());
	}
	@GetMapping("/event/{event}")
	public String getEvent(@PathVariable Event event) {
		this.logger.debug(event.toString());
		return event.getId().toString();
	}
}

Converter 를 사용해보자

String <--> Event 객체를 변환해주는 class 들을 Converter<S, T> 를 implements 하여 만든다.

EventConverter.java
package herdin.boot;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.convert.converter.Converter;

public class EventConverter {
	/* 상태가 없기때문에 Bean 으로 등록해도 무방함
	 * 하지만 등록해서 사용하는 방법이 있음.
	 */
	public static class StringToEventConverter implements Converter<String, Event> {
		private static Logger logger = LoggerFactory.getLogger(StringToEventConverter.class);
		@Override
		public Event convert(String source) {
			StringToEventConverter.logger.debug("SOURCE STRING {}", source);
			return new Event(Integer.parseInt(source));
		}
	}
	public static class EventToStringConverter implements Converter<Event, String> {
		private static Logger logger = LoggerFactory.getLogger(EventToStringConverter.class);
		@Override
		public String convert(Event source) {
			EventToStringConverter.logger.debug("EVENT OBJECT {}", source);
			return source.getId().toString();
		}
	}
}

그리고 Spring Legacy 에서는 WebMvcConfigurer 를 implements 한 설정 class 에서 등록해준다. Spring Boot 에서는 자동으로 등록이 된다. 이렇게 사용하는 법만 알아도 되는걸까..

WebConfig.java
package herdin.boot;

import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {
	@Override
	public void addFormatters(FormatterRegistry registry) {
		registry.addConverter(new EventConverter.StringToEventConverter());
		registry.addConverter(new EventConverter.EventToStringConverter());
	}
}

아무튼 등록만하면 Controller 에서 자동형변환이 되게 된다.

Formatter 를 사용해보자.

EventFormatter.java
package herdin.boot;

import java.text.ParseException;
import java.util.Locale;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.format.Formatter;

public class EventFormatter implements Formatter<Event> {
	private Logger logger = LoggerFactory.getLogger(EventFormatter.class);
	@Override
	public String print(Event object, Locale locale) {
		this.logger.debug(object.toString());
		return object.getId().toString();
	}
	@Override
	public Event parse(String text, Locale locale) throws ParseException {
		this.logger.debug(text);
		this.logger.debug(text);
		return new Event(Integer.parseInt(text));
	}
}

위에서 사용한 설정 class 에서 등록 method 만 변경해주면 된다. 이게 대체 뭔차이지..냐면 FormatterLocale 기반으로 사용할 수 있음.

WebConfig.java
package herdin.boot;

import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {
	@Override
	public void addFormatters(FormatterRegistry registry) {
//		registry.addConverter(new EventConverter.StringToEventConverter());
//		registry.addConverter(new EventConverter.EventToStringConverter());
		registry.addFormatter(new EventFormatter());
	}
}

위에서 등록한 ConverterFormatter 들을 이용하여 ConversionService 가 변환 작업을 한다. Spring Boot 에선 기본적으로 등록되는 ConversionServiceWebConversionService 이고, Spring Legacy 에서 기본적으로 등록되는 것은 DefaultFormattingConversionService 이다.

class WebConversionService/*1*/ extends DefaultFormattingConversionService/*2*/
class DefaultFormattingConversionService/*2*/ extends FormattingConversionService/*3*/
class FormattingConversionService/*3*/ extends GenericConversionService implements FormatterRegistry/*4*/, EmbeddedValueResolverAware
interface FormatterRegistry/*4*/ extends ConverterRegistry/*5*/

ConversionService.toString() 을 찍어보면 등록된 Converter 들을 볼 수 있다.

Last updated

Was this helpful?