java spring 数据校验_SpringMVC数据校验

29.1 类型转换

form表单提交的数据都是String类型,例如在Servlet中我们是通过StringfiledName=request.getParameter(“…”)方法来获取相应的字段值。如果需要的是int类型,在 Servlet中我们也必须进行类型转换,如intage=Integer.parseInt(…)。但是在SpringMVC中,我们并不需要关心类型的转换,例如:

复制

@RequestMapping(value ="/requestWithREST/{id}",

method =RequestMethod.POST)

publicStringrequestWithRestAdd(@PathVariable("id")Integerid)

{

System.out.println("增加时需要的id:"+id);

return"success";

}

SpringMVC可以直接将form表单中的id字段值转为Integer类型,并传递给requestWithRestAdd()方法中的参数id。这是因为SpringMVC中存在着一些内置的类型转换器,可以自动实现大多数的类型转换。

除此以外,我们还可以根据需求来自定义类型转换器。例如,现在需要将form表单传来的字符串“1-张三-23”解析成学号为1、姓名为张三、年龄为23,并将这些值封装到一个学生对象之中,也就是说需要将字符串“1-张三-23”转换为Student对象类型。

以下是具体的实现步骤:

①创建自定义类型转换器

创建基于SpringMVC的自定义类型转换器,需要新建一个类,并实现SpringMVC提供的Converter接口,如下,

自定义类型转换器,用于将字符串转换为Student类型 : StudentConverter.java

复制

importorg.springframework.core.convert.converter.Converter;

publicclassStudentConverter

implementsConverter

{

@Override

publicStudentconvert(Stringsource)

{

//source值就是前端form传来的"1-张三-23"

if(source !=null)

{

//解析出source中的学号、姓名、年龄

String[]vals =source.split("-");

intstuNo =Integer.parseInt(vals[0]);

StringstuName =vals[1];

intstuAge =Integer.parseInt(vals[2]);

//将解析出的学号、姓名、年龄封装到Student对象之中

Studentstudent =newStudent();

student.setStuNo(stuNo);

student.setStuAge(stuAge);

student.setStuName(stuName);

returnstudent;

}

returnnull;

}

}

②注册自定义类型转换器

springmvc.xml:将自定义的类型转换器注册到SpringMVC之中,共三步

复制

class="org.lanqiao.converter.StudentConverter">

class="org.springframework.context

.support.ConversionServiceFactoryBean">

conversion-service="conversionService">

至此就完成了自定义类型转化器的编写及配置工作。以下,对配置完成的类型转换器StudentConverter进行测试。

③请求处理方法

FirstSpringDemo.java

复制

@Controller

@RequestMapping(value ="/FirstSpringDemo")

publicclassFirstSpringDemo

{

@RequestMapping("/testConversionServiceConverer")

publicStringtestConversionServiceConverer

(@RequestParam("studentInfo")Studentstudent)

{

System.out.println("学号:"+student.getStuNo()

+",姓名:"+student.getStuName()+",年龄:"

+student.getStuAge());

return"success";

}

}

④测试

index.jsp

复制

学生信息:

输入学生信息“1-张三-23”,如图,

29.1.png

图29-01

点击“增加”后,可在控制台得到以下结果:

29.2.png

图29-02

通过自定义类型转换器StudentConverter,成功的将前端传来的字符串“1-张三-23”转为了请求处理方法参数中的Student类型。

29.2 格式化数据

有时候需要对于日期、数字等类型进行格式化操作,例如:规定日期的格式必须为yyyy-MM-dd。

使用SpringMVC实现数据的格式化,只需要简单的两步操作:

①在需要格式化的属性前加上格式化注解,如@DateTimeFormat;

②在springmvc.xml中加入和SpringMVC提供的FormattingConversionServiceFactoryBean,如下:

springmvc.xml

复制

class="org.springframework.format.

support.FormattingConversionServiceFactoryBean">

说明:

通过类的名字可知,FormattingConversionServiceFactoryBean既提供了格式化需要的“Formatting”,又提供了类型转换需要的“Conversion”。因此,之前配置类型转换时使用的ConversionServiceFactoryBean,也可以使用FormattingConversionServiceFactoryBean来替代。也就是说,使用以下配置既可以实现自定义的类型转换,也可以实现格式化数据:

复制

class="org.springframework.

format.support.FormattingConversionServiceFactoryBean">

例如,以下指定Date类型的birthday属性的输入格式必须为yyyy-MM-dd。

Student.java

复制

publicclassStudent

{

privateintstuNo;

privateStringstuName;

@DateTimeFormat(pattern="yyyy-MM-dd")

privateDatebirthday ;

//setter、getter

}

通过注解@DateTimeFormat(pattern="yyyy-MM-dd")指定birthday属性的输入格式必须为yyyy-MM-dd。以下是测试格式化的操作:

请求处理方法:FirstSpringDemo.java

复制

@Controller

@RequestMapping(value ="/FirstSpringDemo")

publicclassFirstSpringDemo

{

@RequestMapping("/testDateTimeFormat")

publicStringtestDateTimeFormat(Studentstudent){

System.out.println("学号:"+student.getStuNo()

+",姓名:"+student.getStuName()+",生日"

+student.getBirthday());

return"success";

}

}

请求页index.jsp

复制

姓名:

年龄:

生日:

如果表单中输入的日期格式符合“yyyy-MM-dd”,如“2015-05-16”,如图,

29.3.png

图29-03

就会将日期赋值给birthday属性,并可以在控制台得到输出结果:

29.4.png

图29-04

而如果输入的日期格式不符合“yyyy-MM-dd”格式,如输入“2015年05月16日”,点击“提交”后JSP页面就会显示HTTP Status 400,如图,

29.5.png

图29-05

但控制台并没有任何异常信息的输出,很不利于开发人员排查错误。为此,我们可以给请求处理方法加入一个BindingResult类型的参数,此参数就包含了格式化数据失败时的异常信息,如下:

FirstSpringDemo.java

复制

@Controller

@RequestMapping(value ="/FirstSpringDemo")

publicclassFirstSpringDemo

{

@RequestMapping("/testDateTimeFormat")

publicStringtestDateTimeFormat(Studentstudent,

BindingResultresult)

{

//如果有错误信息

if(result.getErrorCount()>0)

{

//循环遍历所有错误信息

for(FieldErrorerror :result.getFieldErrors())

{

System.out.println(error.getField()+":"

+error.getDefaultMessage());

}

}

return"success";

}

}

此时再输入不符合格式的日期“2015年05月16日”,就能既在JSP页面显示HTTP Status 400异常,又能在控制台得到具体的异常信息,如下:

控制台输出:

复制

birthday:Failedto convert propertyvalue of type [java.lang.String]to required type [java.util.Date]forproperty'birthday';nested exception isorg.springframework.core.convert.ConversionFailedException:Failedto convert fromtype [java.lang.String]to type [@javax.validation.constraints.Past@org.springframework.format.annotation.DateTimeFormatjava.util.Date]forvalue '2015年05月16日';

nested exception isjava.lang.IllegalArgumentException:

Unableto parse '2015年05月16日'

除了用于格式化日期的注解@DateTimeFormat以外,SpringMVC还提供了用于格式化数字的注解@NumberFormat,例如,可以使用@NumberFormat指定以下int类型的属性count的输入格式为“#,###”(其中#代表数字)

复制

publicclassClassName

{

@NumberFormat(pattern="#,###")

privateintcount;

//setter、getter

}

通过form表单中的input字段来映射count属性时,合法输入:如1,234;不合法的输入:如12,34。

29.3 数据校验

除了使用JS、正则表达式以外,还可以使用JSR 303-Bean Validation(简称JSR 303)来实现数据的校验。例如:用户名不能为空,email必须是一个合法地址,某个日期时间必须在当前时间之前等众多校验,都可以使用JSR 303-Bean Validation非常方便的实现。

JSR 303通过在实体类的属性上标注类@NotNull、@Max等注解指定校验规则,并通过与注解相对应的验证接口(JSR303内置提供)对属性值进行验证。

JSR 303提供的标准注解如下:

注解

简介

@Null

被注释的元素必须为 null。

@NotNull

被注释的元素必须不为 null。

@AssertTrue

被注释的元素必须为 true。

@AssertFalse

被注释的元素必须为 false。

@Min(value)

被注释的元素必须是一个数字,其值必须大于或等于value。

@Max(value)

被注释的元素必须是一个数字,其值必须小于或等于value。

@DecimalMin(value)

被注释的元素必须是一个数字,其值必须大于或等于value。

@DecimalMax(value)

被注释的元素必须是一个数字,其值必须小于或等于value。

@Size(max, min)

被注释的元素的取值范围必须是介于min和max之间。

@Digits (integer, fraction)

被注释的元素必须是一个数字,其值必须在可接受的范围内。

@Past

被注释的元素必须是一个过去的日期。

@Future

被注释的元素必须是一个将来的日期。

@Pattern(value)

被注释的元素必须符合指定的正则表达式。

Hibernate Validator 是JSR 303的扩展。Hibernate Validator 提供了 JSR 303中所有内置的注解,以及自身扩展的4个注解,如下:

注解

简介

@Email

被注释的元素值必须是合法的电子邮箱地址。

@Length

被注释的字符串的长度必须在指定的范围内。

@NotEmpty

被注释的字符串的必须非空。

@Range

被注释的元素必须在合适的范围内。

以下是使用Spring整合Hibernate Validator实现数据校验的步骤:

①导入JAR包:

Spring整合Hibernate Validator共需要导入以下5个JAR包:

hibernate-validator-5.0.0.CR2.jar

classmate-0.8.0.jar

jboss-logging-3.1.1.GA.jar

validation-api-1.1.0.CR1.jar

hibernate-validator-annotation-processor-5.0.0.CR2.jar

②加入

Spring提供了一个LocalValidatorFactoryBean类,这个类既实现了Spring的校验接口,也实现了JSR303的校验接口。因此,Spring整合Hibernate Validator时,需要在Spring容器中定义了一个LocalValidatorFactoryBean。方便的是,就会自动给Spring容器装配一个LocalValidatorFactoryBean,因此只需要在springmvc.xml中配置上即可。

③使用JSR303或Hibernate Validator校验注解,标识实体类的属性:

本次使用JSR303提供的@Past注解,以及Hibernate Validator提供的@Email注解进行输入校验,如下:

Student.java

复制

publicclassStudent

{

@Past

@DateTimeFormat(pattern="yyyy-MM-dd")

privateDatebirthday ;

@Email

privateStringemail;

//setter、getter

}

规定birthday必须在当天之前、email必须符合邮箱格式。

④在请求处理方法对应的实体类参数前,增加@Valid注解

SpringMVC会对标有@Valid注解的实体类参数进行校验,并且可以通过BindingResult类型的参数来存储校验失败时的信息,如下:

请求处理类:FirstSpringDemo.java

复制

@Controller

@RequestMapping(value ="/FirstSpringDemo")

publicclassFirstSpringDemo

{

@RequestMapping("/testValid")

publicStringtestValid(@ValidStudentstudent,

BindingResultresult)

{

if(result.getErrorCount()>0)

{

//循环遍历所有错误信息

for(FieldErrorerror :result.getFieldErrors())

{

System.out.println(error.getField()+":"

+error.getDefaultMessage());

}

}

return"success";

}

}

⑤测试

index.jsp

复制

用户名:

生日:

邮箱:

如果输入的数据不符合要求,如下:

29.6.png

图29-06

点击提交后,就会在控制台得到校验失败的信息(错误信息是JSR303/Hibernate Validator框架提供的,无需开发人员编写):

29.7.png

图29-07

如果希望校验失败后,跳转到错误提示页面(error.jsp),可以通过以下方式实现:

请求处理类:FirstSpringDemo.java

复制

@Controller

@RequestMapping(value ="/FirstSpringDemo")

publicclassFirstSpringDemo

{

@RequestMapping("/testValid")

publicStringtestValid(@ValidStudentstudent,

BindingResultresult,Mapmap)

{

if(result.getErrorCount()>0)

{

//将错误信息通过map放入request作用域之中

map.put ("errors",result.getFieldErrors());

return"error";

}

return"success";

}

}

错误提示页:error.jsp

复制

${error.getDefaultMessage() }、

再次在index.jsp中输入错误的信息(生日2021-11-11,邮箱yanqun),点击“提交”后得到以下error.jsp页面:

29.8.png

图29-08

说明:

需要注意的是:在请求处理方法的参数中,实体类参数和存储错误信息的BindingResult参数必须书写在一起,它们之间不能掺杂任何其它参数。

例如,可以写成:

复制

publicStringtestValid(@ValidStudentstudent,BindingResultresult,Mapmap)

但不能写成:

复制

publicStringtestValid(@ValidStudentstudent,Mapmap,BindingResultresult)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值