智能摘要文章源自JAVA秀-https://www.javaxiu.com/66728.html
在控制器类的方法里自己写校验逻辑代码当然也可以,只是代码比较丑陋,有点"low"。当请求URI不满足正则表达式时,客户端将收到404错误码。用户输入的值,必须是FlagValidator注解规定的那些值其中之一。常见的场景之一是,查询某信息时要输入开始时间和结束时间。MyBatis、Redis、MongoDB、ES、分库分表、读写分离、SpringMVC、Webflux、权限、WebSocket、Dubbo、RabbitMQ、RocketMQ、Kafka、性能测试等等内容。文章源自JAVA秀-https://www.javaxiu.com/66728.html
原文约 5527 字 | 图片 8 张 | 建议阅读 12 分钟 | 评价反馈文章源自JAVA秀-https://www.javaxiu.com/66728.html
一波带走,SpringBoot 中的各种参数校验方案汇总
点击关注 ? Java基基 文章源自JAVA秀-https://www.javaxiu.com/66728.html
点击上方“Java基基”,选择“设为星标”文章源自JAVA秀-https://www.javaxiu.com/66728.html
做积极的人,而不是积极废人!文章源自JAVA秀-https://www.javaxiu.com/66728.html
每天 14:00 更新文章,每天掉亿点点头发...文章源自JAVA秀-https://www.javaxiu.com/66728.html
文章源自JAVA秀-https://www.javaxiu.com/66728.html
源码精品专栏文章源自JAVA秀-https://www.javaxiu.com/66728.html
-
原创 | Java 2021 超神之路,很肝~文章源自JAVA秀-https://www.javaxiu.com/66728.html
-
中文详细注释的开源项目文章源自JAVA秀-https://www.javaxiu.com/66728.html
-
RPC 框架 Dubbo 源码解析文章源自JAVA秀-https://www.javaxiu.com/66728.html
-
网络应用框架 Netty 源码解析文章源自JAVA秀-https://www.javaxiu.com/66728.html
-
消息中间件 RocketMQ 源码解析文章源自JAVA秀-https://www.javaxiu.com/66728.html
-
数据库中间件 Sharding-JDBC 和 MyCAT 源码解析文章源自JAVA秀-https://www.javaxiu.com/66728.html
-
作业调度中间件 Elastic-Job 源码解析文章源自JAVA秀-https://www.javaxiu.com/66728.html
-
分布式事务中间件 TCC-Transaction 源码解析文章源自JAVA秀-https://www.javaxiu.com/66728.html
-
Eureka 和 Hystrix 源码解析文章源自JAVA秀-https://www.javaxiu.com/66728.html
-
Java 并发源码文章源自JAVA秀-https://www.javaxiu.com/66728.html
来源:blog.csdn.net/jinjiankang/文章源自JAVA秀-https://www.javaxiu.com/66728.html
article/details/8971149文章源自JAVA秀-https://www.javaxiu.com/66728.html
-
1、前言文章源自JAVA秀-https://www.javaxiu.com/66728.html
-
2、PathVariable校验文章源自JAVA秀-https://www.javaxiu.com/66728.html
-
3、方法参数校验文章源自JAVA秀-https://www.javaxiu.com/66728.html
-
4、表单对象/VO对象校验文章源自JAVA秀-https://www.javaxiu.com/66728.html
-
5、自定义校验规则文章源自JAVA秀-https://www.javaxiu.com/66728.html
-
5.1 自定义注解校验文章源自JAVA秀-https://www.javaxiu.com/66728.html
-
5.2 分组校验文章源自JAVA秀-https://www.javaxiu.com/66728.html
-
6、异常拦截器文章源自JAVA秀-https://www.javaxiu.com/66728.html
-
7、相关标准文章源自JAVA秀-https://www.javaxiu.com/66728.html
-
8、参数校验原理文章源自JAVA秀-https://www.javaxiu.com/66728.html
-
9、本文源码文章源自JAVA秀-https://www.javaxiu.com/66728.html
-
10、同时校验2个或更多个字段/参数文章源自JAVA秀-https://www.javaxiu.com/66728.html
文章源自JAVA秀-https://www.javaxiu.com/66728.html
1、前言
在控制器类的方法里自己写校验逻辑代码当然也可以,只是代码比较丑陋,有点“low”。业界有更好的处理方法,分别阐述如下。文章源自JAVA秀-https://www.javaxiu.com/66728.html
基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能。文章源自JAVA秀-https://www.javaxiu.com/66728.html
项目地址:https://github.com/YunaiV/ruoyi-vue-pro文章源自JAVA秀-https://www.javaxiu.com/66728.html
2、PathVariable校验
@GetMapping("/path/{group:[a-zA-Z0-9_]+}/{userid}")@ResponseBodypublic String path(@PathVariable("group") String group, @PathVariable("userid") Integer userid) { return group + ":" + userid;}
用法是:路径变量:正则表达式。当请求URI不满足正则表达式时,客户端将收到404错误码。不方便的地方是,不能通过捕获异常的方式,向前端返回统一的、自定义格式的响应参数。文章源自JAVA秀-https://www.javaxiu.com/66728.html
基于微服务的思想,构建在 B2C 电商场景下的项目实战。核心技术栈,是 Spring Boot + Dubbo 。未来,会重构成 Spring Cloud Alibaba 。文章源自JAVA秀-https://www.javaxiu.com/66728.html
项目地址:https://github.com/YunaiV/onemall文章源自JAVA秀-https://www.javaxiu.com/66728.html
3、方法参数校验
@GetMapping("/validate1")@ResponseBodypublic String validate1( @Size(min = 1,max = 10,message = "姓名长度必须为1到10")@RequestParam("name") String name, @Min(value = 10,message = "年龄最小为10")@Max(value = 100,message = "年龄最大为100") @RequestParam("age") Integer age) { return "validate1";}
如果前端传递的参数不满足规则,则抛出异常。注解Size、Min、Max来自validation-api.jar,更多注解参见相关标准 小节。文章源自JAVA秀-https://www.javaxiu.com/66728.html
4、表单对象/VO对象校验
当参数是VO时,可以在VO类的属性上添加校验注解。文章源自JAVA秀-https://www.javaxiu.com/66728.html
public class User { @Size(min = 1,max = 10,message = "姓名长度必须为1到10") private String name; @NotEmpty private String firstName; @Min(value = 10,message = "年龄最小为10")@Max(value = 100,message = "年龄最大为100") private Integer age; @Future @JSONField(format="yyyy-MM-dd HH:mm:ss") private Date birth; 。。。}
其中,Future注解要求必须是相对当前时间来讲“未来的”某个时间。文章源自JAVA秀-https://www.javaxiu.com/66728.html
@PostMapping("/validate2")@ResponseBodypublic User validate2(@Valid @RequestBody User user){ return user;}
5、自定义校验规则
5.1 自定义注解校验
需要自定义一个注解类和一个校验类。文章源自JAVA秀-https://www.javaxiu.com/66728.html
import javax.validation.Constraint;import javax.validation.Payload;import java.lang.annotation.*;@Documented@Retention(RetentionPolicy.RUNTIME)@Target({ElementType.PARAMETER,ElementType.FIELD})@Constraint(validatedBy = FlagValidatorClass.class)public @interface FlagValidator { // flag的有效值,多个使用,隔开 String values(); // flag无效时的提示内容 String message() default "flag必须是预定义的那几个值,不能随便写"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {};}import javax.validation.ConstraintValidator;import javax.validation.ConstraintValidatorContext;public class FlagValidatorClass implements ConstraintValidator<FlagValidator,Object> { /** * FlagValidator注解规定的那些有效值 */ private String values; @Override public void initialize(FlagValidator flagValidator) { this.values = flagValidator.values(); } /** * 用户输入的值,必须是FlagValidator注解规定的那些值其中之一。 * 否则,校验不通过。 * @param value 用户输入的值,如从前端传入的某个值 */ @Override public boolean isValid(Object value, ConstraintValidatorContext constraintValidatorContext) { // 切割获取值 String[] value_array = values.split(","); Boolean isFlag = false; for (int i = 0; i < value_array.length; i++){ // 存在一致就跳出循环 if (value_array[i] .equals(value)){ isFlag = true; break; } } return isFlag; }}
使用我们自定义的注解:文章源自JAVA秀-https://www.javaxiu.com/66728.html
public class User { // 前端传入的flag值必须是1或2或3,否则校验失败 @FlagValidator(values = "1,2,3") private String flag ; 。。。}
5.2 分组校验
import org.hibernate.validator.constraints.Length;import javax.validation.constraints.Min;import javax.validation.constraints.NotNull;public class Resume { public interface Default { } public interface Update { } @NotNull(message = "id不能为空", groups = Update.class) private Long id; @NotNull(message = "名字不能为空", groups = Default.class) @Length(min = 4, max = 10, message = "name 长度必须在 {min} - {max} 之间", groups = Default.class) private String name; @NotNull(message = "年龄不能为空", groups = Default.class) @Min(value = 18, message = "年龄不能小于18岁", groups = Default.class) private Integer age; 。。。} /** * 使用Defaul分组进行验证 * @param resume * @return */ @PostMapping("/validate5") public String addUser(@Validated(value = Resume.Default.class) @RequestBody Resume resume) { return "validate5"; } /** * 使用Default、Update分组进行验证 * @param resume * @return */ @PutMapping("/validate6") public String updateUser(@Validated(value = {Resume.Update.class, Resume.Default.class}) @RequestBody Resume resume) { return "validate6"; }
建立了两个分组,名称分别为Default、Update。POST方法提交时使用Defaut分组的校验规则,PUT方法提交时同时使用两个分组规则。文章源自JAVA秀-https://www.javaxiu.com/66728.html
6、异常拦截器
通过设置全局异常处理器,统一向前端返回校验失败信息。文章源自JAVA秀-https://www.javaxiu.com/66728.html
import com.scj.springbootdemo.WebResult;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.util.CollectionUtils;import org.springframework.validation.ObjectError;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.ConstraintViolation;import javax.validation.ConstraintViolationException;import java.util.List;import java.util.Set;/** * 全局异常处理器 */@ControllerAdvicepublic class GlobalExceptionHandler { private Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class); /** * 用来处理bean validation异常 * @param ex * @return */ @ExceptionHandler(ConstraintViolationException.class) @ResponseBody public WebResult resolveConstraintViolationException(ConstraintViolationException ex){ WebResult errorWebResult = new WebResult(WebResult.FAILED); Set<ConstraintViolation<?>> constraintViolations = ex.getConstraintViolations(); if(!CollectionUtils.isEmpty(constraintViolations)){ StringBuilder msgBuilder = new StringBuilder(); for(ConstraintViolation constraintViolation :constraintViolations){ msgBuilder.append(constraintViolation.getMessage()).append(","); } String errorMessage = msgBuilder.toString(); if(errorMessage.length()>1){ errorMessage = errorMessage.substring(0,errorMessage.length()-1); } errorWebResult.setInfo(errorMessage); return errorWebResult; } errorWebResult.setInfo(ex.getMessage()); return errorWebResult; } @ExceptionHandler(MethodArgumentNotValidException.class) @ResponseBody public WebResult resolveMethodArgumentNotValidException(MethodArgumentNotValidException ex){ WebResult errorWebResult = new WebResult(WebResult.FAILED); List<ObjectError> objectErrors = ex.getBindingResult().getAllErrors(); if(!CollectionUtils.isEmpty(objectErrors)) { StringBuilder msgBuilder = new StringBuilder(); for (ObjectError objectError : objectErrors) { msgBuilder.append(objectError.getDefaultMessage()).append(","); } String errorMessage = msgBuilder.toString(); if (errorMessage.length() > 1) { errorMessage = errorMessage.substring(0, errorMessage.length() - 1); } errorWebResult.setInfo(errorMessage); return errorWebResult; } errorWebResult.setInfo(ex.getMessage()); return errorWebResult; }}
7、相关标准
JSR 303 是Bean验证的规范 ,Hibernate Validator 是该规范的参考实现,它除了实现规范要求的注解外,还额外实现了一些注解。validation-api-1.1.0.jar 包括如下约束注解:文章源自JAVA秀-https://www.javaxiu.com/66728.html
文章源自JAVA秀-https://www.javaxiu.com/66728.html
hibernate-validator-5.3.6.jar 包括如下约束注解:文章源自JAVA秀-https://www.javaxiu.com/66728.html
文章源自JAVA秀-https://www.javaxiu.com/66728.html
8、参数校验原理
这篇文章 写得比较深入,我没有太理解。文章源自JAVA秀-https://www.javaxiu.com/66728.html
9、本文源码
公司不让上传源码到GitHub,可以参加这篇文章。文章源自JAVA秀-https://www.javaxiu.com/66728.html
10、同时校验2个或更多个字段/参数
常见的场景之一是,查询某信息时要输入开始时间和结束时间。显然,结束时间要≥开始时间。可以在查询VO类上使用自定义注解,下面的例子来自这里。划重点:@ValidAddress使用在类上。文章源自JAVA秀-https://www.javaxiu.com/66728.html
@ValidAddresspublic class Address { @NotNull @Size(max = 50) private String street1; @Size(max = 50) private String street2; @NotNull @Size(max = 10) private String zipCode; @NotNull @Size(max = 20) private String city; @Valid @NotNull private Country country; // Getters and setters}public class Country { @NotNull @Size(min = 2, max = 2) private String iso2; // Getters and setters}@Documented@Target(TYPE)@Retention(RUNTIME)@Constraint(validatedBy = { MultiCountryAddressValidator.class })public @interface ValidAddress { String message() default "{com.example.validation.ValidAddress.message}"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {};}public class MultiCountryAddressValidator implements ConstraintValidator<ValidAddress, Address> { public void initialize(ValidAddress constraintAnnotation) { } @Override public boolean isValid(Address address, ConstraintValidatorContext constraintValidatorContext) { Country country = address.getCountry(); if (country == null || country.getIso2() == null || address.getZipCode() == null) { return true; } switch (country.getIso2()) { case "FR": return // Check if address.getZipCode() is valid for France case "GR": return // Check if address.getZipCode() is valid for Greece default: return true; } }}
文章源自JAVA秀-https://www.javaxiu.com/66728.html
欢迎加入我的知识星球,一起探讨架构,交流源码。加入方式,长按下方二维码噢:文章源自JAVA秀-https://www.javaxiu.com/66728.html
文章源自JAVA秀-https://www.javaxiu.com/66728.html
已在知识星球更新源码解析如下:文章源自JAVA秀-https://www.javaxiu.com/66728.html
文章源自JAVA秀-https://www.javaxiu.com/66728.html
文章源自JAVA秀-https://www.javaxiu.com/66728.html
文章源自JAVA秀-https://www.javaxiu.com/66728.html
文章源自JAVA秀-https://www.javaxiu.com/66728.html
最近更新《芋道 SpringBoot 2.X 入门》系列,已经 101 余篇,覆盖了 MyBatis、Redis、MongoDB、ES、分库分表、读写分离、SpringMVC、Webflux、权限、WebSocket、Dubbo、RabbitMQ、RocketMQ、Kafka、性能测试等等内容。文章源自JAVA秀-https://www.javaxiu.com/66728.html
提供近 3W 行代码的 SpringBoot 示例,以及超 6W 行代码的电商微服务项目。文章源自JAVA秀-https://www.javaxiu.com/66728.html
获取方式:点“在看”,关注公众号并回复 666 领取,更多内容陆续奉上。文章源自JAVA秀-https://www.javaxiu.com/66728.html
文章源自JAVA秀-https://www.javaxiu.com/66728.html
文章有帮助的话,在看,转发吧。谢谢支持哟 (*^__^*)文章源自JAVA秀-https://www.javaxiu.com/66728.html

评论