- 浏览: 550091 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
jsdsh:
自己写的就是不一样.
Spring3 MVC 注解(二)---@RequestMapping -
jsdsh:
吼,非常吼.学习了
Spring3 MVC 注解(一)---注解基本配置及@controller和 @RequestMapping 常用解释 -
爱情是一种错觉:
我爱你 i love 你[color=red][/color] ...
Spring3 MVC 注解(一)---注解基本配置及@controller和 @RequestMapping 常用解释 -
fs08ab:
大哥,目前这个问题有什么可靠的解决方案吗
@ResponseBody注解 -
lhs295988029:
说的很清楚,明白了~
Spring3 MVC 注解(一)---注解基本配置及@controller和 @RequestMapping 常用解释
5. Validation, Data Binding, and Type Conversion
There
are pros and cons for considering validation as business logic,
and Spring offers a design for validation (and data binding) that
does not
exclude either one of them. Specifically validation should not be
tied to
the web tier, should be easy to localize and it should be possible
to plug
in any validator available. Considering the above, Spring has come
up with
a Validator
interface that is
both basic
ands eminently usable in every layer of an application.
Data
binding is useful for allowing user input to be dynamically bound
to the domain model of an application (or whatever objects you use
to
process user input). Spring provides the so-called
DataBinder
to do exactly that.
The
Validator
and the
DataBinder
make up the
validation
package, which is
primarily used in but not
limited to the MVC framework.
The BeanWrapper
is a fundamental
concept in the Spring Framework and is used in a lot of places.
However,
you probably will not have the need to use the
BeanWrapper
directly. Because
this is
reference documentation however, we felt that some explanation
might be in
order. We will explain the BeanWrapper
in
this chapter since, if you were going to use it at all, you would
most
likely do so when trying to bind data to objects.
Spring's
DataBinder and the lower-level BeanWrapper both use
PropertyEditors to parse and format property values. The
PropertyEditor
concept is part
of the
JavaBeans specification, and is also explained in this chapter.
Spring 3
introduces a "core.convert" package that provides a general type
conversion facility, as well as a higher-level "format" package
for
formatting UI field values. These new packages may be used as
simpler
alternatives to PropertyEditors, and will also be discussed in
this
chapter.
Spring features a Validator
interface
that you can use to validate objects. The
Validator
interface works using
an
Errors
object so that while
validating,
validators can report validation failures to the
Errors
object.
Let's consider a small data object:
public class Person { private String name; private int age; // the usual getters and setters... }
We're going to provide validation behavior for the
Person
class by implementing the
following two
methods of the
org.springframework.validation.Validator
interface:
-
supports(Class)
- Can thisValidator
validate instances of the suppliedClass
? -
validate(Object, org.springframework.validation.Errors)
- validates the given object and in case of validation errors, registers those with the givenErrors
object
Implementing a Validator
is
fairly
straightforward, especially when you know of the
ValidationUtils
helper class that
the Spring
Framework also provides.
public class PersonValidator implements Validator { /** * This Validator validates just Person instances */ public boolean supports(Class clazz) { return Person.class .equals(clazz); } public void validate(Object obj, Errors e) { ValidationUtils.rejectIfEmpty(e, "name" , "name.empty" ); Person p = (Person) obj; if (p.getAge() < 0) { e.rejectValue("age" , "negativevalue" ); } else if (p.getAge() > 110) { e.rejectValue("age" , "too.darn.old" ); } } }
As you can see, the static
rejectIfEmpty(..)
method on the
ValidationUtils
class is used to
reject the
'name'
property if it is null
or the
empty string. Have a look at the Javadoc for the
ValidationUtils
class to see what
functionality it
provides besides the example shown previously.
While it is
certainly possible to implement a single
Validator
class to validate
each of the
nested objects in a rich object, it may be better to encapsulate
the
validation logic for each nested class of object in its own
Validator
implementation. A
simple example
of a 'rich'
object would be
a
Customer
that is composed of two
String
properties (a first and
second name) and a
complex Address
object.
Address
objects may be used
independently of
Customer
objects, and so a distinct
AddressValidator
has been
implemented. If you want
your CustomerValidator
to reuse the
logic contained
within the AddressValidator
class
without resorting
to copy-and-paste, you can dependency-inject or instantiate an
AddressValidator
within your
CustomerValidator
, and use it like
so:
public class CustomerValidator implements Validator { private final Validator addressValidator; public CustomerValidator(Validator addressValidator) { if (addressValidator == null) { throw new IllegalArgumentException( "The supplied [Validator] is required and must not be null." ); } if (!addressValidator.supports(Address.class )) { throw new IllegalArgumentException( "The supplied [Validator] must support the validation of [Address] instances." ); } this .addressValidator = addressValidator; } /** * This Validator validates Customer instances, and any subclasses of Customer too */ public boolean supports(Class clazz) { return Customer.class .isAssignableFrom(clazz); } public void validate(Object target, Errors errors) { ValidationUtils.rejectIfEmptyOrWhitespace(errors, "firstName" , "field.required" ); ValidationUtils.rejectIfEmptyOrWhitespace(errors, "surname" , "field.required" ); Customer customer = (Customer) target; try { errors.pushNestedPath("address" ); ValidationUtils.invokeValidator(this .addressValidator, customer.getAddress(), errors); } finally { errors.popNestedPath(); } } }
Validation errors are reported to the
Errors
object passed to the
validator. In
case of Spring Web MVC you can use <spring:bind/>
tag to inspect the error messages, but of course you can also
inspect the
errors object yourself. More information about the methods it
offers can
be found from the Javadoc.
We've
talked about databinding and validation. Outputting messages
corresponding to validation errors is the last thing we need to
discuss.
In the example we've shown above, we rejected the name
and the age
field. If we're going to
output the error
messages by using a MessageSource
,
we will
do so using the error code we've given when rejecting the field
('name'
and 'age' in this case). When you call (either directly, or
indirectly,
using for example the ValidationUtils
class)
rejectValue
or one of the other
reject
methods from the
Errors
interface, the
underlying
implementation will not only register the code you've passed in,
but also
a number of additional error codes. What error codes it registers
is
determined by the MessageCodesResolver
that
is used. By default, the
DefaultMessageCodesResolver
is
used, which for
example not only registers a message with the code you gave, but
also
messages that include the field name you passed to the reject
method. So
in case you reject a field using rejectValue("age",
"too.darn.old")
, apart from the too.darn.old
code, Spring will also register too.darn.old.age
and
too.darn.old.age.int
(so the first
will include the
field name and the second will include the type of the field);
this is
done as a convenience to aid developers in targeting error
messages and
suchlike.
More information on the
MessageCodesResolver
and the
default
strategy can be found online with the Javadocs for MessageCodesResolver
and DefaultMessageCodesResolver
respectively.
The
org.springframework.beans
package adheres
to
the JavaBeans standard provided by Sun. A JavaBean is simply a
class with
a default no-argument constructor, which follows a naming
convention where
(by way of an example) a property named bingoMadness
would have a setter method setBingoMadness(..)
and a getter method getBingoMadness()
.
For more
information about JavaBeans and the specification, please refer to
Sun's
website ( java.sun.com/products/javabeans
).
One
quite important class in the beans package is the
BeanWrapper
interface and its
corresponding
implementation (BeanWrapperImpl
).
As quoted from
the Javadoc, the BeanWrapper
offers
functionality to set and get property values (individually or in
bulk),
get property descriptors, and to query properties to determine if
they are
readable or writable. Also, the BeanWrapper
offers support for nested properties, enabling the setting of
properties
on sub-properties to an unlimited depth. Then, the
BeanWrapper
supports the
ability to add
standard JavaBeans PropertyChangeListeners
and VetoableChangeListeners
,
without the
need for supporting code in the target class. Last but not least,
the
BeanWrapper
provides support
for the
setting of indexed properties. The
BeanWrapper
usually isn't used
by
application code directly, but by the
DataBinder
and the
BeanFactory
.
The way the BeanWrapper
works is partly
indicated by its name: it wraps a bean
to perform
actions on that bean, like setting and retrieving properties.
Setting and
getting properties is done using the
setPropertyValue(s)
and
getPropertyValue(s)
methods that
both come with a
couple of overloaded variants. They're all described in more
detail in
the Javadoc Spring comes with. What's important to know is that
there
are a couple of conventions for indicating properties of an
object. A
couple of examples:
Table 5.1. Examples of properties
name
|
Indicates
the property name
corresponding to the methods getName()
or isName()
and
setName(..)
|
account.name
|
Indicates the nested property name
of
the property account
corresponding e.g. to
the methods getAccount().setName()
or
getAccount().getName()
|
account[2]
|
Indicates the third
element of the
indexed property account
.
Indexed properties
can be of type array
, list
or other naturally ordered
collection |
account[COMPANYNAME]
|
Indicates the value of the map entry indexed by the key
COMPANYNAME
of
the Map property
account
|
Below you'll find some examples of working with
the
BeanWrapper
to get and set
properties.
(This next section
is not vitally important to you if
you're not planning to work with the
BeanWrapper
directly. If
you're just
using the DataBinder
and the
BeanFactory
and their
out-of-the-box
implementation, you should skip ahead to the section about
PropertyEditors
.)
Consider the following two classes:
public class Company { private String name; private Employee managingDirector; public String getName() { return this .name; } public void setName(String name) { this .name = name; } public Employee getManagingDirector() { return this .managingDirector; } public void setManagingDirector(Employee managingDirector) { this .managingDirector = managingDirector; } }
public class Employee { private String name; private float salary; public String getName() { return this .name; } public void setName(String name) { this .name = name; } public float getSalary() { return salary; } public void setSalary(float salary) { this .salary = salary; } }
The following code snippets show some examples of how to
retrieve
and manipulate some of the properties of instantiated
Companies
and Employees
:
BeanWrapper company = BeanWrapperImpl(new Company()); // setting the company name.. company.setPropertyValue("name" , "Some Company Inc." ); // ... can also be done like this: PropertyValue value = new PropertyValue("name" , "Some Company Inc." ); company.setPropertyValue(value); // ok, let's create the director and tie it to the company: BeanWrapper jim = BeanWrapperImpl(new Employee()); jim.setPropertyValue("name" , "Jim Stravinsky" ); company.setPropertyValue("managingDirector" , jim.getWrappedInstance()); // retrieving the salary of the managingDirector through the company Float salary = (Float) company.getPropertyValue("managingDirector.salary" );
Spring uses the concept
of PropertyEditors
to
effect the conversion between an Object
and a
String
. If you think about it, it
sometimes might
be handy to be able to represent properties in a different way
than the
object itself. For example, a Date
can be
represented in a human readable way (as the
String
'2007-14-09
'),
while
we're still able to convert the human readable form back to the
original
date (or even better: convert any date entered in a human
readable form,
back to Date
objects). This
behavior can be
achieved by registering custom
editors
, of type
java.beans.PropertyEditor
.
Registering
custom editors on a BeanWrapper
or
alternately in a specific IoC container as mentioned in the
previous
chapter, gives it the knowledge of how to convert properties to
the
desired type. Read more about
PropertyEditors
in the
Javadoc of the
java.beans
package provided by Sun.
A couple of examples where property editing is used in Spring:
-
setting properties on beans is done using
PropertyEditors
. When mentioningjava.lang.String
as the value of a property of some bean you're declaring in XML file, Spring will (if the setter of the corresponding property has aClass
-parameter) use theClassEditor
to try to resolve the parameter to aClass
object. -
parsing HTTP request parameters in Spring's MVC framework is done using all kinds of
PropertyEditors
that you can manually bind in all subclasses of theCommandController
.
Spring has a number of built-in PropertyEditors
to make life easy. Each of those is listed below and they are
all
located in the
org.springframework.beans.propertyeditors
package.
Most, but not all (as indicated below), are registered by
default by
BeanWrapperImpl
. Where the
property editor is
configurable in some fashion, you can of course still register
your own
variant to override the default one:
Table 5.2. Built-in
PropertyEditors
ByteArrayPropertyEditor
|
Editor for byte arrays. Strings will
simply be converted to
their corresponding byte representations. Registered by
default
by BeanWrapperImpl
. |
ClassEditor
|
Parses Strings representing classes to actual classes and
the other way around. When a class is not found, an
IllegalArgumentException
is thrown.
Registered by default by
BeanWrapperImpl
. |
CustomBooleanEditor
|
Customizable property editor for
Boolean
properties.
Registered by default
by BeanWrapperImpl
, but,
can be
overridden by registering custom instance of it as
custom
editor. |
CustomCollectionEditor
|
Property editor for Collections,
converting any source
Collection
to a given
target
Collection
type. |
CustomDateEditor
|
Customizable property editor for java.util.Date, supporting a custom DateFormat. NOT registered by default. Must be user registered as needed with appropriate format. |
CustomNumberEditor
|
Customizable property editor for any
Number subclass like
Integer
, Long
,
Float
, Double
.
Registered by default by BeanWrapperImpl
,
but can be overridden by registering custom instance of
it as a
custom editor. |
FileEditor
|
Capable of resolving Strings to
java.io.File
objects.
Registered by
default by BeanWrapperImpl
.
|
InputStreamEditor
|
One-way property editor, capable of
taking a text string
and producing (via an intermediate
ResourceEditor
and
Resource
) an
InputStream
, so
InputStream
properties may be
directly set as Strings. Note that the default usage
will not
close the InputStream
for you!
Registered by default by
BeanWrapperImpl
. |
LocaleEditor
|
Capable of resolving Strings to
Locale
objects and vice
versa (the String
format is [language]_[country]_[variant], which is the
same
thing the toString() method of Locale provides).
Registered by
default by BeanWrapperImpl
. |
PatternEditor
|
Capable of resolving Strings to JDK 1.5
Pattern
objects and vice
versa. |
PropertiesEditor
|
Capable of converting Strings
(formatted using the format
as defined in the Javadoc for the java.lang.Properties
class) to
Properties
objects.
Registered by default
by BeanWrapperImpl
. |
StringTrimmerEditor
|
Property editor that trims Strings.
Optionally allows
transforming an empty string into a null
value. NOT registered by default; must be user
registered as
needed. |
URLEditor
|
Capable
of resolving a String representation of a URL to an
actual URL
object.
Registered by default
by BeanWrapperImpl
. |
Spring uses the
java.beans.PropertyEditorManager
to set
the search path for property editors that might be needed. The
search
path also includes sun.bean.editors
,
which includes
PropertyEditor
implementations for types
such as Font
, Color
, and
most of the primitive types. Note also that the standard
JavaBeans
infrastructure will automatically discover
PropertyEditor
classes
(without you
having to register them explicitly) if they are in the same
package as
the class they handle, and have the same name as that class,
with
'Editor'
appended; for example, one
could have the
following class and package structure, which would be sufficient
for the
FooEditor
class to be recognized
and used as the
PropertyEditor
for
Foo
-typed properties.
com
chank
pop
Foo
FooEditor // the PropertyEditor
for the Foo
class
Note
that you can also use the standard
BeanInfo
JavaBeans mechanism
here as well
(described in not-amazing-detail here
). Find below an example of
using the
BeanInfo
mechanism for
explicitly
registering one or more PropertyEditor
instances with the properties of an associated class.
com
chank
pop
Foo
FooBeanInfo // the BeanInfo
for the Foo
class
Here is the Java source code for the referenced
FooBeanInfo
class. This would
associate a
CustomNumberEditor
with the
age
property of the Foo
class.
public class FooBeanInfo extends SimpleBeanInfo { public PropertyDescriptor[] getPropertyDescriptors() { try { final PropertyEditor numberPE = new CustomNumberEditor(Integer.class , true); PropertyDescriptor ageDescriptor = new PropertyDescriptor("age" , Foo.class ) { public PropertyEditor createPropertyEditor(Object bean) { return numberPE; }; }; return new PropertyDescriptor[] { ageDescriptor }; } catch (IntrospectionException ex) { throw new Error(ex.toString()); } } }
When
setting bean properties as a string value, a Spring IoC
container ultimately uses standard JavaBeans
PropertyEditors
to convert these
Strings to the
complex type of the property. Spring pre-registers a number of
custom
PropertyEditors
(for example, to
convert a
classname expressed as a string into a real
Class
object). Additionally,
Java's standard
JavaBeans PropertyEditor
lookup
mechanism allows a PropertyEditor
for a class
simply to be named appropriately and placed in the same
package as the
class it provides support for, to be found automatically.
If
there is a need to register other custom
PropertyEditors
, there are
several mechanisms
available. The most manual approach, which is not normally
convenient
or recommended, is to simply use the
registerCustomEditor()
method
of the
ConfigurableBeanFactory
interface,
assuming you have a BeanFactory
reference. Another, slightly more convenient, mechanism is to
use a
special bean factory post-processor called
CustomEditorConfigurer
.
Although bean factory
post-processors can be used with
BeanFactory
implementations, the
CustomEditorConfigurer
has a
nested property
setup, so it is strongly recommended that it is used with the
ApplicationContext
, where
it may be
deployed in similar fashion to any other bean, and
automatically
detected and applied.
Note that all bean factories and
application contexts
automatically use a number of built-in property editors,
through their
use of something called a BeanWrapper
to handle property conversions. The standard property editors
that the
BeanWrapper
registers are
listed in
the previous
section
.
Additionally, ApplicationContexts
also override or
add an additional number of editors to handle resource lookups
in a
manner appropriate to the specific application context type.
Standard
JavaBeans PropertyEditor
instances are used to convert property values expressed as
strings to
the actual complex type of the property.
CustomEditorConfigurer
, a bean
factory
post-processor, may be used to conveniently add support for
additional
PropertyEditor
instances to
an
ApplicationContext
.
Consider
a user class ExoticType
, and
another class DependsOnExoticType
which needs
ExoticType
set as a property:
package example; public class ExoticType { private String name; public ExoticType(String name) { this .name = name; } } public class DependsOnExoticType { private ExoticType type; public void setType(ExoticType type) { this .type = type; } }
When things are properly set up, we want to be able to assign
the
type property as a string, which a
PropertyEditor
will behind
the scenes
convert into an actual ExoticType
instance:
<bean id ="sample" class ="example.DependsOnExoticType" > <property name ="type" value ="aNameForExoticType" /> </bean >
The PropertyEditor
implementation
could look similar to this:
// converts string representation to ExoticType object package example; public class ExoticTypeEditor extends PropertyEditorSupport { public void setAsText(String text) { setValue(new ExoticType(text.toUpperCase())); } }
Finally, we use CustomEditorConfigurer
to
register the new PropertyEditor
with
the ApplicationContext
,
which will then
be able to use it as needed:
<bean class ="org.springframework.beans.factory.config.CustomEditorConfigurer" > <property name ="customEditors" > <map > <entry key ="example.ExoticType" value ="example.ExoticTypeEditor" /> </map > </property > </bean >
Another
mechanism for registering property editors with the
Spring container is to create and use a
PropertyEditorRegistrar
.
This
interface is particularly useful when you need to use the
same set
of property editors in several different situations: write a
corresponding registrar and reuse that in each case.
PropertyEditorRegistrars
work
in conjunction with
an interface called
PropertyEditorRegistry
,
an interface
that is implemented by the Spring
BeanWrapper
(and
DataBinder
).
PropertyEditorRegistrars
are
particularly
convenient when used in conjunction with the
CustomEditorConfigurer
(introduced here
),
which exposes a property called
setPropertyEditorRegistrars(..)
:
PropertyEditorRegistrars
added
to a
CustomEditorConfigurer
in
this fashion can
easily be shared with DataBinder
and
Spring MVC Controllers
.
Furthermore,
it avoids the need for synchronization on custom editors: a
PropertyEditorRegistrar
is expected
to create fresh PropertyEditor
instances for each bean creation attempt.
Using a PropertyEditorRegistrar
is perhaps best illustrated with an example. First off, you
need to
create your own
PropertyEditorRegistrar
implementation:
package com.foo.editors.spring; public final class CustomPropertyEditorRegistrar implements PropertyEditorRegistrar { public void registerCustomEditors(PropertyEditorRegistry registry) { // it is expected that new PropertyEditor instances are created registry.registerCustomEditor(ExoticType.class , new ExoticTypeEditor()); // you could register as many custom property editors as are required here... } }
See also the
org.springframework.beans.support.ResourceEditorRegistrar
for an example
PropertyEditorRegistrar
implementation. Notice how in its implementation of the
registerCustomEditors(..)
method it creates
new instances of each property editor.
Next we
configure a
CustomEditorConfigurer
and
inject an instance
of our CustomPropertyEditorRegistrar
into
it:
<bean class ="org.springframework.beans.factory.config.CustomEditorConfigurer" > <property name ="propertyEditorRegistrars" > <list > <ref bean ="customPropertyEditorRegistrar" /> </list > </property > </bean > <bean id ="customPropertyEditorRegistrar" class ="com.foo.editors.spring.CustomPropertyEditorRegistrar" />
Finally,
and in a bit of a departure from the focus of this
chapter, for those of you using Spring's MVC web
framework
, using
PropertyEditorRegistrars
in
conjunction with data-binding
Controllers
(such as
SimpleFormController
) can be
very convenient.
Find below an example of using a
PropertyEditorRegistrar
in the
implementation of an initBinder(..)
method:
public final class RegisterUserController extends SimpleFormController { private final PropertyEditorRegistrar customPropertyEditorRegistrar; public RegisterUserController(PropertyEditorRegistrar propertyEditorRegistrar) { this .customPropertyEditorRegistrar = propertyEditorRegistrar; } protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception { this .customPropertyEditorRegistrar.registerCustomEditors(binder); } // other methods to do with registering a User }
This style of PropertyEditor
registration can lead to concise code (the implementation of
initBinder(..)
is just one
line long!), and
allows common PropertyEditor
registration code to be encapsulated in a class and then
shared
amongst as many Controllers
as
needed.
Spring 3 introduces a core.convert
package that
provides a general type conversion system. The system defines an
SPI to
implement type conversion logic, as well as an API to execute type
conversions at runtime. Within a Spring container, this system can
be used
as an alternative to PropertyEditors to convert externalized bean
property
value strings to required property types. The public API may also
be used
anywhere in your application where type conversion is needed.
The SPI to implement type conversion logic is simple and strongly typed:
package org.springframework.core.convert.converter; public interface Converter<S, T> { T convert(S source); }
To create your own Converter, simply implement the interface above. Parameterize S as the type you are converting from, and T as the type you are converting to. For each call to convert(S), the source argument is guaranteed to be NOT null. Your Converter may throw any Exception if conversion fails. An IllegalArgumentException should be thrown to report an invalid source value. Take care to ensure your Converter implementation is thread-safe.
Several converter
implementations are provided in the
core.convert.support
package as a
convenience.
These include converters from Strings to Numbers and other
common types.
Consider StringToInteger
as an
example Converter
implementation:
package org.springframework.core.convert.support; final class StringToInteger implements Converter<String, Integer> { public Integer convert(String source) { return Integer.valueOf(source); } }
When you need to centralize the conversion logic for an entire
class hierarchy, for example, when converting from String to
java.lang.Enum objects, implement
ConverterFactory
:
package org.springframework.core.convert.converter; public interface ConverterFactory<S, R> { <T extends R> Converter<S, T> getConverter(Class<T> targetType); }
Parameterize S to be the type you are converting from and R to be the base type defining the range of classes you can convert to. Then implement getConverter(Class<T>), where T is a subclass of R.
Consider the StringToEnum
ConverterFactory
as an example:
package org.springframework.core.convert.support; final class StringToEnumConverterFactory implements ConverterFactory<String, Enum> { public <T extends Enum> Converter<String, T> getConverter(Class<T> targetType) { return new StringToEnumConverter(targetType); } private final class StringToEnumConverter<T extends Enum> implements Converter<String, T> { private Class<T> enumType; public StringToEnumConverter(Class<T> enumType) { this .enumType = enumType; } public T convert(String source) { return (T) Enum.valueOf(this .enumType, source.trim()); } } }
When you require a sophisticated Converter implementation, consider the GenericConverter interface. With a more flexible but less strongly typed signature, a GenericConverter supports converting between multiple source and target types. In addition, a GenericConverter makes available source and target field context you can use when implementing your conversion logic. Such context allows a type conversion to be driven by a field annotation, or generic information declared on a field signature.
package org.springframework.core.convert.converter; public interface GenericConverter { public Set<ConvertiblePair> getConvertibleTypes(); Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType); }
To implement a GenericConverter, have getConvertibleTypes() return the supported source->target type pairs. Then implement convert(Object, TypeDescriptor, TypeDescriptor) to implement your conversion logic. The source TypeDescriptor provides access to the source field holding the value being converted. The target TypeDescriptor provides access to the target field where the converted value will be set.
A good example of a GenericConverter is a converter that converts between a Java Array and a Collection. Such an ArrayToCollectionConverter introspects the field that declares the target Collection type to resolve the Collection's element type. This allows each element in the source array to be converted to the Collection element type before the Collection is set on the target field.
Note |
Because GenericConverter is a more complex SPI interface, only use it when you need it. Favor Converter or ConverterFactory for basic type conversion needs. |
Sometimes you only want a Converter to execute if a specific condition holds true. For example, you might only want to execute a Converter if a specific annotation is present on the target field. Or you might only want to execute a Converter if a specific method, such as static valueOf method, is defined on the target class. ConditionalGenericConverter is an subinterface of GenericConverter that allows you to define such custom matching criteria:
public interface ConditionalGenericConverter extends GenericConverter { boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType); }
A good example of a ConditionalGenericConverter is an EntityConverter that converts between an persistent entity identifier and an entity reference. Such a EntityConverter might only match if the target entity type declares a static finder method e.g. findAccount(Long). You would perform such a finder method check in the implementation of matches(TypeDescriptor, TypeDescriptor).
The ConversionService defines a unified API for executing type conversion logic at runtime. Converters are often executed behind this facade interface:
package org.springframework.core.convert; public interface ConversionService { boolean canConvert(Class<?> sourceType, Class<?> targetType); <T> T convert(Object source, Class<T> targetType); boolean canConvert(TypeDescriptor sourceType, TypeDescriptor targetType); Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType); }
Most ConversionService implementations also implement ConverterRegistry , which provides an SPI for registering converters. Internally, a ConversionService implementation delegates to its registered converters to carry out type conversion logic.
A robust ConversionService implementation is
provided in the
core.convert.support
package.
GenericConversionService
is the
general-purpose
implementation suitable for use in most environments.
ConversionServiceFactory
provides
a convenient
factory for creating common ConversionService configurations.
A ConversionService is a stateless object designed to be instantiated at application startup, then shared between multiple threads. In a Spring application, you typically configure a ConversionService instance per Spring container (or ApplicationContext). That ConversionService will be picked up by Spring and then used whenever a type conversion needs to be performed by the framework. You may also inject this ConversionService into any of your beans and invoke it directly.
Note |
If no ConversionService is registered with Spring, the original PropertyEditor-based system is used. |
To register a default ConversionService with Spring, add the
following bean definition with id conversionService
:
<h
发表评论
-
Spring @Transactional
2011-08-01 11:53 1856Spring事务的传播行为 在service类前加上@ ... -
spring mvc java.lang.IllegalStateException: Errors/BindingResult argument declar
2011-01-21 10:21 5100关于BindingResult Spring ... -
kaptcha 验证码在spring mvc 中的使用
2010-11-11 14:46 15443kaptcha 是一个非常实用的验证码生成工具。有了它,你可 ... -
@ResponseBody注解
2010-11-04 17:44 29877在SpringMVC中可以在Contr ... -
spring 标签介绍
2010-10-27 14:42 3085Spring 标记库分类如下: 1、spring:has ... -
spring roo
2010-10-22 14:50 3207Spring Roo 是一种 Spring 开发的辅助工具,当 ... -
spring mvc 实现的验证码功能
2010-10-19 15:56 8845import java.awt.BasicStroke; i ... -
spring 基于注解的控制器配置
2010-10-18 16:10 389713.12. 基 于注解的控制器配置 现时对于一些类型的配 ... -
打散 <mvc:annotation-driven>
2010-10-18 13:10 4807Spring3.0的基于注解的MVC非常好用,特别在加入了新的 ... -
spring mvc使用注解后的校验和绑定处理
2010-10-12 15:18 1426spring mvc使用注解后,依然可以使用自带的Valida ... -
使用 Spring 2.5 基于注解驱动的 Spring MVC
2010-10-12 10:45 1593概述 继 Spring 2.0 对 Spring MV ... -
Spring MVC的表单控制器
2010-10-11 15:36 3986概述 大多数Web应 ... -
context:component-scan
2010-10-08 13:33 45141. 扫描过滤方式 过滤器类型 说明 注释 假如 com.ba ... -
Spring MVC
2010-09-21 16:12 4441Spring提供了一个细致完整的MVC框架。该框架为模型、视图 ... -
领略Spring 3.x 时代的Spring MVC
2010-09-21 16:07 2039鼎鼎大名的Spring框架3.0版在12月5日由其作者之 ... -
Spring入门之三: 进入Spring MVC
2010-09-13 11:04 2468Spring入门之三: 进入Sprin ... -
Spring3 MVC Restful 多请求类型(json,xml,k-v),多视图配置(Json,Xml,JSP,Freemarker,Volacity等)
2010-09-13 10:59 5884beans xmlns="http://www.sp ... -
Spring3 MVC (三)---请求处理方法 参数及返回值总结
2010-09-13 10:50 8618@RequestMapping("/xx ... -
Spring3 MVC 注解(二)---@RequestMapping
2010-09-13 10:47 156291 问题:有多个 @RequestMapping @ ... -
Spring3 MVC 注解(一)---注解基本配置及@controller和 @RequestMapping 常用解释
2010-09-13 10:46 93174一:配置web.xml 1)问题:spri ...
相关推荐
Core technologies: dependency injection, events, resources, i18n, validation, data binding, type conversion, SpEL, AOP. Testing: mock objects, TestContext framework, Spring MVC Test, WebTestClient. ...
29.3. JPA and “Spring Data” 29.3.1. Entity Classes 29.3.2. Spring Data JPA Repositories 29.3.3. Creating and Dropping JPA Databases 29.3.4. Open EntityManager in View 29.4. Using H2’s Web Console ...
Validation, Data Binding, and Type Conversion部分讲解了Spring中如何进行验证、数据绑定和类型转换。Spring提供了一个Validator接口,可以用来执行验证操作,并且可以将错误代码解析为错误信息。BeanWrapper类...
#### Validation, Data Binding, and Type Conversion - **Introduction**:概述验证、数据绑定和类型转换的基本概念。 - **Validation using Spring’s Validator interface**:介绍了如何使用Spring的Validator...
10. **Conversion and Validation**: Spring MVC提供了数据转换和验证功能,如使用`@RequestParam`、`@PathVariable`注解自动转换参数,以及使用`@Valid`和`BindingResult`进行表单验证。 11. **Tiles or Layouts**...
#### Validation, Data Binding, and Type Conversion Spring提供了强大的验证、数据绑定和类型转换功能,这对于Web开发尤为重要。主要包括以下几个方面: - **Validation using Spring’s Validator interface**...
校验(Validation) 数据绑定(Data Binding) 类型装换(Type Conversion) Spring 表达式(Spring Express Language) 面向切面编程(AOP) 数据存储(Data Access) JDBC 事务抽象(Transactions) DAO 支持(DAO Support) O/R...
国际化(i18n)支持使应用能够适应不同地区的语言环境,数据校验(Validation)和数据绑定(Data Binding)确保了输入数据的准确性和一致性。类型转换(Type Conversion)系统则允许不同数据类型的自动转换,而...
9. **Conversion and Formatting**:Spring MVC有内置的转换服务,可以自动将不同类型的值转换为期望的类型,如日期、数字等。 Spring MVC与Mybatis的结合使用则进一步增强了应用程序的功能。Mybatis是一个轻量级的...
**3.3 Validation, Data Binding, and Type Conversion** - **3.3.1 验证介绍**: 介绍了 Spring 提供的验证支持。 - **3.3.2 使用 Spring 的 Validator 接口进行验证**: 详细解释了如何使用 Validator 接口进行数据...
7. **Data Binding and Validation**: Spring MVC提供数据绑定功能,可以自动将请求参数绑定到Controller方法的参数上。同时,使用@Valid和Validator接口可以进行数据验证,确保输入的有效性。 8. **Conversion and...
3. New Features and Enhancements in Spring Framework 4.0 ............................................ 17 3.1. Improved Getting Started Experience .........................................................
13. **Conversion and Validation**:Spring MVC提供了转换器和验证器,用于处理不同类型的数据输入和确保数据的正确性。 通过这些组件和机制,Spring MVC能够灵活地处理Web请求,提供高效的开发体验。在实际应用中...
2. **验证和数据绑定(Validation and Data Binding)**:可以配合Java的校验框架(如Hibernate Validator)进行数据验证,然后将验证结果封装进Bean。 3. **减少代码冗余**:使用BeanUtils可以避免在控制器层手动...
3. New Features and Enhancements in Spring Framework 4.0 ............................................ 17 3.1. Improved Getting Started Experience .........................................................
3. **数据绑定(Data Binding)**:JSF允许将UI组件的值与后端bean的属性直接绑定,使得数据在视图和模型之间自动同步。 4. **生命周期(Life Cycle)**:JSF有自己的一套处理请求、更新模型、渲染响应的生命周期。...