当前位置: 首页 > backend >正文

validate校验的使用

目录

1.说明

2.RequestParam及PathVariable示例

3.RequestBody示例

4.总结


1.说明

后端接收前端传递的参数时,需要进行校验处理,最常用的就是非空校验,前端传递的内容不能为空。

2.RequestParam及PathVariable示例

①依赖

        <!--        参数校验--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId></dependency>

② 校验代码

package com.example.demo2.controller;import com.example.demo2.domain.SysUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.Validator;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import java.util.Set;@RestController
@RequestMapping("/validate")
@Validated
public class ValidateController {@Autowiredprivate Validator validator;@GetMapping("/test1")public String test1(@RequestParam @Min(value = 10, message = "id不能小于10") Long id,@RequestParam @NotBlank(message = "name不能为空") String name) {return "test1";}@GetMapping("/test5/{id}")public String test5(@PathVariable @Min(value = 10, message = "id不能小于10") Long id) {return "test5";}@GetMapping("/test2")public String test2(@RequestParam Long id,@RequestParam String name) {SysUser sysUser = new SysUser().setUserId(id).setUserName(name);Set<ConstraintViolation<SysUser>> validate = validator.validate(sysUser);if (!CollectionUtils.isEmpty(validate)) {throw new ConstraintViolationException(validate);}return "test2";}}
package com.example.demo2.domain;import lombok.Data;
import lombok.experimental.Accessors;import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import java.util.Date;/*** 用户对象 sys_user*/
@Data
@Accessors(chain = true)
public class SysUser
{private static final long serialVersionUID = 1L;/** 用户ID */@Min(value = 10, message = "id不能小于10")private Long userId;/** 部门ID */private Long deptId;/** 用户账号 */@NotBlank(message = "name不能为空")private String userName;/** 用户昵称 */private String nickName;/** 用户邮箱 */private String email;/** 手机号码 */private String phonenumber;/** 用户性别 */private String sex;/** 用户头像 */private String avatar;/** 密码 */private String password;/** 帐号状态(0正常 1停用) */private String status;/** 删除标志(0代表存在 2代表删除) */private String delFlag;/** 最后登录IP */private String loginIp;/** 最后登录时间 */private Date loginDate;}

③实现方式

实现方式一

  1. 在类上需要添加@Validated
  2. 在参数中添加校验注解
  3. 抛出ConstraintViolationException异常,通过全局异常处理校验的异常

实现方式二

  1. 注入Validator
  2. 将参数传递至实体类中
  3. 在实体类的属性上添加校验注解
  4. 调用Validator的validate方法进行校验,将实体类作为参数
  5. 判断返回值是否为空,不为空,抛出ConstraintViolationException校验异常,方通过全局异常进行处理

3.RequestBody示例

①依赖同上

②示例

package com.example.demo2.controller;import com.example.demo2.domain.SysUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.Validator;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import java.util.Set;@RestController
@RequestMapping("/validate")
public class ValidatePostController {@Autowiredprivate Validator validator;@PostMapping("/test3")public String test3(@RequestBody @Validated SysUser sysUser) {return "test3";}@PostMapping("/test4")public String test4(@RequestBody SysUser sysUser) {Set<ConstraintViolation<SysUser>> validate = validator.validate(sysUser);if (!CollectionUtils.isEmpty(validate)) {throw new ConstraintViolationException(validate);}return "test4";}}
package com.example.demo2.domain;import lombok.Data;
import lombok.experimental.Accessors;import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import java.util.Date;/*** 用户对象 sys_user*/
@Data
@Accessors(chain = true)
public class SysUser
{private static final long serialVersionUID = 1L;/** 用户ID */@Min(value = 10, message = "id不能小于10")private Long userId;/** 部门ID */private Long deptId;/** 用户账号 */@NotBlank(message = "name不能为空")private String userName;/** 用户昵称 */private String nickName;/** 用户邮箱 */private String email;/** 手机号码 */private String phonenumber;/** 用户性别 */private String sex;/** 用户头像 */private String avatar;/** 密码 */private String password;/** 帐号状态(0正常 1停用) */private String status;/** 删除标志(0代表存在 2代表删除) */private String delFlag;/** 最后登录IP */private String loginIp;/** 最后登录时间 */private Date loginDate;}

全局异常处理

package com.example.demo2.globalException;import com.example.demo2.domain.AjaxResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.stream.Collectors;/*** 全局异常处理器*/
@RestControllerAdvice
public class GlobalExceptionHandler {private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);/*** 处理业务异常*/@ExceptionHandler(BusinessException.class)@ResponseStatus(HttpStatus.BAD_REQUEST)public AjaxResult handleBusinessException(BusinessException e, HttpServletRequest request) {log.error("业务异常:请求地址:{},异常信息:{}", request.getRequestURI(), e.getMessage());return AjaxResult.error(e.getMessage());}/*** 处理参数校验异常*/@ExceptionHandler(IllegalArgumentException.class)@ResponseStatus(HttpStatus.BAD_REQUEST)public AjaxResult handleIllegalArgumentException(IllegalArgumentException e, HttpServletRequest request) {log.error("参数校验异常:请求地址:{},异常信息:{}", request.getRequestURI(), e.getMessage());return AjaxResult.error("参数错误:" + e.getMessage());}/*** 处理请求方法不支持异常*/@ExceptionHandler(HttpRequestMethodNotSupportedException.class)@ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)public AjaxResult handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e, HttpServletRequest request) {log.error("不支持的请求方法:请求地址:{},异常信息:{}", request.getRequestURI(), e.getMessage());return AjaxResult.error("不支持的请求方法:" + e.getMethod());}/*** 处理参数缺失异常*/@ExceptionHandler(MissingServletRequestParameterException.class)@ResponseStatus(HttpStatus.BAD_REQUEST)public AjaxResult handleMissingServletRequestParameterException(MissingServletRequestParameterException e, HttpServletRequest request) {log.error("缺少请求参数:请求地址:{},异常信息:{}", request.getRequestURI(), e.getMessage());return AjaxResult.error("缺少必要的请求参数:" + e.getParameterName());}/*** 处理参数类型不匹配异常*/@ExceptionHandler(MethodArgumentTypeMismatchException.class)@ResponseStatus(HttpStatus.BAD_REQUEST)public AjaxResult handleMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e, HttpServletRequest request) {log.error("参数类型不匹配:请求地址:{},异常信息:{}", request.getRequestURI(), e.getMessage());return AjaxResult.error("参数类型不匹配:" + e.getName());}/*** 处理参数绑定异常*/@ExceptionHandler(BindException.class)@ResponseStatus(HttpStatus.BAD_REQUEST)public AjaxResult handleBindException(BindException e, HttpServletRequest request) {log.error("参数绑定异常:请求地址:{},异常信息:{}", request.getRequestURI(), e.getMessage());return AjaxResult.error("参数绑定失败:" + e.getBindingResult().getFieldError().getDefaultMessage());}/*** 处理参数校验异常* 在请求中直接使用@Validated注解对请求体进行校验,会抛出此异常,不能在类上添加@Validated,必须在请求中添加*/@ExceptionHandler(MethodArgumentNotValidException.class)@ResponseStatus(HttpStatus.BAD_REQUEST)public AjaxResult handleMethodArgumentNotValidException(MethodArgumentNotValidException e, HttpServletRequest request) {log.error("参数校验异常:请求地址:{},异常信息:{}", request.getRequestURI(), e.getMessage());String errorInfo = e.getBindingResult().getFieldErrors().stream().map(FieldError::getDefaultMessage).collect(Collectors.joining(";"));return AjaxResult.error("参数校验失败:" + errorInfo);}/*** 处理约束违反异常(@Max、@Min、@Valid等直接在参数上的校验)* 处理get请求及post请求的请求地址中的参数校验,需要在整个controller中添加注解@Validated,然后在每个参数后面添加内容校验的注解,如notnull,min等等* 在service中直接注入private Validator validator;当校验结果不为空时,也可以抛出ConstraintViolationException异常*/@ExceptionHandler(ConstraintViolationException.class)@ResponseStatus(HttpStatus.BAD_REQUEST)public AjaxResult handleConstraintViolationException(ConstraintViolationException e, HttpServletRequest request) {log.error("约束违反异常:请求地址:{},异常信息:{}", request.getRequestURI(), e.getMessage());// 提取所有的约束违反信息String errorMessage = e.getConstraintViolations().stream().map(ConstraintViolation::getMessage).collect(Collectors.joining("; "));return AjaxResult.error("参数校验失败:" + errorMessage);}/*** 处理所有不可知的异常* 注意:这个处理器要放在最后,因为Exception是所有异常的父类*/@ExceptionHandler(Exception.class)@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)public AjaxResult handleException(Exception e, HttpServletRequest request) {log.error("系统异常:请求地址:{},异常信息:", request.getRequestURI(), e);return AjaxResult.error("系统错误,请联系管理员");}
//     主要改进和完善包括:
// 异常分类更细致:
// 业务异常(BusinessException)
// 参数校验异常(IllegalArgumentException)
// 请求方法不支持异常(HttpRequestMethodNotSupportedException)
// 参数缺失异常(MissingServletRequestParameterException)
// 参数类型不匹配异常(MethodArgumentTypeMismatchException)
// 参数绑定异常(BindException)
// 参数校验异常(MethodArgumentNotValidException)
// 约束违反异常(ConstraintViolationException)
// 系统异常(Exception)
// 添加了HTTP状态码:
// 使用@ResponseStatus注解指定不同的HTTP状态码
// 业务异常和参数异常返回400(BAD_REQUEST)
// 请求方法不支持返回405(METHOD_NOT_ALLOWED)
// 系统异常返回500(INTERNAL_SERVER_ERROR)
// 完善了日志记录:
// 添加了请求地址信息
// 区分了不同类型的异常日志
// 使用更详细的日志格式
// 异常处理最佳实践:
// 保持异常处理方法的顺序(从具体到通用)
// 统一的返回格式(使用AjaxResult)
// 清晰的错误信息
// 适当的HTTP状态码
// 其他建议:
// 考虑添加异常监控和告警机制
// 敏感信息不要直接返回给前端
// 可以根据环境(开发/生产)返回不同详细程度的错误信息
// 考虑添加异常统计和性能监控
// 这样的全局异常处理更加完善,能够处理更多类型的异常,并提供更好的日志记录和错误信息。
}

 ③实现方式

方式一

  1. 在参数中添加@Validated注解,不能添加在类上
  2. 在实体类中添加校验注解
  3. 抛出MethodArgumentNotValidException异常,通过全局异常进行处理

方式二

同上

4.总结

①通过validate及全局校验处理,实现参数校验

可以采用方式二,抛出ConstraintViolationException,进行统一的处理

②全局异常处理在开发中很常见,在spring mvc中如果没有配置全局异常处理,会转发到/error(注意是服务端内部转发,非客户端重定向,浏览器地址栏不会变)。),就可能会执行spring mvc的拦截器处理导致发生一些问题,可以配置全局异常处理来避免这种问题

http://www.xdnf.cn/news/13019.html

相关文章:

  • 运动控制--BLDC电机
  • 【Linux指南】用户与系统基础操作
  • C++之list的自我实现
  • 曼昆《经济学原理》第九版 第十二章税收制度的设计
  • NY158NY159美光固态闪存NY160NY161
  • 权限一览表
  • 曼昆《经济学原理》第九版 第八章税收的成本
  • 深入探索CDC:实时数据同步利器
  • C++ map基础概念、map对象创建、map赋值操作、map大小操作、map数据插入、map数据删除、map数据修改、map数据统计
  • zotero及其插件安装
  • Java中的泛型底层是怎样的
  • 【八股消消乐】构建微服务架构体系—服务注册与发现
  • 线性规划饮食问题求解:FastAPI作为服务端+libhv作为客户端实现
  • Boost ASIO 库深入学习(1)
  • CSRF(跨站请求伪造)详解
  • 《经济学原理》第九版 第九章国际贸易
  • 01Linux基础入门教程——从起源到核心概念
  • MySQL的日志
  • 深入理解Python内置模块及第三方库的使用与管理
  • Global Security Markets International Compliance知识点总结
  • 用 DeepSeek 创作一首属于自己的歌
  • HBM 读的那些事
  • Spring通用类型转换的实现原理
  • LangChain4j 1.x 核心源码剖析-基础篇
  • CMake基础:gcc/g++编译选项详解
  • 【GO性能优化】第十五章:性能优化艺术——揭秘Go程序的性能调优技巧
  • Redis : Hash形式
  • 【threejs】每天一个小案例讲解:题外话篇
  • 算法训练第十一天
  • Python应用变量与数据类型