lombok@NonNull 注解无法对 SpringMVC 封装请求的对象的 Field 进行非空校验()

  本篇文章为你整理了lombok@NonNull 注解无法对 SpringMVC 封装请求的对象的 Field 进行非空校验()的详细内容,包含有 lombok@NonNull 注解无法对 SpringMVC 封装请求的对象的 Field 进行非空校验,希望能帮助你了解 lombok@NonNull 注解无法对 SpringMVC 封装请求的对象的 Field 进行非空校验。

  

 If put on a parameter, lombok will insert a null-check at the start of the method / constructors body, throwing a {@code NullPointerException} with the parameters name as message. 
 If put on a field, any generated method assigning a value to this field will also produce these null-checks.

 

  可见 @NonNull 注解用于标注Field时,并非是直接校验所标注字段不能为空,而是对赋值该字段的方法加 null 校验。

  如该对象

  

@Data

 

  @AllArgsConstructor

  public class ReqIn {

   @NonNull

   private Byte name;

   private String id;

   public ReqIn(){

   System.out.println("无参构造");

  

 

   编译生成 .class 文件如下

  

public class ReqIn {

 

   @NonNull

   private String name;

   private String id;

   public ReqIn() {

   System.out.println("无参构造");

   @NonNull

   public String getName() {

   return this.name;

   public String getId() {

   return this.id;

   public void setName(@NonNull final String name) {

   if (name == null) {

   throw new NullPointerException("name is marked non-null but is null");

   } else {

   this.name = name;

   public void setId(final String id) {

   this.id = id;

   public boolean equals(final Object o) {

   if (o == this) {

   return true;

   } else if (!(o instanceof ReqIn)) {

   return false;

   } else {

   ReqIn other = (ReqIn)o;

   if (!other.canEqual(this)) {

   return false;

   } else {

   Object this$name = this.getName();

   Object other$name = other.getName();

   if (this$name == null) {

   if (other$name != null) {

   return false;

   } else if (!this$name.equals(other$name)) {

   return false;

   Object this$id = this.getId();

   Object other$id = other.getId();

   if (this$id == null) {

   if (other$id != null) {

   return false;

   } else if (!this$id.equals(other$id)) {

   return false;

   return true;

   protected boolean canEqual(final Object other) {

   return other instanceof ReqIn;

   public int hashCode() {

   int PRIME = true;

   int result = 1;

   Object $name = this.getName();

   int result = result * 59 + ($name == null ? 43 : $name.hashCode());

   Object $id = this.getId();

   result = result * 59 + ($id == null ? 43 : $id.hashCode());

   return result;

   public String toString() {

   return "ReqIn(name=" + this.getName() + ", id=" + this.getId() + ")";

   public ReqIn(@NonNull final String name, final String id) {

   if (name == null) {

   throw new NullPointerException("name is marked non-null but is null");

   } else {

   this.name = name;

   this.id = id;

  

 

   可见,对 setName() 和 @AllArgsConstructor 注解生成的全参数构造器,均对 name 入参做非 null 校验。

   但当 @Controller 内 @RequestMapping 注解的接口,若以 ReqIn 作为封装的请求对象,则接口调用时若没有传 name 字段,则会发现接口接收到的入参里,虽然字段被标注了 @NonNull,但 name 确实为 null。

   原因简单总述为:SpringMVC对参数解析和封装对象时,对于有无参构造器的对象,会使用无参构造器初始化,随后对传入的 Field 进行赋值,对没有传的 Field 则会忽略。因此,虽然带有 name 参数的构造器和 setName()均对 name 做了 null 校验,但实际上根本没有被调用。

   A)初始化被封装对象

  

   详述:

   1、SpringMVC对参数解析和封装对象时

   如果目标对象仅有一个 Constructor,则会调用该Constructor 封装对象;

   如果对象有多于一个Constructor,则会取无参构造器来封装对象,本例中无参构造器为手动生成,使用 @NoArgsConstructor 同样效果。

   如果对象没有指定构造器,这种情况在有 @NonNull 注解时不存在,因为 @NonNull 注解会对指定了该注解的 Field 生成 Constructor,参数与被注解字段数量一致。

  

   2、如果被 @NonNull 注解的字段为 String,则注解不会生效。

  

@Data

 

  @AllArgsConstructor

  public class ReqIn {

   @NonNull

   private String name;

   @NonNull

   private String id;

   public ReqIn(){

   System.out.println("无参构造");

  }
 

 

  

@RequestMapping("/req")
@Controller
public class ReqInController {
 @GetMapping("/testAnnotation")
 public String testAnnotation(ReqIn reqIn){
 System.out.println(reqIn);
 return "index";
 }
}

 

  


 

 

  

 

   2.1、如果请求时,带有 name 字段,则 name 字段会被设置为空字符串

  

请求:
http://localhost:1234/req/testAnnotation?id=133 name=

 

  

 

  

输出:
无参构造

 

  ReqIn(name=, id=133)

  

 

   2.2、如果请求时,不带有 name 字段,则 name 字段会被设置为 null

  

请求:
http://localhost:1234/req/testAnnotation?id=133

 

  

 

  

输出:
无参构造

 

  ReqIn(name=null, id=133)

  

 

   可见,对于 String 字段,在 SpringMVC 封装对象时,@NonNull 注解无法阻止字段被设置为null。

   原因在于,调用无参构造器之后,由于没有传入 name,封装对象的 parameterTypes 仅有 id,进而没有调用过 setName()方法,@NonNull 注解对 name 字段自然无法约束非 null。

  结论

   要使 @NonNull 注解对于指定 Field 生效,则需要

   1、被封装对象没有无参构造器

   2、如果被注解 Field 是 String 类型,则如果该参数为空时,不要作为请求的 key-value 对的 key 传到后端接口。

  

  
写博客这方面,转载是不可能转载的,这辈子都不可能转载,直接抄又没有脸去抄,只有自己随便划拉两笔,才能维持得了生活这样子。

  以上就是lombok@NonNull 注解无法对 SpringMVC 封装请求的对象的 Field 进行非空校验()的详细内容,想要了解更多 lombok@NonNull 注解无法对 SpringMVC 封装请求的对象的 Field 进行非空校验的内容,请持续关注盛行IT软件开发工作室。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: