Configuring global data-binding formatters in Spring MVC
Here's a very quick how-to for configuring Spring-MVC (Spring 3.1.x) to use a global set of formatters for converting (data-binding) web-request and form parameters for use in Controllers, rather than having to have an @InitBinder
annotated method in all your @Controller
's.
In your spring-web configuration:
<mvc:annotation-driven conversion-service="conversionService"/>
<!-- just to show that we can wire other beans into our registrar -->
<bean id="serviceA" class="com.sjl.myproject.ServiceA"/>
<bean id="serviceB" class="com.sjl.myproject.ServiceB"/>
<!-- Binding -->
<bean
id="customFormatterRegistrar"
class="com.sjl.myproject.web.config.CustomFormatterRegistrar">
<constructor-arg ref="serviceA"/>
<constructor-arg ref="serviceB"/>
</bean>
<bean
id="conversionService"
class="
org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="formatterRegistrars">
<set>
<ref local="customFormatterRegistrar"/>
</set>
</property>
</bean>
Be sure to add the "conversion-service" attribute (pointing at your conversionService bean) to the <mvc:annotation-driven> element, otherwise it won't work!
The CustomFormatterRegistrar class:
package com.sjl.myproject.web.config;
import org.springframework.format.*;
import com.sjl.myproject.*;
public class CustomFormatterRegistrar implements FormatterRegistrar {
private ServiceA serviceA;
private ServiceB serviceB;
// construct the registrar with other spring-beans as constructor args
public CustomFormatterRegistrar(
ServiceA aServiceA,
ServiceB aServiceB) {
serviceA = aServiceA;
serviceB = aServiceB;
}
@Override
public void registerFormatters(FormatterRegistry aRegistry) {
aRegistry.addFormatter(new SomeTypeFormatter(serviceA));
aRegistry.addFormatter(new OtherTypeFormatter(serviceB))
}
}
An example formatter:
package com.sjl.myproject.web.config;
import java.text.*;
import java.util.*;
import org.springframework.format.Formatter;
import com.sjl.myproject.*;
public class SomeTypeFormatter implements Formatter<SomeType> {
private ServiceA serviceA;
public SomeTypeFormatter(ServiceA aServiceA) {
serviceA = aServiceA;
}
@Override
public String print(SomeType aSomeType, Locale aLocale) {
return aSomeType..; // produce some string-based identifier
}
@Override
public SomeType parse(String aText, Locale aLocale) throws ParseException {
return serviceA.lookupByNameOrIdOrSomething(aText);
}
}
And a Controller that benefits from it:
package com.sjl.myproject.web.controllers;
import org.springframework.stereotype.*;
import org.springframework.web.bind.annotation.*;
import com.sjl.myproject.*;
@Controller
public class SomeController {
public static final String URL = "path/with/{param1}/and/{param2}";
@RequestMapping(SomeController.URL)
public String blah(
@PathVariable SomeType param1,
@PathVariable OtherType param2) {
// .. do stuff with our typed params
return "view-name";
}
}
blog comments powered by Disqus