Spring WebMVCをやってみる (17) - Formatter -

2014-01-03T00:00:00+00:00 Java Spring Framework

前回の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に追加してあげれば良い模様

Spring WebMVCをやってみる (18) - AnnotationFormatterFactory - thymeleaf+spring mvc