Lombok首字母小写,第二个字母大写的问题

一、问题描述

最近在和前端对接接口的时候,发现后端接口返回给前端的一个字段大小写有问题,具体如下。

使用的开发框架及版本:

框架:SpringMVC;
Lombok版本:1.18.12;

对象简化后如下:

  1.  
    @Data
  2.  
    public class MobileInfo {
  3.  
    private String iPhone;
  4.  
    }

预期返回结果:iPhone,实际返回结果:iphone

也就是说SpringMVC环境下,使用Lombok注解@Data之后,返回给前端的是iphone,而不是我们预期中的iPhone

二、原因

针对首字母小写,第二个字母大写的这种驼峰命名时,使用@Data注解生成的getter和setter方法分别是:

  1.  
    public String getIPhone() {
  2.  
    return iPhone;
  3.  
    }
  4.  
     
  5.  
    public void setIPhone(String iPhone) {
  6.  
    this.iPhone = iPhone;
  7.  
    }

而正常场景下及Spring中对象的getter和setter方法应该是:

  1.  
    public String getiPhone() {
  2.  
    return iPhone;
  3.  
    }
  4.  
     
  5.  
    public void setiPhone(String iPhone) {
  6.  
    this.iPhone = iPhone;
  7.  
    }

也就是说Lombok与Spring针对这种首字母小写,第二个字母大写的对象的解析是不同的,而这也就自然而然影响到默认的Jackson的解析,导致返回给前端的属性名称不是我们预期中的名称。

2.1 Lombok问题

其实,针对这个问题,多年前就有人已经在lombok的github提出过对应的issue,参考:

https://github.com/projectlombok/lombok/issues/757

其实,无论是Lombok还是Spring,在处理对象的时候总会有一个API规范进行参考的,这个规范一般就是JavaBeans API的规范。而针对这个问题,Lombok的官方回复是:

JavaBeans的规范就是这样的,Lombok只是遵循这个规范而已,并且不应该使用首字母小写,第二个字母大写这样的命名规则,而Spring的处理方式才是没有遵循JavaBean的规范。除非Oracle官方推荐如此或者大家都是这样处理的化,Lombok才会进行修改。

也就是说,Lombok认为,JavaBeans的规范就是这么定义的,而针对JavaBean的规范,Spring和Lombok选择了不同的实现方式:

  • Spring,Jackson针对get/set的生成方式,和我们使用 IDEA 编译器自动生成get/set的方式是相同的,都是诸如getiPhone()的形式。
  • Lombok,针对get/set的生成方式,是getIPhone()的形式。

那么,针对JavaBeans规范的定义,到底是Spring的这种方式正确呢,还是Lombok的解析方式正确呢?

2.2 JavaBeans API规范

Lombok官方回复的JavaBeans API规范,是Sun 1997年的API规范文档:

https://download.oracle.com/otndocs/jcp/7224-javabeans-1.01-fr-spec-oth-JSpec/

根据这个文档,我去stackoverflow上搜了一下,最接近这个问题的描述应该是:8.8 Capitalization of inferred names

其实根据JavaBeans的描述,是没有具体说明针对我们文中这个问题,首字母小写,第二个字母大写这样的字段该如何get/set的,不过如果强行按照JavaBeans的规范来的话,那这个其实应该是:

  1.  
    public String getiPhone() { return iPhone;}
  2.  
    public void setiPhone(String iPhone) { this.iPhone = iPhone;}

那如果从这点上来说的话,其实Lombok的说法就不太恰当的了。

不过还有一种方式,就是如果站在Java中方法命名的角度上来说的话,也就是:Defing Methods - Naming a Method
那么,正确的命名方式应该是:

  1.  
    public String getIPhone() { return iPhone;}
  2.  
    public void setIPhone(String iPhone) { this.iPhone = iPhone;}

那么站到这个角度的话,Spring的方式又是不太恰当的了。

不过,总的来说,Lombok和Spring他们各自的实现本身没啥问题,只是针对javaBean的规范,各自选择了不同的实现策咯而已。

大家有兴趣的可以看下stackoverflow上的讨论及Lombok的回复:
https://stackoverflow.com/questions/2948083/naming-convention-for-getters-setters-in-java/49348966#49348966
https://github.com/projectlombok/lombok/issues/504

三、解决方式

知道了原因,其实解决起来也非常简单了,就是针对这种对象,手动生成get和set方法即可,或者使用编译器自动生成的,也就是如下:

  1.  
    public String getiPhone() {
  2.  
    return iPhone;
  3.  
    }
  4.  
     
  5.  
    public void setiPhone(String iPhone) {
  6.  
    this.iPhone = iPhone;
  7.  
    }

当然为了避免这种问题发生,还有一种更简单的方式,就是命名的时候,不要使用诸如xXXXX这种格式的命名,使用正常的命名方式,比如indexX这种形式。

posted @ 2022-08-29 10:13  liftsail  阅读(204)  评论(0编辑  收藏  举报