告別set和get澎蛛,兩大利器輕松搞定model轉(zhuǎn)換

場景一:一般我們遇到需要新建model宗兼,常規(guī)做法就是創(chuàng)建一個類躏鱼,老老實實的定義好model中的所有屬性氮采,一般來說屬性對應(yīng)的set方法和get方法都是少不了的殷绍,有時候還需要toString甚至equals和hashCode方法。

現(xiàn)在的IDE已經(jīng)很成熟了鹊漠,一般不會手寫set和get方法主到,采用IDE自帶的快捷方式自動生成居多茶行。如下圖所示

image

該方式相對手寫方法來說,效率已經(jīng)有了很大的提升登钥,但還是有進一步的提升空間(下文會介紹)畔师。而且該種方式維護性較差,當需要修改某個屬性名稱或者屬性類型時牧牢,對應(yīng)的set和get方法以及toString都需要調(diào)整看锉。

場景二:大部分時候,我們都是基于當前流行的微服務(wù)架構(gòu)和SSM(Spring+Spring MVC + Mybatis)框架進行開發(fā)塔鳍,這時候我個人經(jīng)常遇到一個問題就是model的轉(zhuǎn)換問題伯铣。

不同層會有不同的model,比如DAO層的model轮纫,service層的model腔寡,對外API接口的model,還有更上層的controller層的model以及提供給前端的View model掌唾。

為了能夠是接口正常調(diào)用放前,我們不得不處理這些model的轉(zhuǎn)換,沒有一個稱手的工具糯彬,我們只能手寫轉(zhuǎn)換類凭语,通過一個又一個的set和get方法來完成model的轉(zhuǎn)換。

有時候情连,我們在測試接口的時候發(fā)現(xiàn)有些屬性沒有值叽粹,調(diào)試半天才發(fā)現(xiàn),是因為其中一個屬性忘記寫set方法了却舀。我們明知道這些工作并不需要太多的思考虫几,但是卻不得不小心翼翼的對待。

那么挽拔,是否有更加優(yōu)雅的處理方式辆脸,請看下文介紹

Lombok

這是一個插件,能夠很好的解決場景一中的難題

下載安裝

我用的IDE是Intellij idea螃诅,可以在Preferences->Plugins中找到相應(yīng)的插件安裝并重啟即可啡氢。

image

該插件的實現(xiàn)已經(jīng)放在github上,有興趣可以到https://github.com/mplushnikov/lombok-intellij-plugin查看

lombok使用

添加jar包依賴

在你需要的項目的pom文件中添加如下的依賴


<dependency>  <groupId>org.projectlombok</groupId>  <artifactId>lombok</artifactId>  <version>1.16.18</version>  </dependency>

編寫model

package com.jackie.wowjava.best.practice.java.orika.model;

import java.util.Date;

public class AuthorDTO {   private String name;

    private Date birthday;
}

添加需要的注解

Lombok可以通過注解的方式實現(xiàn)你需要添加的方法术裸,比如你需要添加這些屬性對應(yīng)的set方法倘是,那么只要在model類上添加注解@Setter即可,相應(yīng)的袭艺,如果需要get方法添加@Getter搀崭。

此外還有@ToString@NoArgsConstructor猾编,@AllArgsConstructor等方便使用的注解瘤睹。

事實上升敲,我們真的只需要這樣添加注解的方式,就能夠?qū)崿F(xiàn)輕松調(diào)用set和get方法的需要轰传。這樣驴党,以后如果model的屬性有改變,我們只需要直接改相應(yīng)的屬性即可获茬,不再需要做任何一點多余的操作港庄。

將注解還原為具體方法

Lombok為我們提供可以將對應(yīng)注解還原為對應(yīng)方法的功能。

點擊Refactor->Delombok選擇想還原的方法即可

image

是不是很好用恕曲?

Orika

Orika是一個簡單快速的model拷貝框架攘轩。

Orika使用

添加jar包依賴

在需要使用的項目的pom文件中添加如下依賴


<dependency>  <groupId>ma.glasnost.orika</groupId>  <artifactId>orika-core</artifactId>  <version>1.5.2</version>  </dependency>

創(chuàng)建兩個需要轉(zhuǎn)換的model

BookEntity


package com.jackie.wowjava.best.practice.java.orika.model;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import java.util.Date;

@Setter @Getter @AllArgsConstructor @NoArgsConstructor public class BookEntity {   private String bookName;

    private String authorName;

    private Date authorBirthday;

    private String bookInformation;

    private Integer type;

} 

BookDTO


package com.jackie.wowjava.best.practice.java.orika.model;

import lombok.Getter;
import lombok.Setter;

@Setter @Getter public class BookDTO {   private String bookName;

    private AuthorDTO author;

    private BookType bookType;

    private BookInfo bookInfo;
}

備注:這里的AuthorDTO、BookType和BookInfo如下


package com.jackie.wowjava.best.practice.java.orika.model;

import lombok.*;

import java.util.Date;

@Setter @Getter @ToString @NoArgsConstructor @AllArgsConstructor public class AuthorDTO {   private String name;

    private Date birthday;
} 


package com.jackie.wowjava.best.practice.java.orika.model;

public enum BookType {
 NOVEL(1),
    ESSAY(2);

    private int value;

    BookType(int value) {
 this.value = value;
    }   public static BookType getBookType(int value) {
 BookType bookType = null;

        switch (value) {
 case 1:
                bookType = NOVEL;
                break;
            case 2:
                bookType = ESSAY;
                break;
            default:
                break;
        }
 return bookType;
    }   public int getValue() {
 return value;
    } } 


package com.jackie.wowjava.best.practice.java.orika.model;

import lombok.Getter;
import lombok.Setter;

@Setter @Getter public class BookInfo {   private String ISBN;

    private int page;
}

你沒看錯码俩,就是BookDTO和BookEntity這兩個model度帮,需要相互轉(zhuǎn)換,Orika可以幫你搞定稿存,具體看下面是如何實現(xiàn)的笨篷。

model轉(zhuǎn)換

我們看到兩個model中包含了多種情況

  • 屬性名稱完全一樣的,比如bookName

  • 一個屬性對應(yīng)一個對象的瓣履,BookDTO中的AuthorDTO對應(yīng)BookEntity中的authorName以及authorBirthday

  • 枚舉類型的率翅,比如BookEntity的type和BookDTO的BookType

  • JSON類型的,比如BookEntity的bookInformation和BookDTO的bookInfo

1袖迎、屬性名稱完全一樣的屬性拷貝

新建測試類OrikaTest


package com.jackie.wowjava.best.practice.java.orika;

import com.alibaba.fastjson.JSON;
import com.jackie.wowjava.best.practice.java.orika.model.BookDTO;
import com.jackie.wowjava.best.practice.java.orika.model.BookEntity;
import com.jackie.wowjava.best.practice.java.orika.model.BookInfo;
import com.jackie.wowjava.best.practice.java.orika.model.BookType;
import ma.glasnost.orika.MapperFactory;
import ma.glasnost.orika.MappingContext;
import ma.glasnost.orika.converter.BidirectionalConverter;
import ma.glasnost.orika.impl.DefaultMapperFactory;
import ma.glasnost.orika.metadata.Type;

import java.time.LocalDate;
import java.time.Month;
import java.time.ZoneId;
import java.util.Date;

public class OrikaTest {   private static final MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();

    public static void main(String[] args) {   BookEntity bookEntity = new BookEntity(
 "銀河系漫游指南",
                "道格拉斯·亞當斯",
                Date.from(LocalDate.of(1952, Month.MARCH, 11).atStartOfDay(ZoneId.systemDefault()).toInstant()),
                "{\"ISBN\": \"9787532754687\", \n \"page\": 279\n }",
                1);

        BookDTO bookDTO = mapperFactory.getMapperFacade().map(bookEntity, BookDTO.class);

        System.out.println(JSON.toJSONString(bookDTO));
    } } 

運行結(jié)果如下


{"bookName":"銀河系漫游指南"}

沒錯冕臭,只有名稱相同的屬性被轉(zhuǎn)換了。

從代碼來看燕锥,我們不需要做任何特殊化處理就能做到這一點辜贵,因為Orika默認就是按照名稱相同就拷貝進行處理的。

2归形、一個屬性對應(yīng)一個對象的屬性拷貝

這里我們是想BookDTO中的AuthorDTO對應(yīng)BookEntity中的authorName以及authorBirthday托慨。

我們只需要添加如下代碼即可實現(xiàn)。


mapperFactory.classMap(BookDTO.class, BookEntity.class)
 .field("author.name", "authorName")
 .field("author.birthday", "authorBirthday")
 .byDefault()
 .register();

運行結(jié)果如下


{"author":{"birthday":-562060800000,"name":"道格拉斯·亞當斯"},"bookName":"銀河系漫游指南"}

3暇榴、枚舉類型的屬性拷貝

這時候我們需要新建一個轉(zhuǎn)換器并注冊到mapperFactory上厚棵。

注冊轉(zhuǎn)換器代碼如下


mapperFactory.getConverterFactory().registerConverter("bookTypeConvert", new BidirectionalConverter<BookType, Integer>() {
 @Override
 public Integer convertTo(BookType bookType, Type<Integer> type, MappingContext mappingContext) {
 return bookType.getValue();
    }   @Override
 public BookType convertFrom(Integer value, Type<BookType> type, MappingContext mappingContext) {
 return BookType.getBookType(value);
    } });

注冊轉(zhuǎn)換器代碼如下


mapperFactory.classMap(BookDTO.class, BookEntity.class)
 .field("author.name", "authorName")
 .field("author.birthday", "authorBirthday")
 .fieldMap("bookType", "type").converter("bookTypeConvert").add()
 .byDefault()
 .register();

運行結(jié)果如下:


{"author":{"birthday":-562060800000,"name":"道格拉斯·亞當斯"},"bookName":"銀河系漫游指南","bookType":"NOVEL"}

4、JSON類型的屬性轉(zhuǎn)換

該屬性的轉(zhuǎn)換原理和上述的枚舉類型轉(zhuǎn)換相同蔼紧,需要創(chuàng)建轉(zhuǎn)換器并注冊使用


mapperFactory.getConverterFactory().registerConverter("bookInfoConvert", new BidirectionalConverter<BookInfo, String>() {
 @Override
 public String convertTo(BookInfo bookInfo, Type<String> type, MappingContext mappingContext) {
 return JSON.toJSONString(bookInfo);
    }   @Override
 public BookInfo convertFrom(String s, Type<BookInfo> type, MappingContext mappingContext) {
 return JSON.parseObject(s, BookInfo.class);
    } });



mapperFactory.classMap(BookDTO.class, BookEntity.class)
 .field("author.name", "authorName")
 .field("author.birthday", "authorBirthday")
 .fieldMap("bookType", "type").converter("bookTypeConvert").add()
 .fieldMap("bookInfo", "bookInformation").converter("bookInfoConvert").add()
 .byDefault()
 .register();

運行結(jié)果如下


{"author":{"birthday":-562060800000,"name":"道格拉斯·亞當斯"},"bookInfo":{"iSBN":"9787532754687","page":279},"bookName":"銀河系漫游指南","bookType":"NOVEL"}

是不是很神奇婆硬?

?

總結(jié)

相信有了這兩大神奇Lombok和Orika,基本上實現(xiàn)了和set和get的真正告別奸例。

項目代碼地址:https://github.com/DMinerJackie/rome

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末彬犯,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,110評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件奥务,死亡現(xiàn)場離奇詭異欺缘,居然都是意外死亡,警方通過查閱死者的電腦和手機箭阶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,443評論 3 395
  • 文/潘曉璐 我一進店門虚茶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人仇参,你說我怎么就攤上這事嘹叫。” “怎么了诈乒?”我有些...
    開封第一講書人閱讀 165,474評論 0 356
  • 文/不壞的土叔 我叫張陵罩扇,是天一觀的道長。 經(jīng)常有香客問我怕磨,道長喂饥,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,881評論 1 295
  • 正文 為了忘掉前任肠鲫,我火速辦了婚禮员帮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘导饲。我一直安慰自己捞高,他們只是感情好,可當我...
    茶點故事閱讀 67,902評論 6 392
  • 文/花漫 我一把揭開白布渣锦。 她就那樣靜靜地躺著硝岗,像睡著了一般。 火紅的嫁衣襯著肌膚如雪袋毙。 梳的紋絲不亂的頭發(fā)上辈讶,一...
    開封第一講書人閱讀 51,698評論 1 305
  • 那天,我揣著相機與錄音娄猫,去河邊找鬼贱除。 笑死,一個胖子當著我的面吹牛媳溺,可吹牛的內(nèi)容都是我干的月幌。 我是一名探鬼主播,決...
    沈念sama閱讀 40,418評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼悬蔽,長吁一口氣:“原來是場噩夢啊……” “哼扯躺!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,332評論 0 276
  • 序言:老撾萬榮一對情侶失蹤录语,失蹤者是張志新(化名)和其女友劉穎倍啥,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體澎埠,經(jīng)...
    沈念sama閱讀 45,796評論 1 316
  • 正文 獨居荒郊野嶺守林人離奇死亡虽缕,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,968評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了蒲稳。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片氮趋。...
    茶點故事閱讀 40,110評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖江耀,靈堂內(nèi)的尸體忽然破棺而出剩胁,到底是詐尸還是另有隱情,我是刑警寧澤祥国,帶...
    沈念sama閱讀 35,792評論 5 346
  • 正文 年R本政府宣布昵观,位于F島的核電站,受9級特大地震影響舌稀,放射性物質(zhì)發(fā)生泄漏索昂。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,455評論 3 331
  • 文/蒙蒙 一扩借、第九天 我趴在偏房一處隱蔽的房頂上張望椒惨。 院中可真熱鬧,春花似錦潮罪、人聲如沸康谆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,003評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽沃暗。三九已至,卻和暖如春何恶,著一層夾襖步出監(jiān)牢的瞬間孽锥,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,130評論 1 272
  • 我被黑心中介騙來泰國打工细层, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留惜辑,地道東北人。 一個月前我還...
    沈念sama閱讀 48,348評論 3 373
  • 正文 我出身青樓疫赎,卻偏偏與公主長得像盛撑,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子捧搞,可洞房花燭夜當晚...
    茶點故事閱讀 45,047評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 變抵卫,這是個很日常的話題狮荔!變好變壞,變丑變美介粘,變窮變富……這個世界每一秒鐘都在發(fā)生著變化殖氏,大大小小,多多少...
    禍福相依_閱讀 310評論 0 0
  • 第011 校園的花兒開了 文/何文斌 沒有清華園荷葉的清韻 沒有末名湖畔春桃的靈動 火紅的石榴 在逝去的春光中嫣紅...
    何文斌簡書閱讀 369評論 0 1
  • 文/小番茄Zoe 廢話說在前頭姻采,我這個人真的不愛刷劇雅采。但!我最近真的是太(重音)無聊了Y怂!纲堵!心血來潮巡雨,點開了當時為...
    菜菜要開心呀閱讀 10,803評論 0 0