当前位置:

首页 > 编程开发 > Java中的@Valid,@Validated和@PathVariable怎么用

Java中的@Valid,@Validated和@PathVariable怎么用

@Valid和@Validated@Valid和@Validated比较相同点:@Valid注解和@Validated注解都是开启校验功能的注解不同点:@Valid注解:可以使用在方法,构造函数,方法参数和成员属性上@Validated注解:可以用在类型,方法和方法参数上.但是不能用在成员属性上@Validated注解是Spring基于@Valid注解的进一步封装,并提供比如分组,分组顺序的高级功能使用位置不同:@Valid高级使用@Valid级联校验级联校验:也叫嵌套检测.嵌套就是一个实体类包含另一个实

本文目录

      @Valid和@Validated

      @Valid和@Validated比较

      • 相同点:

        • @Valid注解和 @Validated注解都是开启校验功能的注解

      • 不同点:

        • @Valid注解 : 可以使用在方法,构造函数,方法参数和成员属性上

        • @Validated注解 : 可以用在类型,方法和方法参数上. 但是不能用在成员属性上

        • @Validated注解是Spring基于 @Valid注解的进一步封装,并提供比如分组,分组顺序的高级功能

        • 使用位置不同:

      @Valid高级使用

      @Valid级联校验
      • 级联校验: 也叫嵌套检测.嵌套就是一个实体类包含另一个实体类

      • @Valid和可以用在成员属性的字段上,因此 @Valid可以提供级联校验

      • 示例:

        @Data
        public class Hair {
        	
        	@NotBlank(message = "头发长度必须提交!")
        	private Double length;
        
          	@NotBlank(message = "头发颜色必须提交!")
          	private String color;
        }
        
        @Data
        public class Person {
        	
        	@NotBlank(message = "用户姓名必须提交!")
        	@Size(min=2, max=8)
        	private String userName;
        
          	// 添加@Valid注解实现嵌套检测
          	@Valid
            @NotEmpty(message = "用户要有头发!")
            private List hairs;
        }
         
        @PostMapping("/person")
        public Result addPerson(@Valid @RequestBody Person person) {
        	return Result.buildSuccess(person);
        }
        • 只是在方法参数前面添加 @Valid和 @Validated注解,不会对嵌套的实体类进行校验.要想实现对嵌套的实体类进行校验,需要在嵌套的实体类属性上添加 @Valid注解

      @Validated高级使用

      @Validated分组校验
      • 分组校验:

        • 对指定的组开启校验,可以分别作用于不同的业务场景中

        • 分组校验是由 @Validated注解中的value提供的

      • groups:

        @Data
        public class PersonGroup {
        	
        	public interface AddGroup {}
          
          	public interface UpdateGroup {}
        
          	// @Validated注解value方法指定分组UpdateGroup.class时校验
          	@NotBlank(message = "用户ID必须提交!", groups = UpdateGroup.class)
          	private String id;
        
          	// @Validated注解value方法指定分组AddGroup.class或者分组UpdateGroup.class时校验
          	@NotBlank(message = "用户的姓名必须提交!", groups = {AddGroup.class, UpdateGroup.class}) 
          	private String name;
        
          	// @Validated注解value方法未指定分组时校验
          	@Range(min = 1, max = 200, message = "用户的年龄必须提交!")
          	private int age;
        }
        • JSR 303校验注解中的分组方法groups

        • 示例:

      • 开启分组校验: 通过 @Validated注解的value方法对指定的分组开启校验

      @RestController
      @RequestMapping("/person")
      public class PersonGroupController {
      	
      	// 不指定分组时校验
      	@GetMapping("/person")
      	public Result getPerson(@Validated @RequestBody PersonGroup person) {
      		return Result.buildSuccess(person);
      	}
      
      	// 指定AddGroup分组校验
      	@PostMapping("/person")
      	public Result addPerson(@Validated(value = PersonGroup.AddGroup.class) @RequestBody PersonGroup person) {
      		return Result.buildSuccess(person);
      	}
      
      	// 指定UpdateGroup分组校验
      	@PutMapping("/person")
      	public Result updatePerson(@Validated(value = PersonGroup.updateGroup.class) @RequestBody PersonGroup person) {
      		return Result.buildSuccess(person);
      	}
      }
      • 校验方法添加groups的值来指定分组,只有使用 @Validated注解的value的值指定这个分组时,开会开启注解的校验数据的功能

      @Validated分组校验顺序
      • 默认情况下,分组间的约束是无序的,但是在一些特殊的情况下可能对分组间的校验有一定的顺序

        • 比如第二组的分组的约束的校验需要依赖第一组的稳定状态来进行,此时,要求分组间的约束校验一定要有顺序

      • 分组校验顺序通过使用 @GroupSequence注解实现

      • 示例:

      @Data
      public class UserGroupSequence {
      	
      	public interface FirstGroup {}
      
      	public interface SecondGroup {}
      
      	// 使用GroupSequence定义分组校验顺序:按照FirstGroup,SecondGroup分组顺序进行校验
      	@GroupSequence({FirstGroup.class, SecondGroup.class})
      	public interface Group {}
      
      	@NotEmpty(message = "用户ID必须提交!", group = FirstGroup.class)
      	private String userId;
      
      	@NotEmpty(message = "用户姓名必须提交!", group = FirstGroup.class)
      	@Size(min = 2, max = 8, message = "用户姓名的长度在2~8之间", goup = Second.class)
      	private String userName;
      }
      @RestController
      @RequestMapping("/user")
      public class UserGroupSequenceController {
      	// 这里方法中@Validated注解value的值是Group.class
      	@PostMapping("/user")
      	public Result addGroup(@Validated(value = Group.class) @RequestBody UserGroupSequence user) {
      		return Result.buildSuccess(user);
      	}
      }
      • 使用 @GroupSequence注解指定分组校验顺序后,第一组分组的约束的校验没有通过后,就不会进行第二组分组的约束的校验

      @Validated非实体类校验
      • 在非实体类上添加 @Validated注解对非实体类进行校验

      @Validated
      public class AnnotationController {
      	
      	@GetMapping("/person")
      	public Result getAge(@Range(min = 2, max = 8, message = "年龄在3~8岁!") @RequestParam int age) {
      		return Result.buildSuccess(age);
      	}
      }
      • 在GlobalExceptionHandler中添加全局统一异常处理方法:

      @ExceptionHandler(ConstraintViolationException.class)
      @ResponseBody
      public Result resolveConstraintViolationException(ConstraintVilationException exception) {
      	Set> constraintVilations = exception.getConstraintVilations();
      	// 处理异常信息
      	if (!CollectionUtils.isEmpty(constraintVilations)) {
      		StringBuilder messageBuilder = new StringBuilder();
      		for (ConstraintVilation constraintViolation : constraintVilations) {
      			messageBuilder.append(constraintVilation.getMessage()).append(",");
      		}
      		String errorMessage = messageBuilder.toString();
      		if (errorMessage.length() > 1) {
      			errorMessage.substring(0, errorMessage.length() - 1);
      		}
      		return Result.builderFailure(ErrorStatus.ILLEGAL_DATA.getCode(), errorMessage);
      	} 
      	return Result.builderFailure(ErrorStatus.ILLEGAL_DATA.getCode(), exception.getMessage())
      }

      @PathVariable

      • @PathVariable的作用: 用来指定请求URL路径里面的变量

      • @PathVariable和 @RequestParam的区别:

        • @PathVariable用来指定请求URL中的变量

        • @RequestParam用来获取静态的URL请求入参

      正则表达式校验

      • 使用正则表达式校验 @PathVariable指定的路径变量

      // 请求路径中的id必须是数字,否则寻找不到这个路径404
      @GetMapping("/user/{id:\\d+}")
      public Result getId(@PathVariable(name="id") String userId) {
      	return Result.buildSuccess(userId);
      }

      继承BasicErrorController类

      • @ControllerAdvice注解只能处理进入控制器方法抛出的异常

      • BasicErrorController接口可以处理全局异常

      • @PathVariable路径校验异常不是控制器方法抛出的,此时还没有进入控制器方法:

        • BasicErrorController处理异常,比如404异常时,会跳转到 /error路径,此时会返回错误的html页面

        • 为了保证返回结果统一,继承BasicErrorController类,重写BasicErrorController接口中的错误处理方法

      @RestController
      public class PathErrorController extends BasicErrorController {
      	
      	@Autowired
      	public PathErrorController(ErrorAttributes errorAttributes, ServerProperties serverProperties, List errorViewResolvers) {
      		super(errorAttributes, serverProperties.getError(), errorViewResolvers);
      	}
      
      	/**
      	 * 处理html请求
      	 */
      	@Override
      	public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
      		HttpStatus status = getStatus(request);
      		Map model = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.TEXT_HTML));
      		ModelAndView modelAndView = new ModelAndView("pathErrorPage", model, status);
      		return modelAndView;
      	}
      	
      	/**
      	 * 处理json请求
      	 */
      	@Override
      	public ResponseEntity> error(HttpServletRequest request) {
      		Map body = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.ALL));
      		
      		Map responseBody = new HashMap<>(8);
      		responseBody.put("success", false);
      		responseBody.put("code", body.get("status"));
      		responseBody.put("message", body.get("error")); 
      		
      		return new ResponseEntity<>(responseBody, HttpStatus.OK);
      	}
      }

      自定义校验注解

      • 使用场景:

        • 对某一个只能输入指定值的字段进行校验. 此时需要使用自定义注解实现

      • 定义自定义的注解 @Show :

      @Documented
      @Constraint(validateBy = {Show.ShowConstraintValidator.class})
      @Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
      @Rentation(RUNTIME)
      public @interface Show {
      	String message() default "{com.oxford.annotation.Show.message}";
      
      	Class[] groups() default {};
      
      	Class[] payload() default {};
      	
      	int[] value();
      
      	class ShowConstraintValidator implements ConstraintValidator {
      		
      		private Set set = new HashSet<>();
      
      		/**
      		 * 初始化操作
      		 * 获取value属性指定的数字,保存到Set集合中
      		 */
      		@Override
      		public void initilize(Show constraintAnnotation) {
      			int[] value = constraintAnnotation.value();
      			for (int v : value) {
      				set.add(i);
      			}
      		}	
      
      		@Override
      		public boolean isValid(Integer value, ConstraintValidatorContext context) {
      			return set.contains(value);
      		}
      	} 
      }
      • 注意点:

        • 实现自定义的校验逻辑

        • 返回boolean类型的校验结果

        • 获取到自定义注解中的相关的数据

        • 接口中第一个泛型参数表示的是自定义注解类

        • 接口中第二个泛型参数表示的是校验的属性的值的类型

        • 将自定义的注解和实现的校验类联系起来

        • @Constraint注解:

        • 自定义校验注解类需要实现ConstraintValidator 接口

        • initialize() 方法:

        • isValid() 方法:

      • 自定义注解的使用:

      @Data
      public class AnnotationQuery {
      	
      	@Show(value = {0, 1}, message = "数值只能是0或者1")
      	private Integer isShow;
      }
      @PostMapping("/annotation")
      public Result addAnnotation(@Validated @RequestBody AnnotationQuery annotation) {
      	return Result.buildSuccess(annotation);
      }
      本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
      作者最新文章
      编程开发 Java
      相关文章 更多
      Java单元测试入门:使用JUnit 5编写第一个测试用例
      Java单元测试入门:使用JUnit 5编写第一个测试用例

      面向初学者的JUnit 5实用入门指南。从测试概念、Maven依赖配置,到手把手编写首个单元测试用例及断言验证,助你掌握Java单元测试的核心流程。

      Java变量未初始化报错解析:局部变量与成员变量默认值差异
      Java变量未初始化报错解析:局部变量与成员变量默认值差异

      深入解析Java中局部变量未初始化编译报错与成员变量自动赋予默认值的机制差异,涵盖JVM内存分配、编译期确定性赋值检查与实际排查修复方案。

      Java获取当前时间并格式化输出:DateTimeFormatter与SimpleDateFormat
      Java获取当前时间并格式化输出:DateTimeFormatter与SimpleDateFormat

      详细讲解在Java中获取当前系统时间并进行格式化输出的两种核心方案:基于Java 8全新日期时间API的DateTimeFormatter与传统遗留的SimpleDateFormat,包含完整代码示例、线程安全机制对比及生产选型建议。

      Java中final与static final常量的定义及初始化规则
      Java中final与static final常量的定义及初始化规则

      深入解析Java中final变量与static final常量的定义、内存语义、初始化时机及合法赋值路径,涵盖编译期常量优化与实战避坑指南。

      Java抽象方法与接口方法的区别及选型建议
      Java抽象方法与接口方法的区别及选型建议

      深入对比Java中抽象类抽象方法与接口方法的语法演进、设计意图及运行期差异,并提供清晰的架构选型决策流程与实战范例。

      Java实现HTTP请求与JSON解析的完整代码示例
      Java实现HTTP请求与JSON解析的完整代码示例

      本文提供Java标准库HttpClient发起HTTP GET/POST请求并结合Jackson进行JSON数据反序列化与序列化的完整代码示例与工程实践指南。

      Java递归出现StackOverflowError的原因分析及栈空间优化方案
      Java递归出现StackOverflowError的原因分析及栈空间优化方案

      详细分析Java递归调用出现StackOverflowError的原因,结合代码说明线程栈、栈帧和递归深度之间的关系,并介绍终止条件排查、迭代改写、减少栈帧开销以及通过-Xss调整JVM栈空间的方法。

      Java空指针异常(NPE)的代码排查与修复实例
      Java空指针异常(NPE)的代码排查与修复实例

      针对Java中常见的NullPointerException(NPE),本文从堆栈日志定位、典型代码触发场景、具体修复代码对比到防御体系进行系统讲解,提供实用且易上手的排查与修复方案。

      selenium上传文件教程本地文件路径设置方法
      selenium上传文件教程本地文件路径设置方法

      深入解析Selenium处理文件上传的技术细节,涵盖标准HTML控件的路径直接注入法与非标准控件的系统级模拟方案,提供Windows与Linux环境下的路径设置最佳实践及常见异常排查。

      大数据开发语言选型:Java对比Scala与Python的优缺点及适用场景
      大数据开发语言选型:Java对比Scala与Python的优缺点及适用场景

      针对大数据工程场景,系统对比Java、Scala与Python在执行性能、生态结合、开发效率和维护成本上的核心差异,给出清晰的架构选型依据与落地方案。

      查看更多
      精品专题 更多
      装机必备
      装机必备

      正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

      Windows
      Windows

      正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

      PDF教程
      PDF教程

      正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

      Mac软件 更多
      讯飞智作 网页版
      讯飞智作 网页版
      Windows/ macOS/ Linux

      讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

      火山引擎 网页版
      火山引擎 网页版
      Windows/ macOS/ Linux

      火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

      Aperty macOS版
      Aperty macOS版
      macOS

      Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

      WINDOWS 更多
      讯飞智作 网页版
      讯飞智作 网页版
      Windows/ macOS/ Linux

      讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

      火山引擎 网页版
      火山引擎 网页版
      Windows/ macOS/ Linux

      火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

      PixTV 网页版
      PixTV 网页版
      Windows

      PixTV 是一款在浏览器中使用的 AI 视觉内容创作平台,提供图片、视频、音频、文字生成、AI 分镜、局部重绘、提示词反推和无限画布等工具,适合短剧、漫剧、广告及社交媒体内容制作。