数据验证(数据验证错误不会报异常)
和类型转化不一样
类型转换:form表单提交的是字符串, 但是springMVC接收的userId是Integer 如果表单填写的是aa aa转化为Integer的时候就会报异常出现类型转化错误
数据验证:form表单的类型填写的是正确的, 比如年龄要求填写5-10岁的 就需要进行数据的验证是否符合自己定义的
类型转换: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; } }