validator是用来校验参数使用!

一般来说校验参数的工作可以放在前端去执行,但是假如有人不经过前端直接调用后端的接口呢?很可能就出现非法数据而导致一些问题,所有服务端也要做数据的校验。

前端校验是为了提高用户的体验度,后端校验则是为了保证数据的安全性。

校验参数基本上是一个体力活,而且冗余代码繁多,也影响代码的可读性,我们需要一个比较优雅的方式来解决这个问题。Hibernate Validator 框架刚好解决了这个问题,可以以很优雅的方式实现参数的校验,让业务代码和校验逻辑分开,不再编写重复的校验逻辑。

hibernate-validator优势:  1.验证逻辑与业务逻辑之间进行了分离,降低了程序耦合度

2.统一且规范的验证方式,无需你再次编写重复的验证代码

             3.你将更专注于你的业务,将这些繁琐的事情统统丢在一边

hibernate-validator的maven坐标:

其实spring-boot-starter-web中已经依赖了hibernate-validator

<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.18.Final</version>
</dependency>

hibernate-validator提供的校验方式为在类的属性上加入相应的注解来达到校验的目的。hibernate-validator提供的用于校验的注解如下:

注解 说明
@AssertTrue 用于boolean字段,该字段只能为true
@AssertFalse 用于boolean字段,该字段只能为false
@CreditCardNumber 对信用卡号进行一个大致的验证
@DecimalMax 只能小于或等于该值
@DecimalMin 只能大于或等于该值
@Email 检查是否是一个有效的email地址
@Future 检查该字段的日期是否是属于将来的日期
@Length(min=,max=) 检查所属的字段的长度是否在min和max之间,只能用于字符串
@Max 该字段的值只能小于或等于该值
@Min 该字段的值只能大于或等于该值
@NotNull 不能为null
@NotBlank 不能为空,检查时会将空格忽略
@NotEmpty 不能为空,这里的空是指空字符串
@Pattern(regex=) 被注释的元素必须符合指定的正则表达式
@URL(protocol=,host,port) 检查是否是一个有效的URL,如果提供了protocol,host等,则该URL还需满足提供的条件

入门案例

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath/>
</parent>
<groupId>com.xiaoteng</groupId>
<artifactId>validator-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!--
spring-boot-starter-web中已经依赖了hibernate-validator
-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.18.Final</version>
</dependency>
-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
</project>

实体类

package com.entity;

import lombok.Data;
import org.hibernate.validator.constraints.Length; import javax.validation.constraints.*; /**
* @author xiaozhuang
* @date 2022年02月26日 14:03
*/
@Data
public class User {
@NotNull(message = "用户id不能为空(null)")
private int id;
@NotEmpty(message = "用户名不能为空")
@Length(max = 50, message = "用户名长度不能超过50")
private String userName;
@Max(value = 100, message = "年龄最大为100")
@Min(value = 18, message = "年龄最小为18")
private int age;
@Pattern(regexp = "[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$",
message = "邮箱格式不正确")
private String email; }

controller

package com.controller;

import com.entity.User;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import javax.validation.constraints.NotBlank; /**
* @author xiaozhuang
* @date 2022年02月26日 14:13
*/
@RestController
@RequestMapping("/user")
@Validated //开启校验功能
public class UserController {
//简单数据类型校验
@RequestMapping("/byId")
public String delete(@NotBlank(message = "id不能为空") String id){
System.out.println("id为..." + id);
return "OK";
}
//对象属性校验
@RequestMapping("/save")
public String save(@Validated User user){
System.out.println("save..." + user);
return "OK";
}
}
package com;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import javax.swing.*; /**
* @author xiaozhuang
* @date 2022年02月26日 14:18
*/
@SpringBootApplication
public class ValidatorApp {
public static void main(String[] args) {
SpringApplication.run(ValidatorApp.class,args);
}
}

启动项目,然后访问。

首先是简单类型的校验:

1.正常访问

2.不传id

再看控制台报错

接下来是实体类的校验:

1.传一个id的报错

这里只有三个都传了对于的值才不会报错。并且用了它有几个问题需要处理。

1.页面返回错误也不合适,需要做一个全局的异常处理

2.这里的参数校验,特别是对象时,当已经有一个参数校验不通过了以后,其他的参数也就不需要再校验了,就应该直接返回错误信息了,而不是一个没有通过,其他的还接着校验,需要做一个指定校验时使用快速失败返回模式

全局异常处理: 这里只是针对validator的异常处理

package com.config;

import org.springframework.stereotype.Controller;
import org.springframework.validation.BindException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.Set; /**
* 全局异常处理
*/
@ControllerAdvice(annotations = {RestController.class, Controller.class})
@ResponseBody
public class ExceptionConfiguration {
@ExceptionHandler({ConstraintViolationException.class,BindException.class})
public String validateException(Exception ex, HttpServletRequest request) {
ex.printStackTrace();
String msg = null;
if(ex instanceof ConstraintViolationException){
ConstraintViolationException constraintViolationException =
(ConstraintViolationException)ex;
Set<ConstraintViolation<?>> violations =
constraintViolationException.getConstraintViolations();
ConstraintViolation<?> next = violations.iterator().next();
msg = next.getMessage();
}else if(ex instanceof BindException){
BindException bindException = (BindException)ex;
msg = bindException.getBindingResult().getFieldError().getDefaultMessage();
}
return msg;
}
}

此时页面返回的友好提示是这样的

指定校验时使用快速失败返回模式:  这里并没有使用@Configuration注解,而是使用自定义注解,在需要使用它的类上面用,更加灵活。

package com.config;

import org.hibernate.validator.HibernateValidator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor; import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory; /**
* @author xiaozhuang
* @date 2022年02月26日 14:46
*/
//@Configuration 使用它就是所有的都会经过这里
public class ValidatorConfiguration {
@Bean
public Validator validator() {
ValidatorFactory validatorFactory =
Validation.byProvider(HibernateValidator.class)
.configure()
//快速失败返回模式
.addProperty("hibernate.validator.fail_fast", "true")
.buildValidatorFactory();
return validatorFactory.getValidator();
} /**
* @return 开启快速返回
* 如果参数校验有异常,直接抛异常,不会进入到 controller,使用全局异常拦截进行拦截
*/
@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
MethodValidationPostProcessor postProcessor =
new MethodValidationPostProcessor();
/**设置validator模式为快速失败返回*/
postProcessor.setValidator(validator());
return postProcessor;
}
}
package com.config;

import org.springframework.context.annotation.Import;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; /**
* 在启动类上添加该注解来启动表单验证功能---快速失败返回模式
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(ValidatorConfiguration.class) // 代表导入失败快速返回的配置类
public @interface EnableFormValidator {
}

这时我们把它可以加在启动类上,也可以放在某个单独的controller类上面。

再看效果:

就只校验了age,发生错误就直接返回了,没有再对userName进行校验了。

最新文章

  1. ASP.NET MVC 拦截器IResultFilter
  2. canvas 画六边形边框
  3. 十一、mysql输入安全
  4. Linux vps无法发送邮件
  5. 冒泡排序-Python与PHP实现版
  6. Windows 部署 Redis 群集(转)
  7. Android Studio设置字体和主题
  8. 出现: object() takes no parameters 之后应该如何修改
  9. 【分布式系列】session跨域及单点登录解决方案
  10. Javascript高级编程学习笔记(9)—— 执行环境
  11. redis 实现发布订阅的功能
  12. SQL 必知必会&#183;笔记&lt;17&gt;使用存储过程
  13. Windows视频桌面壁纸实现(libvlc)(类似于wall paper engine效果)
  14. spark基础知识介绍(包含foreachPartition写入mysql)
  15. 使用dd命令制作U盘启动盘wodim刻录光盘cd dvd
  16. 如何使用 MSBuild.exe 生成解决方案中的特定目标
  17. ApplicationContext详解以及多个ApplicationContext.xml的相互引用
  18. Oracle 11g 的bug?: aix 上,expdp 11.2.0.1 导出,impdp 11.2.0.3 导入,Interval 分区的 【Interval】 分区属性成了【N】
  19. c++ 将容量设置为容器的长度(shrink_to_fit)
  20. JQuery的getJSON函数跨域

热门文章

  1. 使用 Jenkins 进行持续集成与发布流程图-图解
  2. linux3种安装软件、yum仓库、防火墙、乱码
  3. Linux shell中2&gt;&amp;1的含义解释
  4. TCP/IP 协议标准简单描述
  5. MassTransit 入门(一)
  6. Java学习day13
  7. javaWeb代码整理03-druid数据库连接池
  8. 2021.07.26 P1010 幂次方(数论)
  9. 公私钥 SSH 数字证书
  10. 集合——Collection接口,List接口