@Valid 注解 的验证之美 和验证类 异常捕获
@Valid 是JSR303 指定的标准 ,hibernate 对其做了实现。
<dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> <version>6.0.13.Final</version> </dependency>
1 使用 只要在 需要验证的 类 ,字段 方法,写上 验证注解,
2 然后在需要使用的地方加上 @Valid 就可以了
验证注解 解释:
需要注意的是 @NotNull 通用 ,@NotBlank 只能修饰String,@NotEmpty 只能修饰集合数组
限制 | 说明 |
---|---|
@Null | 限制只能为null |
@NotNull | 限制必须不为null |
@AssertFalse | 限制必须为false |
@AssertTrue | 限制必须为true |
@DecimalMax(value) | 限制必须为一个不大于指定值的数字 |
@DecimalMin(value) | 限制必须为一个不小于指定值的数字 |
@Digits(integer,fraction) | 限制必须为一个小数,且整数部分的位数不能超过integer,小数部分的位数不能超过fraction |
@Future | 限制必须是一个将来的日期 |
@Max(value) | 限制必须为一个不大于指定值的数字 |
@Min(value) | 限制必须为一个不小于指定值的数字 |
@Past | 限制必须是一个过去的日期 |
@Pattern(value) | 限制必须符合指定的正则表达式 |
@Size(max,min) | 限制字符长度必须在min到max之间 |
@NotEmpty | 验证注解的元素值不为null且不为空(字符串长度不为0、集合大小不为0) |
@NotBlank | 验证注解的元素值不为空(不为null、去除首位空格后长度为0),不同于@NotEmpty,@NotBlank只应用于字符串且在比较时会去除字符串的空格 |
验证注解的元素值是Email,也可以通过正则表达式和flag指定自定义的email格式 |
备注:@Valid 目前默认只在 SpringMvc 的 控制器有效,并且这样写也是无效的 。
1 controller 非顶层方法,也无效
2 service 层也是无效的。
使用验证的一些注意事项
1 @Valid 和 @Validated 效果类似,但是有写时候不一样
2 在对象里面如果对象属性没有验证,而属性的属性需要验证,需要用 @Valid ,不然验证会中断
3 @NotNull 修饰方法参数的时候,需要在参数方法所在类上标注 @Validated 修饰,这时候 @Valid 不起作用
4 在标注方法参数的时候 @NotNull ,@NotBlank @NotEmpty 都一样,只是判断是否空
package com.lomi.controller; import javax.validation.Valid; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import com.alibaba.fastjson.JSONObject; import com.lomi.entity.in.validate.UserIn; import com.lomi.entity.in.validate.UserPakeageIn; import com.lomi.entity.out.FormatOut; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; /** * 1 @Valid 和 @Validated 效果类似,但是有写时候不一样 * 2 在对象里面如果对象属性没有验证,而属性的属性需要验证,需要用 @Valid ,不然验证会中断 * 3 @NotNull 修饰方法参数的时候,需要在参数方法所在类上标注 @Validated 修饰,这时候 @Valid 不起作用 * 4 在标注方法参数的时候 @NotNull ,@NotBlank @NotEmpty 都一样,只是判断是否空 * * * @author ZHANGYUKUN * * */ @Api(tags="Validate测试") @RestController @RequestMapping(value = "/valid") @Validated public class ValidateController extends BaseController { private static final Logger logger = LoggerFactory.getLogger(ValidateController.class); @ApiOperation(value = "单参数") @RequestMapping(value = "t1", method = { RequestMethod.POST }) @ResponseBody public FormatOut t1(@NotBlank String s) throws Exception { System.out.println( JSONObject.toJSONString( s ) ); return null; } @ApiOperation(value = "对象") @RequestMapping(value = "t2", method = { RequestMethod.POST }) @ResponseBody public String t2(@RequestBody @Validated UserIn in) throws Exception { System.out.println( JSONObject.toJSONString( in ) ); return "OK"; } @ApiOperation(value = "2层对象") @RequestMapping(value = "t3", method = { RequestMethod.POST }) @ResponseBody public FormatOut t2( @Valid UserPakeageIn in) throws Exception { System.out.println( JSONObject.toJSONString( in ) ); return null; } }
下面是验证类
package com.lomi.entity.in.validate; import java.util.List; import javax.validation.Valid; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; public class UserPakeageIn { @NotNull(message = "UserPakeageIn-id不能是null") private Long id; @NotBlank(message = "UserPakeageIn-name不能是null") private String name; //标注向下传递验证 @Valid private UserIn user; //@Valid 标记验证向下传递,但是自己不验证 //@Valid private List<UserIn> users; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public UserIn getUser() { return user; } public void setUser(UserIn user) { this.user = user; } public List<UserIn> getUsers() { return users; } public void setUsers(List<UserIn> users) { this.users = users; } }
package com.lomi.entity.in.validate; import java.util.List; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; public class UserIn { @NotNull(message = "UserIn-id不能是null") private Long id; @NotBlank(message = "UserIn-name不能是null") private String name; @NotEmpty(message = "UserIn-skill不能是null") private List<String> skill; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public List<String> getSkill() { return skill; } public void setSkill(List<String> skill) { this.skill = skill; } }
验证框架 异常验证是在进入请求方法之前,需要使用 @ControllerAdvice 而不是 @Component
并且还要标注 @ExceptionHandler(value = Throwable.class) 才能拦截到异常(如果拦截验证类的异常不需要)
package com.lomi.context; import org.springframework.stereotype.Component; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.servlet.HandlerExceptionResolver; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; /** * * 1 @Component 这种写法,没法处理 @Valid 的验证的异常,原因是 验证类异常出现在进入方法之前 * 2 如果需要拦截 验证异常需要 @ControllerAdvice ,可以拦截到进入,并且需要指定@ExceptionHandler(value = Throwable.class) * * 简单的统一异常处理 * @author ZHANGYUKUN * */ //@Component @ControllerAdvice public class GlobalExceptionResolver implements HandlerExceptionResolver { /** *{"msg":true} * @param request * @param response * @param handler * @param ex * @return */ @Override @ExceptionHandler(value = Throwable.class) public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { System.out.println( "异常:" + ex ); String exMsg = null; if( ex instanceof MethodArgumentNotValidException){ exMsg = ((MethodArgumentNotValidException)ex).getBindingResult().getFieldErrors().get(0).getDefaultMessage(); }else{ exMsg = ex.getMessage(); } try { response.setCharacterEncoding("UTF-8"); response.setContentType("application/json; charset=utf-8"); PrintWriter writer = response.getWriter(); writer.write("{\"exMsg\":\""+ exMsg +"\"}" ); writer.flush(); } catch (IOException e) { e.printStackTrace(); } //不能返回null,不要spring或默认返回一个 return new ModelAndView(); //return null; } }
能耍的时候就一定要耍,不能耍的时候一定要学。
天道酬勤,贵在坚持
posted on 2020-03-03 16:40 zhangyukun 阅读(520) 评论(0) 编辑 收藏 举报