iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >spring注解校验原理是什么
  • 345
分享到

spring注解校验原理是什么

2023-06-17 08:06:46 345人浏览 安东尼
摘要

这篇文章主要介绍“spring注解校验原理是什么”,在日常操作中,相信很多人在spring注解校验原理是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”spring注解校验原理是什么”的疑惑有所帮助!接下来

这篇文章主要介绍“spring注解校验原理是什么”,在日常操作中,相信很多人在spring注解校验原理是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”spring注解校验原理是什么”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

一、介绍

关于参数合法性验证的重要性就不多说了,即使前端对参数做了基本验证以外,后端依然还需要进行验证,以防不合规的数据直接进入后端,严重的甚至会造成系统直接崩溃!

本文结合自己在项目中的实际使用经验,主要以实用为主,对数据合法性验证做一次总结,不了解的朋友可以学习一下,同时可以立马实践到项目上去。

下面我们通过几个示例来演示如何判断参数是否合法,不多说直接开撸!

二、断言验证

对于参数的合法性验证,最初的做法比较简单,自定义一个异常类。

public class CommonException extends RuntimeException {           private Integer code;           private String msg;      //...set/get      public CommonException(String msg) {         super(msg);         this.msg = msg;     }      public CommonException(String msg, Throwable cause) {         super(msg, cause);         this.msg = msg;     }  }

当判断某个参数不合法的时候,直接抛异常!

@RestController public class HelloController {   @RequestMapping("/upload")  public void upload(MultipartFile file) {   if (file == null) {    throw new CommonException("请选择上传文件!");   }      //.....  } }

然后写一个统一异常拦截器,对抛异常的程序进行处理。

这种做法比较直观,如果当前参数既要判断是否为空,又要判断长度是否超过最大长度的时候,代码就显得有点多了!

于是,程序界的大佬想到了一个更加优雅又能节省代码的方式,创建一个断言类工具类,专门用来判断参数的是否合法,如果不合法,就抛异常!

 public abstract class LocalAssert {    public static void isTrue(boolean expression, String message) throws CommonException {   if (!expression) {    throw new CommonException(message);   }  }  public static void isStringEmpty(String param, String message) throws CommonException{   if(StringUtils.isEmpty(param)) {    throw new CommonException(message);   }  }   public static void isObjectEmpty(Object object, String message) throws CommonException {   if (object == null) {    throw new CommonException(message);   }  }   public static void isCollectionEmpty(Collection coll, String message) throws CommonException {   if (coll == null || (coll.size() == 0)) {    throw new CommonException(message);   }  } }

当我们需要对参数进行验证的时候,直接通过这个类就可以完成基本操作,方式如下:

@RestController public class HelloController {   @RequestMapping("/save")  public void save(String name, String email) {   LocalAssert.isStringEmpty(name, "用户名不能为空!");   LocalAssert.isStringEmpty(email, "邮箱不能为空!");      //.....  } }

相比上个步骤,当要判断的参数比较多时,代码明显简洁多了!

类似这样的工具类,spring也提供了一个名为Assert的断言工具类,在开发的时候,可以直接使用!

spring注解校验原理是什么

三、注解验证

使用注解对数据进行合法性验证,可以说是 java  界一项非常伟大的创新,使用这种方式不仅使的代码变得很简洁,而且阅读起来非常令人赏心悦目!

3.1、依赖包引入

下面我们一起来看看具体的实践方式,以Spring  Boot工程为例,如果需要使用注解校验,直接引入spring-boot-starter-WEB依赖包即可,会自动将注解验证相关的依赖包打入工程!

<!-- spring boot web --> <dependency>     <groupId>org.springframework.boot</groupId>     <artifactId>spring-boot-starter-web</artifactId> </dependency>

下面在创建实体类的时候,还会用到lombok插件,因此还需要引入lombok依赖包!

<!-- lombok --> <dependency>     <groupId>org.projectlombok</groupId>     <artifactId>lombok</artifactId>     <version>1.18.4</version>     <scope>provided</scope> </dependency>

如果是普通的Java工程,引入以下几个依赖包即可!

<dependency>     <groupId>org.hibernate.validator</groupId>     <artifactId>hibernate-validator</artifactId>     <version>6.0.9.Final</version> </dependency> <dependency>      <groupId>javax.el</groupId>      <artifactId>javax.el-api</artifactId>      <version>3.0.0</version>  </dependency>  <dependency>     <groupId>org.glassfish.web</groupId>     <artifactId>javax.el</artifactId>     <version>2.2.6</version>  </dependency>

3.2、注解校验请求对象

紧接着我们来创建一个实体User,用于模拟用户注册时的请求实体对象!

@Data @EqualsAndHashCode(callSuper = false) @Accessors(chain = true) public class User {      @NotBlank(message = "用户名不能为空!")     private String userName;      @Email(message = "邮箱格式不正确")     @NotBlank(message = "邮箱不能为空!")     private String email;      @NotBlank(message = "密码不能为空!")     @Size(min = 8, max = 16,message = "请输入长度在8~16位的密码")     private String userPwd;      @NotBlank(message = "确认密码不能为空!")     private String confirmPwd; }

在web层创建一个reGISter()注册接口方法,同时在请求参数上添加@Valid,如下:

@RestController public class UserController {      @RequestMapping("/register")     public boolean register(@RequestBody @Valid User user){         if(!user.getUserPwd().equals(user.getConfirmPwd())){             throw new CommonException("确认密码与密码不相同,请确认!");         }   //业务处理...         return true;     } }

最后自定义一个异常全局处理器,用于处理异常消息,如下:

@Slf4j @Configuration public class GlobalWebmvcConfig implements WebMvcConfigurer {           @Override     public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {         resolvers.add(new HandlerExceptionResolver() {             @Override             public ModelAndView resolveException(httpservletRequest request, HttpServletResponse response, Object o, Exception e) {                 log.error("【统一异常拦截】请求出现异常,内容如下:",e);                 ModelAndView mv = new ModelAndView(new MappingJackson2JSONView());                 String uri = request.getRequestURI();                 if(e instanceof CommonException){                     //CommonExecption为自定义异常类抛出的异常                     printWrite(((CommonException) e).getMsg(),((CommonException) e).getData(), uri, mv);                 } else if(e instanceof MethodArgumentNotValidException){                     //MethodArgumentNotValidException为注解校验异常类                     //获取注解校验异常信息                     String error = ((MethodArgumentNotValidException) e).getBindingResult().getFieldError().getDefaultMessage();                     printWrite(error,null, uri, mv);                 } else {                     printWrite(e.getMessage(),null, uri, mv);                 }                 return mv;             }         });     }            private void printWrite(String msg, Object object, String uri, ModelAndView mv){         ResResult resResult = new ResResult(uri, object);         if(msg != null){resResult.setMsg(msg);}         if(log.isDebugEnabled()){             log.debug("【response】异常输出结果:" + jsONObject.toJSONString(resResult, SerializerFeature.WriteMapNullValue));         }         Map resultMap = BeanToMapUtil.beanToMap(resResult);         mv.addAllObjects(resultMap);     } }

下面我们启动项目,使用postman来测试一把,看看效果如何?

  • 测试字段是否为空

spring注解校验原理是什么

  • 测试邮箱是否合法

spring注解校验原理是什么

  • 测试密码长度是否符合要求

spring注解校验原理是什么

  • 测试密码与确认密码是否相同

spring注解校验原理是什么

3.3、注解校验请求参数

上面我们介绍了请求对象的验证方式,那如果直接在方法上对请求参数进行验证是否同样有效呢?

为了眼见为实,下面我们就来模拟在方法上对请求参数进行验证,看看结果如何。

新建一个查询接口query,如下

@RestController public class UserController {      @PostMapping("/query")     public boolean query(@RequestParam("userId") @Valid @NotBlank(message = "用户ID不能为空") String userId ){         return true;     }  }

使用postman请求试一试,默认给userId参数为null,结果如下:

spring注解校验原理是什么

很清晰的看到,query()方法中的参数注解验证无效!

当我们在UserController类上加上@Validated注解!

@RestController @Validated public class UserController {      @PostMapping("/query")     public boolean query(@RequestParam("userId") @Valid @NotBlank(message = "用户ID不能为空") String userId ){         return true;     }  }

使用postman请求再试一试,结果如下!

spring注解校验原理是什么

很清晰的看到,注解进行了验证,同时还抛出异常ConstraintViolationException!

spring注解校验原理是什么

@Validated参数作用于类上时,表示告诉Spring可以对方法中请求参数进行校验!

所有在实际开发的时候,我们可以使用@Validated和@Valid注解的组合来对方法中的请求参数和请求对象进行校验!

同时,@Validated和@Valid注解不仅仅只是验证控制器级别,可以验证任何Spring组件,例如Service层方法入参的验证!

@Service @Validated public class UserService {      public void saveUser(@Valid User user){         //dao插入     } }

3.4、自定义注解验证

默认的情况下,依赖包已经给我们提供了非常多的校验注解,如下!

  • JSR提供的校验注解!

spring注解校验原理是什么

  • Hibernate Validator提供的校验注解

spring注解校验原理是什么

但是某些情况,例如性别这个参数可能需要我们自己去验证,同时我们也可以自定义一个注解来完成参数的校验,实现方式如下!

  • 新创建一个Sex注解,其中SexValidator类指的是具体的参数验证类

@Target({FIELD}) @Retention(RUNTIME) @Constraint(validatedBy = SexValidator.class) @Documented public @interface Sex {      String message() default "性别值不在可选范围内";      Class<?>[] groups() default {};      Class<? extends Payload>[] payload() default {}; }
  • SexValidator类,实现自ConstraintValidator接口

public class SexValidator implements ConstraintValidator<Sex, String> {      @Override     public boolean isValid(String value, ConstraintValidatorContext context) {         Set<String> sexSet = new HashSet<String>();         sexSet.add("男");         sexSet.add("女");         return sexSet.contains(value);     } }

最后在User实体类上加入一个性别参数,使用自定义注解进行校验!

@Data @EqualsAndHashCode(callSuper = false) @Accessors(chain = true) public class User {      @NotBlank(message = "用户名不能为空!")     private String userName;      @Email(message = "邮箱格式不正确")     @NotBlank(message = "邮箱不能为空!")     private String email;      @NotBlank(message = "密码不能为空!")     @Size(min = 8, max = 16,message = "请输入长度在8~16位的密码")     private String userPwd;      @NotBlank(message = "确认密码不能为空!")     private String confirmPwd;           @Sex(message = "性别输入有误!")     private String sex; }

使用postman来请求试一试,结果如下!

  • 不传sex参数

spring注解校验原理是什么

很清晰的看到,已经生效!

3.5、手动进行注解校验

某些时候呢,假如有100个类需要用到校验注解,此时我们可能在每个类会加上注解@Validated或者@Valid,再增加100个这样的类,就会造成很多大量的重复工作。

而此时,我们的诉求是想对有校验注解的实体类进行全局参数验证!

解决办法就会用到Validator提供的手动注解校验证工具类,实现方法如下!

  • 新建一个注解验证工具类

 public class ValidatorUtils {           public static String validated(Object object){         List<String> errORMessageList = new ArrayList<>();   //获取注解校验工厂         ValidatorFactory factory = Validation.buildDefaultValidatorFactory();         Validator validator = factory.getValidator();         Set<ConstraintViolation<Object>> violations = validator.validate(object);          for (ConstraintViolation<Object> constraintViolation : violations) {             errorMessageList.add(constraintViolation.getMessage());         }         return errorMessageList.toString();     } }

使用ValidatorUtils工具类,对参数进行验证

@Test public void testUser(){     User user = new User();     System.out.println(ValidatorUtils.validated(user)); }

执行之后,结果如下!

[邮箱不能为空!, 用户名不能为空!, 密码不能为空!, 确认密码不能为空!, 性别输入有误!]

当然你还可以对ValidatorUtils类进行改造,当有异常信息的时候,直接抛异常!

同时,你还可以通过@Autowired直接注入的方式来获取Validator对象!

@Autowired Validator validator

3.6、spring 注解校验原理

如果你对springMVC的方法参数解析器(HandlerMethodArgumentResolver)了解的话,就可能会想到参数校验这块肯定是在对应的方法参数解析器里执行的。

直接定位到resolveArgument这个方法,先通过WebDataBinder进行入参属性绑定,然后再进行校验!

spring注解校验原理是什么

validateIfApplicable方法逻辑,会遍历当前参数methodParam所有的注解,如果注解是@Validated或者注解的名字以Valid开头,则使用WebDataBinder对象执行校验逻辑。

spring注解校验原理是什么

方法参数解析器只针对接口请求时入参进行验证,如果想对任何组件中方法进行注解校验,似乎还缺了点什么!

而当需要对一个类中的方法参数使用注解校验时,在类上加上@Validated就是为了告诉Spring去校验方法参数!

底层核心是通过切面代理类并配合MethodValidationPostProcessor这个后置处理器进行处理!

spring注解校验原理是什么

到此,关于“spring注解校验原理是什么”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

--结束END--

本文标题: spring注解校验原理是什么

本文链接: https://www.lsjlt.com/news/287906.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • spring注解校验原理是什么
    这篇文章主要介绍“spring注解校验原理是什么”,在日常操作中,相信很多人在spring注解校验原理是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”spring注解校验原理是什么”的疑惑有所帮助!接下来...
    99+
    2023-06-17
  • 参数校验Spring的@Valid注解有什么用
    小编给大家分享一下参数校验Spring的@Valid注解有什么用,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!参数校验Spring的@Valid注解@Valid ...
    99+
    2023-06-20
  • spring注解的底层实现原理是什么
    Spring注解的底层实现原理主要依赖于Java的反射机制。在Spring中,通过使用注解来标识类、方法或字段,从而告诉Spring...
    99+
    2023-10-09
    spring
  • spring依赖注入的原理是什么
    Spring依赖注入的原理是通过IOC(Inversion of Control)容器来实现的。IOC容器是Spring框架的核心,...
    99+
    2023-09-29
    spring
  • Spring boot怎么实现超灵活的注解式数据校验
    本篇内容主要讲解“Spring boot怎么实现超灵活的注解式数据校验”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Spring boot怎么实现超灵活的注解式数据校验”吧!...
    99+
    2023-06-21
  • SpringMVC注解之@ResponseBody注解原理是什么
    这篇文章主要介绍SpringMVC注解之@ResponseBody注解原理是什么,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!一、介绍@ResponseBody 注解的作用是将方法的返回值通过适当的转换器转换为指定的...
    99+
    2023-06-15
  • 怎么通过自定义spring invalidator注解校验数据合法性
    今天小编给大家分享一下怎么通过自定义spring invalidator注解校验数据合法性的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面...
    99+
    2023-07-02
  • CRC校验原理及C语言实现的方法是什么
    这篇“CRC校验原理及C语言实现的方法是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“CRC校验原理及C语言实现的方法是...
    99+
    2023-07-05
  • Spring MVC原理是什么
    这篇文章将为大家详细讲解有关Spring MVC原理是什么,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。springMVC,是spring的一个子框架,当然拥有spring的特性,如依赖注入。在web模型...
    99+
    2023-06-27
  • Spring框架实现依赖注入的原理是什么
    这篇文章主要介绍“Spring框架实现依赖注入的原理是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Spring框架实现依赖注入的原理是什么”文章能帮助大家解决问题。Spring 框架作为 Ja...
    99+
    2023-07-06
  • Spring中@Configuration注解修改的类生成代理的原因是什么
    今天小编给大家分享一下Spring中@Configuration注解修改的类生成代理的原因是什么的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们...
    99+
    2023-06-29
  • spring session的原理是什么
    Spring Session是一种用于管理用户会话的框架,它通过将会话数据存储在外部存储介质中,而不是默认的内存中,来实现会话的持久...
    99+
    2023-09-21
    spring
  • Spring底层原理是什么
    这篇文章主要讲解了“Spring底层原理是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Spring底层原理是什么”吧!Spring简介ClassPathXmlApplicationCo...
    99+
    2023-07-05
  • tomcat+spring mvc原理是什么
    这篇文章主要讲解了“tomcat+spring mvc原理是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“tomcat+spring mvc原理是什么”吧!tomat + spring ...
    99+
    2023-06-02
  • spring scope的原理是什么
    Spring的Bean的作用域(scope)指定了一个Bean的实例是如何被创建和管理的。Spring框架提供了多种作用域,包括si...
    99+
    2023-08-31
    spring scope
  • Spring MVC的原理是什么
    今天小编给大家分享一下Spring MVC的原理是什么的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。SpringMVC是一种...
    99+
    2023-06-27
  • Java增加自定义注解进行校验入参的方法是什么
    这篇文章主要介绍“Java增加自定义注解进行校验入参的方法是什么”,在日常操作中,相信很多人在Java增加自定义注解进行校验入参的方法是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java增加自定义注解...
    99+
    2023-07-06
  • spring是怎么处理注解的
    Spring框架是一个基于注解的框架,它可以处理各种注解来实现不同的功能。下面是Spring框架处理注解的一般过程:1. 扫描注解:...
    99+
    2023-08-18
    spring
  • Spring MVC异常解析器的原理是什么
    本篇内容主要讲解“Spring MVC异常解析器的原理是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Spring MVC异常解析器的原理是什么”吧!使用介...
    99+
    2022-10-19
  • Spring框架的原理是什么
    这篇文章主要讲解了“Spring框架的原理是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Spring框架的原理是什么”吧!简要介绍spring的原理,并结合一个简单的实例,如何配置使用...
    99+
    2023-06-03
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作