一、数据格式化
Spring提供了注解的属性对象格式化功能:在Bean属性中设置、SpringMVC处理方法参数绑定数据、模型数据输出时自动通过注解应用格式化的功能。
在org.springframework.format.annotation包下面定义了两个格式化的注解类型:
1.DateTimeFormat
@DateTimeFormat注解可以对java.util.Date、java.util.Calendar等时间类型的属性进行标注。它支持以下几个互斥的属性:
·iso。类型为DateTimeFormat.ISO。以下是几个常用的可选值。
DateTimeFormat.ISO.DATE:格式为yyyy-MM-dd。
DateTimeFormat.ISO.DATE_TIME:格式为yyyy-MM-dd hh:mm:ss .SSSZ.
DateTimeFormat.ISO.TIME:格式为hh:mm:ss.SSSZ。
DateTimeFormat.ISO.NONE:表示不使用ISO格式的时间。
·pattern。类型为String,使用自定义的时间格式化字符串,如“yyyy-MM-dd hh:mm:ss”。
·style。类型为String,通过样式指定日期时间的格式,由两位字符组成,第1位表示日期的样式,第2位表示时间的格式,以下是几个常用的可选值。
S:短日期/时间的样式
M:中日期/时间的样式
L:长日期/时间的样式
F:完整日期/时间的样式
-:忽略日期/时间的样式
2.NumberFormat
@NumberFormat可对类似数字类型的属性进行标注,它拥有两个互斥的属性。
~pattern。类型为String,使用自定义的数字格式化串,如“##,###。##”。
~style。类型为NumberFormat.Style,以下是几个常用的可选值:
NumberFormat.CURRENCY: 货币类型
NumberFormat.NUMBER: 正常数字类型
NumberFormat.PERCEMT: 百分数类型
代码实例:
前端js页面:
<h3>数据格式化页面</h3>
<form action="test" method="post">
<table>
<tr>
<td>日期类型:</td>
<td><input type="text" id="birthday" name="birthday" /></td>
</tr>
<tr>
<td>整数类型:</td>
<td><input type="text" id="total" name="total" /></td>
</tr>
<tr>
<td>百分数类型:</td>
<td><input type="text" id="discount" name="discount" /></td>
</tr>
<tr>
<td>货币类型:</td>
<td><input type="text" id="money" name="money" /></td>
</tr>
<tr>
<td><input id="submit" type="submit" value="提交" ></td>
</tr>
</table>
</form>
实体接受:
public class User implements Serializable{
//日期类型
@DateTimeFormat(pattern="yyyy-MM-dd")
private Date birthday;
//正常数字类型
@NumberFormat(style = NumberFormat.Style.NUMBER,pattern = "#,###")
private int total;
//百分数类型
@NumberFormat(style = NumberFormat.Style.PERCENT)
private double discount;
//货币类型
@NumberFormat(style = NumberFormat.Style.CURRENCY)
private double money;
//省略get/set方法
}
说明:User类的多个属性使用了DateTimeFormat和NumberFormat注解,用于将页面传递的String转换成对应的格式化数据。
二、数据校验
1.分类:数据校验分为客户端校验和服务器端校验,客户端校验主要是过滤正常用户的误操作,通常在前端页面进行处理;服务器端校验是整个应用阻止非法数据的最后防线,只要是在后台进行处理。
2.为什么要做两个校验?
客户端校验的主要作用是防止正常用户的误输入,这仅能对输入进行初步的过滤;对于恶意用户的恶意行为,客户端校验将无能为力。所以,需要在客户端进行二次校验,客户端校验能把用户误输入的数据阻止在客户端,从而降低了服务器的负载。
3.两种校验的方法:一种是利用Spring自带的Validation校验框架;另一种是利用JSR303(java验证规范)实现校验功能。
4.Spring的Validation校验框架
Spring的校验框架在org.springframework.validation包中,其中重要的接口和类如下:
~Validator。最重要的接口。该接口有两个方法:
boolean supports(Class<?> clazz):该校验器能够对clazz类型的对象进行校验。
void validate(Object target,Errors errors):对目标类target进行校验,并将校验错误记录在errors当中。
~Errors。Spring用来存放错误信息的接口。SpringMVC框架在将请求数据绑定到入参对象后,就会调用校验框架实施校验,而校验结果保存在处理方法的入参对象之后的参数对象当中。这歌保存校验结果的参数对象必须是Errors或者BindingResult类型。
~ValidationUtils。Spring提供的一个关于校验的工具类。它提供了多个给Errors对象保存错误的方法。
~LocalValidatorFactoryBean。位于org.springframework.validation.beanvalidation包中,给类即实现了Spring的Validator接口,也实现了JSR303的Validator接口。只要在Spring容器中定义一个LocalValidatorFactoryBean,即可将其注入到需要数据校验的Bean中。定义一个LocalValidatorFactoryBean的Bean
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>
在实际项目配置中<mvc:annotation-driven />已经默认配置好了一个LocalValidatorFactoryBean。
测试代码:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>测试validator</title>
</head>
<body>
<h3>登录页面</h3>
<form:form modelAttribute="user" action="login" method="post" >
<table>
<tr>
<td><label>登录名</label> </td>
<td><form:input path="loginname"/></td>
<!--显示错误信息-->
<td><form:errors path="loginname" cssStyle="color:red"/></td>
</tr>
<tr>
<td><label>密码:</label> </td>
<td><form:input path="password"/> </td>
<td><form:errors path="password" cssStyle="color:red" /></td>
</tr>
<tr>
<td><input type="submit" value="提交"/></td>
</tr>
</table>
</form:form>
</body>
</html>
实体代码
public class User implements Serializable {
private String loginname;
private String password;
//省略get/set方法
}
UserValidator代码实例:
package com.hu.controller;
import com.hu.model.User;
import org.springframework.stereotype.Repository;
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;
@Repository("userValidator")
public class UserValidator implements Validator {
//该校验器能够对clazz类型的对象进行校验
@Override
public boolean supports(Class<?> aClass) {
return User.class.isAssignableFrom(aClass);
}
//对目标类target进行校验,并将校验错误记录在errors当中
@Override
public void validate(Object o, Errors errors) {
/**
* 使用ValidationUtils中的一个静态方法rejectIfEmpty()来对loginname属性进行校验,假如
* loginname属性是null或者空字符串的话,就拒绝验证通过
*/
ValidationUtils.rejectIfEmpty(errors,"loginname",null,"登录名不能为空");
ValidationUtils.rejectIfEmpty(errors,"password",null,"密码不能为空");
User user = (User)o;
if (user.getLoginname().length() > 10) {
errors.rejectValue("loginname",null,"y=用户名不能超过10个字符");
}
if (user.getPassword() !=null && !user.getPassword().equals("") && user.getPassword().length()<6) {
errors.rejectValue("password",null,"密码不能小于6位");
}
}
}
controller代码实现:
package com.hu.controller;
import com.hu.converter.StringToDateConverter;
import com.hu.model.User;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.Errors;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.i18n.SessionLocaleResolver;
import org.springframework.web.servlet.support.RequestContext;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
//Controller注解用于指示该类是一个控制器,可以同时处理多个请求动作
@Controller
public class UserController {
@Autowired
@Qualifier("userValidator")
private UserValidator userValidator;
private static final Log logger = LogFactory.getLog(UserController.class);
@RequestMapping(value = "/{formName}")
public String loginForm(@PathVariable String formName,Model model) {
User user = new User();
model.addAttribute("user",user);
return formName;
}
@RequestMapping(value = "/login", method = RequestMethod.POST)
public String login(@ModelAttribute User user, Model model, Errors errors) {
logger.info(user);
model.addAttribute("user",user);
userValidator.validate(user,errors);
if (errors.hasErrors()) {
return "loginForm";
}
return "success";
}
}
5.JSR303校验。
JSR303是java为Bean数据合法性校验提供的一个标准规范,叫做Bean Validation。官方参考实现的是Hibernate Validator。就是提供注解的方法进行数据校验。
注解 | 功能 | 范例 |
@Null | 验证对象是否为null | @Null String name; |
@NotNull | 验证对象是否不为null,无法检查长度为0的字符串,用于验证基本数据类型 | @NotNull String name; |
@AssertTrue | 验证boolean对象是否为true | @AssertTrue boolean isEmpty; |
@AssertFalse | 验证boolean对象是否为false | @AssertFalse boolean isEmpty; |
@Max(value) | 验证Number和String对象是否小于等于指定的值 | @Max(18) Int age; |
@Min(value) | 验证Number和String对象是否大于等于指定的值 | @Min(1) Int age; |
@DecimalMax(value) | 被标注的值必须不大于约束中指定的最大值。这个约束的参数是一个通过BigDecimal定义的最大值的字符串表示,小数存在精度 | @DecimalMax(1.1) BigDecimal price; |
@DecimalMin(value) | 被标注的值必须不小于约束中指定的最小值。这个约束的参数是一个通过BigDecimal定义的最小值的字符串表示,小数存在精度 | @DecimalMin(1.1) BigDecimal price; |
@Digits(integer,fraction) | 验证字符串是否是符合指定格式的数字,integer指定整数精度,fraction指定小数精度 | @Digits(integer=2,fraction=2) BigDecimal price; |
@Size(min,max) | 验证对象(Array、Collection、Map、String)长度是否在给定的范围之内 | @Size(min=10,max20) String name; |
@Past | 验证Date和Calendar对象是否在当前时间之前 | @Past Date birthday |
@Future | 验证Date和Calendar对象是否在当前时间之后 | @Future Date birthday |
@Pattern | 验证String对象是否符合正则表达式的规则 | @Pattern(regexp="[0-9]{1,8}") String text; |
注解 | 功能 | 范例 |
@NotBlank | 检查约束字符串是不是Null,被Trim的长度是否大于0.只对字符串,且会去掉前后空格 | @NotBlank String name; |
@URL | 验证是否是合法的url | @URL String url |
验证是否是合法的邮箱地址 | Stirng email; |
|
@CreditCardNumber | 验证是否是合法的信用卡号码 | @CreditCardNumber String card; |
@Length(min,max) | 验证字符串的长度必须在指定的范围内 | @Length(min=1,max=8) String password; |
@NotEmpty | 检查元素是否为null或者empty。用于Array、Collection、Map、String | @NotEmpty String name; |
@Range(min,max,message) | 验证属性值必须在合适的范围内 | @Range(min=0,max=18,message="未成年人年龄小于18岁") |