数据验证(数据验证错误不会报异常)
和类型转化不一样
类型转换:form表单提交的是字符串, 但是springMVC接收的userId是Integer 如果表单填写的是aa aa转化为Integer的时候就会报异常出现类型转化错误
数据验证:form表单的类型填写的是正确的, 比如年龄要求填写5-10岁的 就需要进行数据的验证是否符合自己定义的
@Null | 必须为 null |
@NotNull | 必须不为 null |
@AssertTrue | 必须为 true |
@AssertFalse | 必须为 false |
@Min(value) | 必须大于或等于 value |
@Max(value) | 必须小于或等于 value |
@DecimalMin(value) | 必须大于或等于 value |
@DecimalMax(value) | 必须小于或等于 value |
@Size(max,min) | 大小必须在 max 和min 限定的范围内 |
@Digits(integer,fratction) | 值必须是一个数字,且必须在可接受的范围内 |
@Past | 只能用于日期型,且必须是过去的日期 |
@Future | 只能用于日期型,且必须是将来的日期 |
@Pattern(value) | 必须符合指定的正则表达式 |
必须是格式正确的 Email 地址 | |
@Length | 被注释的字符串大小必须在指定的范围内 |
@NotEmpty | 被注释的字符串不能是空字符串 |
@Range | 被注释的元素必须在指定的范围内 |
数据验证的步骤
1.在当前工程类路径下加入以下jar包
classmate-0.8.0.jar
hibernate-validator-5.0.0.CR2.jar
hibernate-validator-annotation-processor-5.0.0.CR2.jar
jboss-logging-3.1.1.GA.jar
validation-api-1.1.0.CR1.jar
2.在Tomcat的lib目录下加入以下jar包
javax.el-2.2.4.jar
javax.el-api-2.2.4.jar
el-api-2.2.jar
3.在需要 user 验证的字段上添加验证注解
@Length(min=5,max=10) //字符串长度在5~10之间
@NotEmpty //非空;空串也不可以
private String userName;
//20~30之间
@Min(value=20)
@Max(value=30)
private int age ;
@Email
private String email;
@Past //必须是一个过去的时间
@DateTimeFormat(pattern= "yyyy-MM-dd") //此处是类型转换 不是数据验证 可由 pattern= "yyyy-MM-dd" 这个参数确定是类型转换
private Date birthday;
@Size(min=3, max=5) //长度在3~5之间
@NotNull //非空
private List<String> multiValues;
4.目标方法的bean前添加@Validated注解
方法1:
※注意:在@Validated注解修饰的bean之后, 紧跟Errors(或BindingResult)类型的参数。
在@Validated注解修饰的bean和Errors参数之间不能再有其他的参数!
正确:public String saveUser(@Validated User user, BindingResult bindingResult) { }
错误:public String saveUser(@Validated User user, String xxx, BindingResult bindingResult) {}
//调用Errors的方法在目标方法中检验是否没有通过验
public String saveUser(@Validated User user, BindingResult bindingResult) {
//如果不进行BindingResult bindingResult判断不会抛异常,应当进行判断,出现错误后返回表单页面,进行错误提示
if (result.hasErrors()) {
//数据绑定错误,做处理
1)可以跳转到元表单页面进行错误消息的显示,这是需要用到spring的form表单以及国际化定制错误消息即步骤6 7
2)抛出自定义的异常(推荐使用)
}
}
方法2:
//或者是目标方法的bean前不加@Validated注解
//用以下方法验证 在bigpay gateway的快捷支付controller可以看到
@Size(max = 8, message = "产品类型[productType]长度最大8位")
@NotBlank(message = "产品类型[productType]不能为空")
private String productType;
@Size(max = 32, message = "支付Key[payKey]长度最大32位")
@NotBlank(message = "支付Key[payKey]不能为空")
private String payKey;
// 参数校验
public void initPay(QuickPayApplyVo quickPayApplyVo, BindingResult bindingResult, HttpServletResponse httpServletResponse, HttpServletRequest httpServletRequest) throws IOException {
validator.validate(quickPayApplyVo, bindingResult);
if (bindingResult.hasErrors()) {
String errorResponse = quickPayService.getErrorResponse(bindingResult);
LOG.info("请求参数异常:{}", errorResponse);
stringObjectMap = new HashMap<String, Object>();
stringObjectMap.put("resultCode", ReturnCodeEnum.REQUEST_PARAMETER_ERROR.getCode());
stringObjectMap.put("orderStatus", "");
stringObjectMap.put("retMsg", errorResponse);
}
}
方法3:
//或者以下验证方法:在payCenter service中可以看到
@Autowired
private Validator validator;
// 1.校验参数
try {
BeanValidators.validateWithException(validator, reqModel);
} catch (RuntimeException e) {
throw new ResponseErrorException("参数校验失败:" + e.getMessage());
}
//要验证的类
public class OnlinePayRequestNew extends BaseRequest {
private static final long serialVersionUID = -3390992083050409730L;
@NotBlank(message = "order_no必填")
private String order_no;
private int third_pay_platform;
private int pay_channel;
@Min(value = 1, message = "pay_money金额非法")
private int pay_money;
@NotBlank(message = "BankCode必填,格式诸如CCB-2C或CCB-2C-C")
private String bank_code;
@NotBlank(message = "notify_url必填")
private String notify_url;
@NotBlank(message = "return_url必填")
private String return_url;
private String merchant_id;
private String order_time;
@NotBlank(message = "goods_name必填")
private String goods_name;
private int time_expire_minutes;
private String remark;
}
/**
* JSR303 Validator(Hibernate Validator)工具类.
*
* ConstraintViolation中包含propertyPath, message 和invalidValue等信息.
* 提供了各种convert方法,适合不同的i18n需求:
* 1. List<String>, String内容为message
* 2. List<String>, String内容为propertyPath + separator + message
* 3. Map<propertyPath, message>
*
* 详情见wiki: https://github.com/springside/springside4/wiki/HibernateValidator
* @author calvin
* @version 2013-01-15
*/
public class BeanValidators {
/**
* 调用JSR303的validate方法, 验证失败时抛出ConstraintViolationException.
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public static void validateWithException(Validator validator, Object object, Class<?>... groups)
throws ConstraintViolationException {
Set<ConstraintViolation<Object>> constraintViolations = validator.validate(object, groups);
if (!constraintViolations.isEmpty()) {
StringBuffer sb=new StringBuffer();
for (ConstraintViolation constraintViolation : constraintViolations) {
sb.append(constraintViolation.getMessage());
}
throw new RuntimeException(sb.toString());
}
}
/**
* 辅助方法, 转换ConstraintViolationException中的Set<ConstraintViolations>中为List<message>.
*/
public static List<String> extractMessage(ConstraintViolationException e) {
return extractMessage(e.getConstraintViolations());
}
/**
* 辅助方法, 转换Set<ConstraintViolation>为List<message>
*/
@SuppressWarnings("rawtypes")
public static List<String> extractMessage(Set<? extends ConstraintViolation> constraintViolations) {
List<String> errorMessages = Lists.newArrayList();
for (ConstraintViolation violation : constraintViolations) {
errorMessages.add(violation.getMessage());
}
return errorMessages;
}
/**
* 辅助方法, 转换ConstraintViolationException中的Set<ConstraintViolations>为Map<property, message>.
*/
public static Map<String, String> extractPropertyAndMessage(ConstraintViolationException e) {
return extractPropertyAndMessage(e.getConstraintViolations());
}
/**
* 辅助方法, 转换Set<ConstraintViolation>为Map<property, message>.
*/
@SuppressWarnings("rawtypes")
public static Map<String, String> extractPropertyAndMessage(Set<? extends ConstraintViolation> constraintViolations) {
Map<String, String> errorMessages = Maps.newHashMap();
for (ConstraintViolation violation : constraintViolations) {
errorMessages.put(violation.getPropertyPath().toString(), violation.getMessage());
}
return errorMessages;
}
/**
* 辅助方法, 转换ConstraintViolationException中的Set<ConstraintViolations>为List<propertyPath message>.
*/
public static List<String> extractPropertyAndMessageAsList(ConstraintViolationException e) {
return extractPropertyAndMessageAsList(e.getConstraintViolations(), " ");
}
/**
* 辅助方法, 转换Set<ConstraintViolations>为List<propertyPath message>.
*/
@SuppressWarnings("rawtypes")
public static List<String> extractPropertyAndMessageAsList(Set<? extends ConstraintViolation> constraintViolations) {
return extractPropertyAndMessageAsList(constraintViolations, " ");
}
/**
* 辅助方法, 转换ConstraintViolationException中的Set<ConstraintViolations>为List<propertyPath +separator+ message>.
*/
public static List<String> extractPropertyAndMessageAsList(ConstraintViolationException e, String separator) {
return extractPropertyAndMessageAsList(e.getConstraintViolations(), separator);
}
/**
* 辅助方法, 转换Set<ConstraintViolation>为List<propertyPath +separator+ message>.
*/
@SuppressWarnings("rawtypes")
public static List<String> extractPropertyAndMessageAsList(Set<? extends ConstraintViolation> constraintViolations,
String separator) {
List<String> errorMessages = Lists.newArrayList();
for (ConstraintViolation violation : constraintViolations) {
errorMessages.add(violation.getPropertyPath() + separator + violation.getMessage());
}
return errorMessages;
}
}