SpringBoot 之使用 Hibernate Validator验证参数
1、在 pom 文件引入依赖
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.13.Final</version>
</dependency>
2、在请求实体类中添加注解
import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.NotEmpty;
/**
* @title: CheckAccountRequest
* @description: TODO
* @date 2019/5/30 11:34
*/
public class CheckAccountRequest {
@Length(max = 16,min = 5, message = "userAccount 长度在4到16位!")
@NotEmpty(message = "userAccount 不能为空!")
private String userAccount;
public String getUserAccount() {
return userAccount;
}
public void setUserAccount(String userAccount) {
this.userAccount = userAccount;
}
}
3、在控制层中添加注解(@Validated)
import com.alibaba.fastjson.JSONObject;
import com.huajie.servera.common.CommonResult;
import com.huajie.servera.entity.request.*;
import com.huajie.servera.service.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;
//import org.springframework.validation.annotation.Validated;
/**
* @title: UsersController
* @description: TODO
* @date 2019/5/24 9:23
*/
@Controller
@RequestMapping("/users")
public class UsersController {
private final static Logger logger = LoggerFactory.getLogger(UsersController.class);
/**
* 校验用户是否存在(不需要验证token登录)
* @param
* @return
*/
@RequestMapping("/checkAccount")
@ResponseBody
public CommonResult checkAccount(@Validated CheckAccountRequest checkAccountRequest) {
try {
return userService.checkAccount(checkAccountRequest);
} catch (Exception e) {
e.printStackTrace();
return CommonResult.error();
}
}
}
4、自定义异常处理后的返回类
/**
* @title: ValidatorResult
* @description: Validator校验公共返回实体
* @date 2019/5/31 14:19
*/
public class ValidatorResult {
private Integer code;
private String msg;
private Object data;
public ValidatorResult () {
}
public ValidatorResult(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
public Integer getCode() {
return code;
}
public String getMsg() {
return msg;
}
public Object getResult() {
return data;
}
public void setCode(Integer code) {
this.code = code;
}
public void setMsg(String msg) {
this.msg = msg;
}
public void setResult(Object data) {
this.data = data;
}
}
5、自定义异常处理
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.validation.ConstraintViolationException;
/**
* @author pzf
* @title: GlobalExceptionHandler
* @description: 全局异常处理类,主要用来处理参数校验没有通过时的异常信息
* @date 2019/5/31 14:20
*/
@ControllerAdvice
@Controller
public class GlobalExceptionHandler {
/**
* 方法参数校验异常
* @param e
* @return
*/
@ExceptionHandler(value = ConstraintViolationException.class)
public ValidatorResult constraintViolationException(Exception e) {
if (e.getMessage() != null) {
int index = e.getMessage().indexOf(":");
return new ValidatorResult(HttpStatus.BAD_REQUEST.value(), index != -1 ?
e.getMessage().substring(index + 1).trim() : e.getMessage());
}
return new ValidatorResult(HttpStatus.BAD_REQUEST.value(), null);
}
/**
* Bean 校验异常
* @param e
* @return
* @throws Exception
*/
//@ExceptionHandler这个注解是指当controller中抛出这个指定的异常类的时候,都会转到这个方法中来处理异常
// MethodArgumentNotValidException.class 自定义验证用该类
// BindException.class
// 说明:该方法在控制层使用 @Validated @RequestBody 会报错,例: public Result<Integer> saveItem(@Validated @RequestBody EhrExamineReportDto dto) {})
// 改进版见下一个方法
@ResponseBody
@ExceptionHandler(value = {MethodArgumentNotValidException.class,BindException.class})
public ValidatorResult notValidExceptionHandler(BindException e) throws Exception {
ValidatorResult ret = new ValidatorResult();
ret.setCode(HttpStatus.BAD_REQUEST.value());
if (e.getBindingResult() != null && !CollectionUtils.isEmpty(e.getBindingResult().getAllErrors())) {
ret.setMsg(e.getBindingResult().getAllErrors().get(0).getDefaultMessage());
} else {
ret.setMsg(e.getMessage());
}
return ret;
}
// 改进版:
@ResponseBody
@ExceptionHandler(MethodArgumentNotValidException.class)
public Result handleMethodArgumentNotValidException(MethodArgumentNotValidException m) {
BindingResult bindingResult = m.getBindingResult();
List<FieldError> fieldErrors = bindingResult.getFieldErrors();
int size = fieldErrors.size();
StringBuilder errMsg = new StringBuilder(size * 16);
for (int i = 0; i < size; i++) {
if (i > 0) {
errMsg.append(",");
}
FieldError fieldError = fieldErrors.get(i);
errMsg.append(fieldError.getField()).append(":").append(fieldError.getDefaultMessage());
}
return Result.failed(ResultCode.FAIL, errMsg.toString());
}
}
这里说一下遇到的坑: 上面 notValidExceptionHandler(BindException e){……}方法中,最开始写的是 notValidExceptionHandler(MethodArgumentNotValidException e){……},运行中一致报错,捕获不到.
传参MethodArgumentNotValidException 是自定义规则异常才使用的,默认的验证规则用BindException
传错参MethodArgumentNotValidException 报错
java.lang.IllegalStateException: Could not resolve parameter [0] in public com.huajie.servera.common.exception.ValidatorResult com.huajie.servera.common.exception.GlobalExceptionHandler.notValidExceptionHandler(org.springframework.web.bind.MethodArgumentNotValidException) throws java.lang.Exception: No suitable resolver
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:164)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:134)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
at org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver.doResolveHandlerMethodException(ExceptionHandlerExceptionResolver.java:412)
at org.springframework.web.servlet.handler.AbstractHandlerMethodExceptionResolver.doResolveException(AbstractHandlerMethodExceptionResolver.java:61)
at org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver.resolveException(AbstractHandlerExceptionResolver.java:140)
at org.springframework.web.servlet.handler.HandlerExceptionResolverComposite.resolveException(HandlerExceptionResolverComposite.java:79)
at org.springframework.web.servlet.DispatcherServlet.processHandlerException(DispatcherServlet.java:1298)
at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1110)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1056)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:908)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:660)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.boot.actuate.web.trace.servlet.HttpTraceFilter.doFilterInternal(HttpTraceFilter.java:90)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:92)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:117)
at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:106)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:200)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:836)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1747)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
2019-05-31 16:24:43.112 WARN 13676 --- [nio-8782-exec-3] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'checkAccountRequest' on field 'userAccount': rejected value [1234]; codes [Length.checkAccountRequest.userAccount,Length.userAccount,Length.java.lang.String,Length]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [checkAccountRequest.userAccount,userAccount]; arguments []; default message [userAccount],16,5]; default message [userAccount 长度在4到16位!]]
6、返回结果
7、请求实体中常用的注解
7.1 内置注解
Bean 校验注解
Hibernate Validator 包含一组基本的常用约束, 其中最重要的是 Bean Validation 规范定义的约束,所有这些约束都适用于字段/属性级别,Bean验证规范中没有定义类级别约束。
限制 | 说明 |
---|---|
@AssertFalse | 限制必须为false |
@AssertTrue | 限制必须为true |
@DecimalMax | 限制必须为一个不大于指定值的数字 |
@DecimalMin | 限制必须为一个不小于指定值的数字 |
@Digits | 限制必须为一个小数,且整数部分的位数不能超过integer,小数部分的位数不能超过fraction |
@Null | 限制只能为null |
@NotNull | 限制必须不为null |
验证注解的元素值是Email,也可以通过正则表达式和flag指定自定义的email格式 | |
@Future | 限制必须是一个将来的日期 |
@Max | 限制必须为一个不大于指定值的数字 |
@Min | 限制必须为一个不小于指定值的数字 |
@NotBlank | 验证注解的元素值不为null且去除空格后长度不为0,@NotBlank只用于字符串 |
@NotEmpty | 验证注解的元素值不为null且不为空,支持字符串、集合、Map和数组类型 |
@Past | 限制必须是一个过去的日期 |
@Pattern | 限制必须符合指定的正则表达式 |
@Range | 限制必须在合适的范围内 |
@Size | 限制字符长度必须在min到max之间 |
7.2 附加注解
Hibernate Validator 还提供了几个有用的自定义约束,如下所示。除了一个例外,这些约束也适用于字段/属性级别,只有@ScriptAssert类级别约束。
限制 | 说明 |
---|---|
@CreditCardNumber | 检查带注释的字符序列是否通过了Luhn校验和测试 |
@Currency | 检查带注释的货币单位javax.money.MonetaryAmount是否为指定货币单位的一部分 |
@EAN | 检查带注释的字符序列是否为有效的EAN条形码。type确定条形码的类型。默认值为EAN-13 |
@ISBN | 检查带注释的字符序列是否为有效的ISBN。type确定ISBN的类型。默认值为ISBN-13 |
@Length | 验证该注释字符序列是间min和max包含 |
@Range | 检查带注释的值是否在(包括)指定的最小值和最大值之间 |
@Length | 限制必须为true |
@Range | 限制必须为一个不大于指定值的数字 |
@SafeHtml | 检查带注释的值是否包含潜在的恶意片段 |
@UniqueElements | 检查带注释的集合是否仅包含唯一元素 |
@URL | 根据RFC2396检查带注释的字符序列是否为有效URL |
8、添加枚举校验
8.1 创建注解
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import javax.validation.Constraint;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import javax.validation.Payload;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* @ClassName: EnumValue
* @Description:
* @author:
* @Date:2020/11/9 19:29
**/
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = EnumValue.Validator.class)
public @interface EnumValue {
String message() default "参数检验失败!";
Class<? extends Enum<?>> enumClass();
String method() default "getValue";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
class Validator implements ConstraintValidator<EnumValue, Object> {
private static final Logger logger = LoggerFactory.getLogger(Validator.class);
private Class<? extends Enum<?>> enumClass;
private List<Object> values = new ArrayList<>();
@Override
public void initialize(EnumValue enumValue) {
try {
enumClass = enumValue.enumClass();
Object[] objects = enumClass.getEnumConstants();
Method method = null;
try {
method = enumClass.getMethod(enumValue.method());
} catch (NoSuchMethodException ne) {
logger.error(String.format("枚举对象: %s 缺少名为: %s 的方法", enumClass.getName(), enumValue.method()));
}
if (Objects.isNull(method))
throw new RuntimeException(String.format("枚举对象: %s 缺少名为: %s 的方法", enumClass.getName(), enumValue.method()));
Object value;
for (Object obj : objects) {
value = method.invoke(obj);
values.add(value);
}
} catch (Exception e) {
logger.error("处理枚举校验异常:{}", e);
}
}
@Override
public boolean isValid(Object value, ConstraintValidatorContext constraintValidatorContext) {
if (value == null) return Boolean.TRUE;
if (value instanceof String) {
String valueStr = (String) value;
return StringUtils.isEmpty(valueStr) || values.contains(value);
}
return Objects.isNull(value) || values.contains(value);
}
}
}
8.2 创建枚举类
import lombok.Getter;
/**
* @ClassName: ContentManagerEnumeration
* @Description:
* @author:
* @Date:2020/11/9 19:09
**/
public class ContentEnums {
/**
* 启用状态:1-停用(默认);2-启用
*/
@Getter
public enum EnableStatus {
停用(1), 启用(2);
private int value;
EnableStatus(int value) {
this.value = value;
}
}
/**
* 产品状态:1-未上架;2-已上架;3-已下架
*/
@Getter
public enum ProStatus {
未上架(1), 已上架(2), 已下架(3);
private int value;
ProductStatus(int value) {
this.value = value;
}
}
/**
* 产品类型
*/
@Getter
public enum ProType {
景点(1), 酒店(2);
private int value;
ProType(int value) {
this.value = value;
}
}
@Getter
public enum ProductLevel {
A级(1), AA级(2), AAA级(3), AAAA级(4), AAAAA级(5);
private int value;
ProductLevel(int value) {
this.value = value;
}
}
}
8.3 实体类添加注解
import common.annotations.EnumValue;
import common.enumeration.ContentEnums;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Pattern;
import java.io.Serializable;
import java.util.Date;
/**
* @author pzf
* @date 2020/11/09
*/
@Data
public class ProductPlace implements Serializable {
private Long id;
@EnumValue(enumClass = ContentManagerEnumeration.ProductType.class, message = "产品类型不合法!")
private Integer productType;
@EnumValue(enumClass = ContentManagerEnumeration.ProductStatus.class, message = "产品状态不合法!")
private Integer status;
@Pattern(regexp = "^(?:\\d{1,3}|1000)$", message = "排序权重区间范围:0-1000 整数")
@NotEmpty(message = "排序权重不能为空!")
private String weight;
@EnumValue(enumClass = ContentManagerEnumeration.Level.class, message = "等级不合法!")
private Integer level;
private String area;
}
8.4 控制层
import javax.validation.Valid;
……
@RequestMapping(value = "/update", method = RequestMethod.POST)
public CommonResult update(@RequestBody @Valid ProductPlace productPlace) {
// todo ……
}
9、入参是集合对象时,处理注解
9.1 重写集合
import javax.validation.Valid;
import java.util.*;
/**
* @ClassName: ValidList
* @Description:
* @author:
* @Date:2020/11/10
**/
public class ValidList<E> implements List<E> {
@Valid
private List<E> list = new ArrayList<>();
public List<E> getList() {
return list;
}
public void setList(List<E> list) {
this.list = list;
}
@Override
public int size() {
return list.size();
}
@Override
public boolean isEmpty() {
return list.isEmpty();
}
@Override
public boolean contains(Object o) {
return list.contains(o);
}
@Override
public Iterator<E> iterator() {
return list.iterator();
}
@Override
public Object[] toArray() {
return list.toArray();
}
@Override
public <T> T[] toArray(T[] a) {
return list.toArray(a);
}
@Override
public boolean add(E e) {
return list.add(e);
}
@Override
public boolean remove(Object o) {
return list.remove(o);
}
@Override
public boolean containsAll(Collection<?> c) {
return list.contains(c);
}
@Override
public boolean addAll(Collection<? extends E> c) {
return list.addAll(c);
}
@Override
public boolean addAll(int index, Collection<? extends E> c) {
return list.addAll(index, c);
}
@Override
public boolean removeAll(Collection<?> c) {
return list.removeAll(c);
}
@Override
public boolean retainAll(Collection<?> c) {
return list.retainAll(c);
}
@Override
public void clear() {
list.clear();
}
@Override
public E get(int index) {
return list.get(index);
}
@Override
public E set(int index, E element) {
return list.set(index, element);
}
@Override
public void add(int index, E element) {
list.add(index, element);
}
@Override
public E remove(int index) {
return list.remove(index);
}
@Override
public int indexOf(Object o) {
return list.indexOf(o);
}
@Override
public int lastIndexOf(Object o) {
return list.lastIndexOf(o);
}
@Override
public ListIterator<E> listIterator() {
return list.listIterator();
}
@Override
public ListIterator<E> listIterator(int index) {
return list.listIterator(index);
}
@Override
public List<E> subList(int fromIndex, int toIndex) {
return list.subList(fromIndex, toIndex);
}
}
9.2 控制层写法
import javax.validation.Valid;
……
@RequestMapping(value = "/update", method = RequestMethod.POST)
public CommonResult update(@RequestBody @Valid ValidList<ProductPlace> productPlace) {
// todo ……
}
10、分组
10.1 定义组
package common.annotations;
/**
* @ClassName: Insert
* @Description:
* @author:
* @Date:2020/11/10 20:15
**/
public interface Insert {
}
package common.annotations;
/**
* @ClassName: Insert
* @Description:
* @author:
* @Date:2020/11/10 20:15
**/
public interface Update {
}
10.2 实体类校验注解中添加组信息
import common.annotations.EnumValue;
import common.enumeration.ContentEnums;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Pattern;
import java.io.Serializable;
import java.util.Date;
/**
* @author pzf
* @date 2020/11/09
*/
@Data
public class ProductPlace implements Serializable {
private Long id;
@EnumValue(enumClass = ContentManagerEnumeration.ProductType.class, message = "产品类型不合法!")
private Integer productType;
@EnumValue(enumClass = ContentManagerEnumeration.ProductStatus.class, message = "产品状态不合法!")
private Integer status;
@Pattern(regexp = "^(?:\\d{1,3}|1000)$", message = "排序权重区间范围:0-1000 整数")
@NotEmpty(groups = {Insert.class},message = "排序权重不能为空!")
private String weight;
@EnumValue(groups = {Insert.class,Update.class}, enumClass = ContentManagerEnumeration.Level.class, message = "等级不合法!")
private Integer level;
private String area;
@Size(min = 1, max = 50, message = "公告标题长度在0-50 字符之间!")
@NotEmpty(groups = {Insert.class},message = "公告标题不能为空!")
private String title;
}
10.3 控制层写法
import org.springframework.validation.annotation.Validated;
@RequestMapping(value = "/save", method = RequestMethod.POST)
public CommonResult save(@RequestBody @Validated({Insert.class}) ProductPlace productPlace) {
// todo ……
}
11、扩展 @Validated 和 @Valid 区别
项目 | @Validated | @Valid |
---|---|---|
来源 | Spring Validation验证框架提供(Spring’s JSR-303规范,是标准JSR-303的一个变种) | javax提供了@Valid(标准JSR-303规范),配合BindingResult可以直接提供参数验证结果。 |
分组 | 提供分组功能,可以在入参验证时,根据不同的分组采用不同的验证机制。 | 没有分组功能 |
注解 | 用在类型、方法和方法参数上。但不能用于成员属性(field) | 可以用在方法、构造函数、方法参数和成员属性(field)上 |
嵌套验证 | 无 | 一个待验证的pojo类,其中还包含了待验证的对象,需要在待验证对象上注解@valid,才能验证待验证对象中的成员属性 |
.