Spring WebMVCをやってみる (17) - Formatter -
前回のConverter同様に型を変換したりする仕組みな模様。@DateTimeFormatのようにアノテーションによって型変換を行うのも可能(後日書く)。んまぁ違い的な所としては非常に曖昧で微妙なのだけど、Formatterはインターフェースによりパースする所と出力サポートを行うメソッドを実装する必要がある。んまぁ詳しい違いとかわかり次第補足なりする予定
とりあえず使ってみる。題材的なのとしてEnumを変換する仕組み的なのを作ってみる
Sample.java
package sample;
public enum Sample {
HOGE("hoge"),
FUGA("fuga");
private String name;
private Sample(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
でこのEnumに変換なりを行うFormatterインターフェースの実装クラスが必要
SampleFormatter.java
package sample;
import java.text.ParseException;
import java.util.Locale;
import org.springframework.format.Formatter;
public class SampleFormatter implements Formatter<Sample> {
@Override
public String print(Sample object, Locale locale) {
return object.getName().toLowerCase();
}
@Override
public Sample parse(String text, Locale locale) throws ParseException {
return Sample.valueOf(text.toUpperCase());
}
}
んでこのFormatterが使えるように設定を行う
spring-web-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">
<context:component-scan base-package="sample" />
<mvc:annotation-driven conversion-service="conversionService" />
<bean
id="conversionService"
class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="formatters">
<list>
<bean class="sample.SampleFormatter" />
</list>
</property>
</bean>
</beans>
SampleController.java
package sample;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
@RequestMapping("/sample")
public class SampleController {
@RequestMapping("/test")
public void test(@RequestParam("name") Sample sample, ModelMap model) {
model.addAttribute(sample);
}
}
的な感じで@RequestParamに指定している型な引数がFormatterで変換される。もし変換に失敗した場合などには400エラーになる
余談1: XMLで定義せずにFormatterを使う
package sample;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.convert.ConversionService;
import org.springframework.format.support.DefaultFormattingConversionService;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
@RequestMapping("/sample")
public class SampleController {
@Autowired
public SampleController(ConversionService conversion) {
((DefaultFormattingConversionService)conversion).addFormatterForFieldType(Sample.class, new SampleFormatter());
}
@RequestMapping("/test")
public void test(@RequestParam("name") Sample sample, ModelMap model) {
model.addAttribute(sample);
}
}
っていう感じで、DefaultFormattingConversionService.addFormatterForFieldTypeメソッドを使う事で出来る模様
余談2: FormatterRegistrarを使う場合
例えば複数のFormatterとかをまとめてregisterしたい時とか
package sample;
import org.springframework.format.FormatterRegistrar;
import org.springframework.format.FormatterRegistry;
public class SampleFormatterRegistrar implements FormatterRegistrar {
@Override
public void registerFormatters(FormatterRegistry registry) {
registry.addFormatterForFieldType(Sample.class, new SampleFormatter());
}
}
とかで定義してこれを
<bean
id="conversionService"
class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="formatterRegistrars">
<list>
<bean class="sample.SampleFormatter" />
</list>
</property>
</bean>
っていう感じでformatterRegistrarsに追加してあげれば良い模様