在Spring的数据绑定里,可以使用@ModelAttribute把表单绑定到JavaBean上。
但是大家都知道从客户端传过来的数据实际上首先都是字符型的,如果绑定对象JavaBean上有别的类型,那么势必需要进行类型转换。
在这点上Spring做的比较欠缺,在绑定之前并没有进行类型check,硬生生的进行转换。
比如转换为数字或者日期类型时
public class PersonForm { @Size(min=2, max=30) private String name; @NumberFormat(pattern="#,###") private Integer age; @DateTimeFormat(pattern="yyyy/MM/dd") private Date birthday; }
如果输入的根本就不是数字类型,或者输入的日期类型不对的话,那么会打出exception
写道
Failed to convert property value of type [java.lang.String] to required type [java.lang.Integer] for property age; nested exception is java.lang.NumberFormatException
Failed to convert property value of type [java.lang.String] to required type [java.util.Date] for property birthday; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [@org.springframework.format.annotation.DateTimeFormat java.util.Date] for value
Failed to convert property value of type [java.lang.String] to required type [java.util.Date] for property birthday; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [@org.springframework.format.annotation.DateTimeFormat java.util.Date] for value
既然无法在绑定前check数据类型或者格式,那么就只能从转换后的exception message上下手了。
上面打出来的信息是默认信息,那么自定义信息的寻找就是以下顺序了
写道
1.: code + "." + object name + "." + field
2.: code + "." + field
3.: code + "." + field type
4.: code
2.: code + "." + field
3.: code + "." + field type
4.: code
比如上面的数值类型
写道
typeMismatch.PersonForm.age=PersonForm.age must be Integer
typeMismatch.age=age must be Integer
typeMismatch.java.lang.Integer={0} must be Integer
typeMismatch=convertion error
typeMismatch.age=age must be Integer
typeMismatch.java.lang.Integer={0} must be Integer
typeMismatch=convertion error
如果全系统都是用同一个message的话,就可以用field type类型
写道
typeMismatch.java.lang.Integer={0} must be Integer
另外补充一下,验证后,如果有错,会把错误信息保存在类FieldError里,并且会把filed的信息作为第一个参数,这个参数的类型是DefaultMessageSourceResolvable。
也就是说,在message的设定里,用{0}就能访问到这个参数,并且因为这个参数本身是DefaultMessageSourceResolvable,同样能在message里定义这个filed的message。
这在多语言里非常有用。