spring 参数校验注解
在写一些controller协议的时候,有些时候从前端传过来的参数较多,好的办法是定义一个实体类来封装请求参数,但是用实体类封装参数后,无法对参数值进行校验,可以使用spring的@Validated 结合java validation、hibernate validation注解进行校验。
1.@validated 注解
@Validated is org.springframework.validation.annotation.Validated.
复制代码
@RequestMapping(value = "/regist", method = {RequestMethod.GET, RequestMethod.POST})
@ResponseBody
public Object hualalaRegist(@Validated HualalaRegistVO registVO, BindingResult bindingResult,
HttpServletRequest request) throws Exception {
if(bindingResult.hasErrors())
return new ResultBean<>(HttpStatus.SC_BAD_REQUEST,"请求参数错误",null);
...
}
复制代码
增加@Validated 注解后,表示需要对其中的参数进行校验。
2.java validation 注解
复制代码
JSR提供的校验注解:
@Null 被注释的元素必须为 null
@NotNull 被注释的元素必须不为 null
@AssertTrue 被注释的元素必须为 true
@AssertFalse 被注释的元素必须为 false
@Min(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@Max(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMin(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@DecimalMax(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@Size(max=, min=) 被注释的元素的大小必须在指定的范围内
@Digits (integer, fraction) 被注释的元素必须是一个数字,其值必须在可接受的范围内
@Past 被注释的元素必须是一个过去的日期
@Future 被注释的元素必须是一个将来的日期
@Pattern(regex=,flag=) 被注释的元素必须符合指定的正则表达式
复制代码
3.hiberate validation 注解
复制代码
@Email 被注释的元素必须是电子邮箱地址
@Length(min=,max=) 被注释的字符串的大小必须在指定的范围内
@NotEmpty 被注释的字符串的必须非空
@Range(min=,max=,message=) 被注释的元素必须在合适的范围内
@URL(protocol=,
host=, port=,
regexp=, flags=) 合法的url
复制代码
主要区分下@NotNull @NotEmpty @NotBlank 3个注解的区别:
@NotNull 任何对象的value不能为null
@NotEmpty 集合对象的元素不为0,即集合不为空,也可以用于字符串不为null
@NotBlank 只能用于字符串不为null,并且字符串trim()以后length要大于0
- 案例
HualalaRegistVO.java
复制代码
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.validator.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import java.math.BigDecimal;
/***
-
@Author: jiyang
-
@Date: 2018-06-27 13:48
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class HualalaRegistVO {@NotBlank
@Pattern(regexp = "^\d{11}$", message = "手机号码格式错误")
String phoneNumber; //手机号码@NotBlank
String name; //姓名@NotBlank
String loanBody;//借款主体@NotBlank
String loanBodyId;//借款主体ID@NotNull
BigDecimal borrowAmount;//借款金额@NotNull
BigDecimal turnover;//月营业额@NotNull
BigDecimal profit; //月利润@NotBlank
String usage;//用途
@NotBlank(groups = {A.clss})
String groupID;//集团IDString source = ""; //来源
String code; //验证码(更换手机号码时使用)
String ipAddress; //ip地址
// 定义两个域
public Interface {}
public Interface{}
}
复制代码
controller
复制代码
@RequestMapping(value = "/regist", method = {RequestMethod.GET, RequestMethod.POST})
@ResponseBody
public Object hualalaRegist(@Validated({HualalaRegistVO.A.class}) HualalaRegistVO registVO, BindingResult bindingResult,
HttpServletRequest request) throws Exception {
if(bindingResult.hasErrors())
return new ResultBean<>(HttpStatus.SC_BAD_REQUEST,"请求参数错误",null);
if (!"dev".equals(profile)) {
registVO.setPhoneNumber(LongdaiUtil.decrypt(registVO.getPhoneNumber()));
registVO.setGroupID(LongdaiUtil.decrypt(registVO.getGroupID()));
}
registVO.setIpAddress(NetworkUtil.getIpAddress(request));
return hualalaService.hualalaRegist(registVO);
}
复制代码
-
custom validation
复制代码
@Documented
@Retention(RUNTIME)
@Target({FIELD, ANNOTATION_TYPE, PARAMETER})
@Constraint(validatedBy = AdultValidator.class)
public @interface Adult {
String message() default "{adult}";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
}
复制代码
复制代码
@Component
public class AdultValidator implements ConstraintValidator<Adult, LocalDate> {
private static final int ADULT_AGE = 18;@Override
public boolean isValid(LocalDate dateOfBirth, ConstraintValidatorContext constraintValidatorContext) {
return dateOfBirth != null && LocalDate.now().minusYears(ADULT_AGE).isAfter(dateOfBirth);
}
}
复制代码
@NotNull
@Past
@Adult
private LocalDate dateOfBirth;