polish
This commit is contained in:
parent
a805819360
commit
2aac0aace4
|
@ -912,23 +912,23 @@ public class MyService {
|
|||
<section id="ui.format">
|
||||
<title>Spring 3 Field Formatting</title>
|
||||
<para>
|
||||
<link linkend="core.convert"><filename>core.convert</filename></link> is a simple, general-purpose type conversion system.
|
||||
It provides a strongly-typed Converter SPI for implementing <emphasis>one-way</emphasis> conversion logic from one type to another and is not limited to just converting Strings.
|
||||
<link linkend="core.convert"><filename>core.convert</filename></link> is a general-purpose type conversion system.
|
||||
It provides a strongly-typed Converter SPI for implementing conversion logic from one type to another and is not limited to just converting Strings.
|
||||
As discussed in the previous section, a Spring Container can be configured to use this system to bind bean property values.
|
||||
In addition, both the Spring Expression Language (SpEL) and DataBinder can use this system to coerce values.
|
||||
In addition, both the Spring Expression Language (SpEL) and DataBinder can use this system to bind values.
|
||||
For example, when SpEL needs to coerce a <classname>Short</classname> to a <classname>Long</classname> to complete an <function>expression.setValue(Object bean, Object value)</function> attempt, the core.convert system performs the coercion.
|
||||
</para>
|
||||
<para>
|
||||
Now consider the type conversion requirements of a typical client environment such as a web or desktop application.
|
||||
In such environments, you typically convert <emphasis>from String</emphasis> to support the client postback process, as well as back <emphasis>to String</emphasis> to support the rendering process.
|
||||
The more general <emphasis>core.convert</emphasis> Converter SPI does not address this specific common scenario directly.
|
||||
To directly address this, Spring 3 introduces a conveient <emphasis>format</emphasis> SPI that provides a simple and robust alternative to PropertyEditors in a client environment.
|
||||
In such environments, you typically convert <emphasis>from String</emphasis> to support the client postback process, as well as back <emphasis>to String</emphasis> to support the view rendering process.
|
||||
The more general <emphasis>core.convert</emphasis> Converter SPI does not address this scenario directly.
|
||||
To directly address this, Spring 3 introduces a conveient <emphasis>format</emphasis> SPI that provides a simple and robust alternative to PropertyEditors for client environments.
|
||||
</para>
|
||||
<para>
|
||||
In general, use the Converter SPI when you need to implement general-purpose type conversion logic.
|
||||
Use Formatters when you're working in a client environment, such as an HTML form of a web application and need to apply String parsing, printing, and localization logic to form field values.
|
||||
Use Formatters when you're working in a client environment, such as a web application, and need to apply String parsing, printing, and localization logic to form field values.
|
||||
</para>
|
||||
<section id="ui-format-Formatter-SPI">
|
||||
<section id="format-Formatter-SPI">
|
||||
<title>Formatter SPI</title>
|
||||
<para>
|
||||
The <literal>org.springframework.format</literal> SPI to implement field formatting logic is simple and strongly typed:
|
||||
|
@ -951,7 +951,7 @@ public interface Formatter<T> extends Printer<T>, Parser<T> {
|
|||
</programlisting>
|
||||
<para>
|
||||
To create your own Formatter, simply implement the Formatter interface above.
|
||||
Parameterize T to be the type of object you are formatting, for example, <classname>java.lang.BigDecimal</classname>.
|
||||
Parameterize T to be the type of object you are formatting, for example, <classname>java.util.Date</classname>.
|
||||
Implement the <methodname>print</methodname> operation to print an instance of T for display in the client locale.
|
||||
Implement the <methodname>parse</methodname> operation to parse an instance of T from the formatted representation returned from the client locale.
|
||||
Your Formatter should throw a ParseException or IllegalArgumentException if a parse attempt fails.
|
||||
|
@ -960,7 +960,7 @@ public interface Formatter<T> extends Printer<T>, Parser<T> {
|
|||
<para>
|
||||
Several Formatter implementations are provided in <filename>format</filename>subpackages as a convenience.
|
||||
The <filename>datetime</filename> package provides a DateFormatter to format java.util.Date objects with a java.text.DateFormat.
|
||||
The <filename>number</filename> package provides a DecimalFormatter, IntegerFormatter, CurrencyFormatter, and PercentFormatter to format java.lang.Number objects using a java.text.NumberFormat.
|
||||
The <filename>number</filename> package provides a NumberFormatter, CurrencyFormatter, and PercentFormatter to format java.lang.Number objects using a java.text.NumberFormat.
|
||||
The <filename>datetime.joda</filename> package provides comprehensive datetime formatting support based on the <ulink url="http://joda-time.sourceforge.net">Joda Time library</ulink>.
|
||||
</para>
|
||||
<para>
|
||||
|
@ -1002,13 +1002,13 @@ public final class DateFormatter implements Formatter<Date> {
|
|||
The Spring team welcomes community-driven Formatter contributions; see <ulink url="http://jira.springframework.org">http://jira.springframework.org</ulink> to contribute.
|
||||
</para>
|
||||
</section>
|
||||
<section id="ui-format-CustomFormatAnnotations">
|
||||
<section id="format-CustomFormatAnnotations">
|
||||
<title>Custom Format Annotations</title>
|
||||
<para>
|
||||
Field formatting can be triggered by annotating model properties.
|
||||
To bind a custom annotation to a Formatter instance, implement AnnotationFormatterFactory:
|
||||
</para>
|
||||
<programlisting language="java"><![CDATA[
|
||||
<programlisting language="java"><![CDATA[
|
||||
package org.springframework.format;
|
||||
|
||||
public interface AnnotationFormatterFactory<A extends Annotation> {
|
||||
|
@ -1019,45 +1019,91 @@ public interface AnnotationFormatterFactory<A extends Annotation> {
|
|||
|
||||
Parser<?> getParser(A annotation, Class<?> fieldType);
|
||||
|
||||
}]]></programlisting>
|
||||
<para>
|
||||
Parameterize A to be the field annotationType you wish to associate formatting logic with, for example <code>org.springframework.format.annotation.DateTimeFormat</code>.
|
||||
Implement the <methodname>getFieldTypes</methodname> operation return the types of fields the annotation may be used on.
|
||||
Implement the <methodname>getPrinter</methodname> operation to return the Printer to print the value of an annotated field.
|
||||
Implement the <methodname>getParser</methodname> operation to return the Parser to parse the value of an annotated field.
|
||||
Take care to ensure your AnnotationFormatterFactory implementation is thread-safe.
|
||||
</para>
|
||||
<para>
|
||||
The example implementation below binds a @DecimalFormat instance to a Formatter instance.
|
||||
This particular annotation allows the NumberFormat pattern to be configured.
|
||||
</para>
|
||||
<programlisting language="java"><![CDATA[
|
||||
public class DecimalAnnotationFormatterFactory implements AnnotationFormatterFactory<DecimalFormat, Number> {
|
||||
}]]>
|
||||
</programlisting>
|
||||
<para>
|
||||
Parameterize A to be the field annotationType you wish to associate formatting logic with, for example <code>org.springframework.format.annotation.DateTimeFormat</code>.
|
||||
Implement the <methodname>getFieldTypes</methodname> operation return the types of fields the annotation may be used on.
|
||||
Implement the <methodname>getPrinter</methodname> operation to return the Printer to print the value of an annotated field.
|
||||
Implement the <methodname>getParser</methodname> operation to return the Parser to parse the value of an annotated field.
|
||||
Take care to ensure your AnnotationFormatterFactory implementation is thread-safe.
|
||||
</para>
|
||||
<para>
|
||||
The example implementation below binds a @NumberFormat instance to a Formatter instance.
|
||||
This particular annotation allows the NumberFormat style or pattern to be specified:
|
||||
</para>
|
||||
<programlisting language="java"><![CDATA[
|
||||
public final class NumberFormatAnnotationFormatterFactory implements AnnotationFormatterFactory<NumberFormat> {
|
||||
|
||||
Formatter<Number> getFormatter(DecimalFormat annotation) {
|
||||
DecimalFormatter formatter = DecimalFormatter();
|
||||
formatter.setPattern(annotation.value());
|
||||
return formatter;
|
||||
}
|
||||
}]]></programlisting>
|
||||
<para>
|
||||
Then, to trigger formatting, simply annotate a property with @DecimalFormat in your model:
|
||||
</para>
|
||||
<programlisting language="java"><![CDATA[
|
||||
public Set<Class<?>> getFieldTypes() {
|
||||
Set<Class<?>> fieldTypes = new HashSet<Class<?>>(7);
|
||||
fieldTypes.add(Short.class);
|
||||
fieldTypes.add(Integer.class);
|
||||
fieldTypes.add(Long.class);
|
||||
fieldTypes.add(Float.class);
|
||||
fieldTypes.add(Double.class);
|
||||
fieldTypes.add(BigDecimal.class);
|
||||
fieldTypes.add(BigInteger.class);
|
||||
return fieldTypes;
|
||||
}
|
||||
|
||||
public Printer<Number> getPrinter(NumberFormat annotation, Class<?> fieldType) {
|
||||
return configureFormatterFrom(annotation, fieldType);
|
||||
}
|
||||
|
||||
public Parser<Number> getParser(NumberFormat annotation, Class<?> fieldType) {
|
||||
return configureFormatterFrom(annotation, fieldType);
|
||||
}
|
||||
|
||||
private Formatter<Number> configureFormatterFrom(NumberFormat annotation, Class<?> fieldType) {
|
||||
if (!annotation.pattern().isEmpty()) {
|
||||
return new NumberFormatter(annotation.pattern());
|
||||
} else {
|
||||
Style style = annotation.style();
|
||||
if (style == Style.PERCENT) {
|
||||
return new PercentFormatter();
|
||||
} else if (style == Style.CURRENCY) {
|
||||
return new CurrencyFormatter();
|
||||
} else {
|
||||
return new NumberFormatter();
|
||||
}
|
||||
}
|
||||
}
|
||||
}]]>
|
||||
</programlisting>
|
||||
<para>
|
||||
Then, to trigger formatting, simply annotate a property with @NumberFormat in your model:
|
||||
</para>
|
||||
<programlisting language="java"><![CDATA[
|
||||
public class MyModel {
|
||||
|
||||
@DecimalFormat("#,###")
|
||||
@NumberFormat(style=Style.CURRENCY)
|
||||
private BigDecimal decimal;
|
||||
|
||||
}]]></programlisting>
|
||||
</section>
|
||||
}]]>
|
||||
</programlisting>
|
||||
<para>
|
||||
A format annotation API exists in the <filename>org.springframework.format.annotation</filename> package.
|
||||
Use the NumberFormat annotation to apply formatting to java.lang.Number fields.
|
||||
Use the DateTimeFormat annotation to apply formatting to java.util.Date, java.util.Calendar, java.util.Long, or Joda Time fields.
|
||||
</para>
|
||||
<para>
|
||||
The example below shows use of the DateTimeFormat annotation to format a java.util.Date as a ISO Date (yyyy-MM-dd):
|
||||
</para>
|
||||
<programlisting language="java"><![CDATA[
|
||||
public class MyModel {
|
||||
|
||||
@DateTimeFormat(iso=ISO.DATE)
|
||||
private Date date;
|
||||
|
||||
}]]>
|
||||
</programlisting>
|
||||
</section>
|
||||
<section id="ui-format-FormatterRegistry-SPI">
|
||||
<section id="format-FormatterRegistry-SPI">
|
||||
<title>FormatterRegistry SPI</title>
|
||||
<para>
|
||||
Formatters can be registered in a FormatterRegistry.
|
||||
A DataBinder uses this registry to resolve the Formatter to use for a specific field.
|
||||
This allows you to configure default Formatting rules centrally, rather than duplicating such configuration across your UI Controllers.
|
||||
When installed, Formatters are registered in a FormatterRegistry.
|
||||
A FormatterRegistry allows you to configure Formatting rules centrally, instead of duplicating such configuration across your Controllers.
|
||||
For example, you might want to enforce that all Date fields are formatted a certain way, or fields with a specific annotation are formatted in a certain way.
|
||||
With a shared FormatterRegistry, you define these rules once and they are applied whenever formatting is needed.
|
||||
</para>
|
||||
|
@ -1069,60 +1115,68 @@ package org.springframework.format;
|
|||
|
||||
public interface FormatterRegistry {
|
||||
|
||||
void add(Formatter<?> formatter);
|
||||
void addFormatterForFieldType(Class<?> fieldType, Printer<?> printer, Parser<?> parser);
|
||||
|
||||
void add(AnnotationFormatterFactory<?, ?> factory);
|
||||
void addFormatterForFieldType(Class<?> fieldType, Formatter<?> formatter);
|
||||
|
||||
void addFormatterForAnnotation(AnnotationFormatterFactory<?, ?> factory);
|
||||
|
||||
}]]></programlisting>
|
||||
<para>
|
||||
As shown above, Formatters may be registered by field type or annotation.
|
||||
<classname>GenericFormatterRegistry</classname> is the implementation suitable for use in most UI binding environments.
|
||||
This implementation may be configured programatically or declaratively as a Spring bean.
|
||||
As shown above, Formatters can be registered by fieldType or annotation.
|
||||
<classname>FormattingConversionService</classname> is the implementation of <classname>FormatterRegistry</classname> suitable for most environments.
|
||||
This implementation may be configured programatically or declaratively as a Spring bean with <classname>FormattingConversionServiceFactoryBean</classname>.
|
||||
Because it also implements <classname>ConversionService</classname>, it can be configured for use with Spring's DataBinder as well as SpEL.
|
||||
</para>
|
||||
</section>
|
||||
<section id="ui-format-configuring-FormatterRegistry">
|
||||
<title>Configuring a FormatterRegistry</title>
|
||||
<section id="format-configuring-FormatterRegistry">
|
||||
<title>Configuring Formatting in Spring MVC</title>
|
||||
<para>
|
||||
A FormatterRegistry is designed to be instantiated at application startup, then shared between multiple threads.
|
||||
In a Spring MVC application, you configure a FormatterRegistry as a property of the WebBindingInitializer.
|
||||
The FormatterRegistry will then be configured whenever a DataBinder is created by Spring MVC to bind and render model properties.
|
||||
In a Spring MVC application, you can configure a ConversionService instance explicity as an attribute of the <literal>annotation-driven</literal> element of the MVC namespace.
|
||||
This ConversionService will then be used any time type conversion is needed during Controller model binding.
|
||||
If not configured explicitly, Spring MVC will configure a FormattingConversionService instance that registers default formatters for number and date types.
|
||||
</para>
|
||||
<note>
|
||||
<para>
|
||||
If no FormatterRegistry is configured, the original PropertyEditor-based system is used.
|
||||
</para>
|
||||
</note>
|
||||
<para>
|
||||
To register a FormatterRegistry with Spring MVC, simply configure it as a property of a custom WebBindingInitializer injected into the
|
||||
Spring MVC AnnotationMethodHandlerAdapter:
|
||||
To rely on default formatting rules, no explicit configuration is required in your Spring MVC config XML:
|
||||
</para>
|
||||
<programlisting language="xml"><![CDATA[
|
||||
<!-- Invokes Spring MVC @Controller methods -->
|
||||
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
|
||||
<property name="webBindingInitializer">
|
||||
<!-- Configures Spring MVC DataBinder instances -->
|
||||
<bean class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
|
||||
<property name="formatterRegistry">
|
||||
<bean class="org.springframework.format.support.GenericFormatterRegistry">
|
||||
<property name="formatters">
|
||||
<list>
|
||||
<!-- Register Formatter beans here -->
|
||||
</list>
|
||||
</property>
|
||||
<property name="annotationFormatterFactories">
|
||||
<list>
|
||||
<!-- Register any AnnotationFormatterFactory beans here -->
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
</property>
|
||||
</bean>]]>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:mvc="http://www.springframework.org/schema/mvc"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
|
||||
|
||||
<mvc:annotation-driven/>
|
||||
|
||||
</beans>
|
||||
]]>
|
||||
</programlisting>
|
||||
<para>
|
||||
When using the @Formatted annotation, no explicit Formatter or AnnotationFormatterFactory registration is required.
|
||||
See the JavaDocs for GenericFormatterRegistry for more configuration options.
|
||||
With this one-line of configuation, default formatters for Numbers and Date types will be installed, including support for the @NumberFormat and @DateTimeFormat annotations.
|
||||
This also includes full support for the Joda Time formatting library if Joda Time is present on the classpath.
|
||||
</para>
|
||||
<para>
|
||||
To inject a ConversionService instance with custom formatters/converters registered, set the conversion-service attribute:
|
||||
</para>
|
||||
<programlisting language="xml"><![CDATA[
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:mvc="http://www.springframework.org/schema/mvc"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
|
||||
|
||||
<mvc:annotation-driven conversion-service="conversionService" />
|
||||
|
||||
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean" />
|
||||
|
||||
</beans>
|
||||
]]>
|
||||
</programlisting>
|
||||
<para>
|
||||
A custom ConversionService instance is often constructed by a FactoryBean, which internally registers custom Formatters and Converters programatically before the ConversionService is returned.
|
||||
See FormatingConversionServiceFactoryBean for an example.
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
|
|
Loading…
Reference in New Issue