Spring技巧:深入研究Java 14和SpringBoot

源碼時代 發佈 2020-04-27T07:33:23+00:00

privatefinal String findByIdSql = """ select * from PEOPLE where ID = ? """; private final String insertSql = """ insert into PEOPLE value

在本期文章中,我們將介紹Java 14中的新特性及其在構建基於SpringBoot的應用程式中的應用。



​開始,我們需要使用Java的最新版本,也是最棒的版本,Java 14,它現在還沒有發布。預計將於2020年初發運。上下載早期訪問版本。Java.net。您也可以考慮使用SDKManager(

sdk

),這使得安裝新JVM版本確實是一件小事。

記住,每6個月就有新的Java版本。這些新版本可以在生產中使用,但只支持一個版本和下一個版本之間的六個月。Java項目不時也會發布一個長期支持(LTS)版本。目前的版本是Java 11,Java 14在Java 15發布之前只是一個可行的生產目標。事實上,我們要研究的是預覽功能,人們可能會說,這根本不應該在生產中。你被警告了!

如果使用SDKManager,可以運行以下咒語來安裝Java 14。

sdk install java 14.ea.36-open

去Spring Initializr並使用SpringBoot2.3或更高版本生成一個新項目。您還需要選擇

JDBC

PostgreSQL

.

SpringBoot的舊版本還不支持Java 14運行時。當然,為了編輯這個版本的Java,您需要將它導入到IDE中。不過,在您這樣做之前,讓我們修改一下

pom.xml

要將構建配置為支持Java 14,通常,當您轉到SpringInitializr時,您還指定了Java的一個版本。目前還不支持Java 14,因此我們希望手動配置一些東西。

通過更改

java.version

財產:

<properties>

<java.version>14</java.version>

</properties>

這允許我們的構建使用Java 14和該版本中所有發布的特性,但是要真正體驗Java 14的新奇之處,我們需要打開預覽功能-發行版中提供的但默認情況下不活動的特性。

<plugins>...</plugins>

節,添加以下插件配置,以啟用Java 14的預覽功能。

<plugin>

<artifactId>maven-compiler-plugin</artifactId>

<configuration>

<release>14</release>

<compilerArgs>

<arg>--enable-preview</arg>

</compilerArgs>

<forceJavacCompilerUse>true</forceJavacCompilerUse>

<parameters>true</parameters>

</configuration>

</plugin>

<plugin>

<artifactId>maven-surefire-plugin</artifactId>

<configuration>

<argLine>--enable-preview</argLine>

</configuration>

</plugin>


現在你可以走了!讓我們看看一些Java代碼。SpringInitializr為我們提供了一個項目和一個基本入口點類:

package com.example.fourteen;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.boot.context.event.ApplicationReadyEvent;

import org.springframework.context.event.EventListener;

import org.springframework.jdbc.core.JdbcTemplate;

import org.springframework.jdbc.core.PreparedStatementCreatorFactory;

import org.springframework.jdbc.core.RowMapper;

import org.springframework.jdbc.core.SqlParameter;

import org.springframework.jdbc.support.GeneratedKeyHolder;

import org.springframework.stereotype.Component;

import org.springframework.stereotype.Service;

import java.sql.Types;

import java.util.List;

@SpringBootApplication

public class FourteenApplication {

public static void main(String[] args) {

SpringApplication.run(FourteenApplication.class, args);

}

}

我們將創建一個簡單的JDBC驅動服務,它使用SQL將其數據寫入資料庫。我們需要一個映射到資料庫表中數據的對象

people

.

此時,我通常要麼使用IDE的代碼生成工具來編寫Javabean對象,要麼使用Lombok來注釋我的方式到具有geters、setter的編譯器合成的對象,

toString

的實現

equals

。我甚至可能會勉強引用其他語言的能力,使這種乏味的工作變得瑣碎。Scala支持案例類。科特林支持數據類.

Java 14支持_Record_s。

record Person(Integer id, String name, int emotionalState) {

}

還不錯吧?這個語法包了一個Wallop!它提供了一個具有構造函數和構造函數參數、屬性、實現的新對象。

equals

toString

還有更多。我們可以像其他對象一樣實例化這個對象的實例。嘗試取消對象中的引用屬性,那麼我們的構造函數屬性就會變成

id()

/

id(int)

,

name()

/

name(String)

,和

emotionalState()

/

emotionalState(int)

。對這麼小的人來說還不錯!

讓我們看一下

PeopleService

.

這個

PeopleService

使用

JdbcTemplate

將資料庫查詢的結果轉換為Java對象的簡短工作。如果您曾經使用過

JdbcTemplate

(誰沒有)?我留下了一些未實現的部分,這樣我們就可以直接重新討論這些部分了。

@Service

class PeopleService {

private final JdbcTemplate template;

//todo

private final String findByIdSql = null;

private final String insertSql = null;

private final RowMapper<Person> personRowMapper =

(rs, rowNum) -> new Person(rs.getInt("id"), rs.getString("name"), rs.getInt("emotional_state"));

PeopleService(JdbcTemplate template) {

this.template = template;

}

public Person create(String name, EmotionalState state) {

//todo

}

public Person findById(Integer id) {

return this.template.queryForObject(this.findByIdSql, new Object[]{id}, this.personRowMapper);

}

}

首先,我們將使用一些SQL查詢。在我的生活中,為了避免在Java代碼中鍵入SQL查詢,我付出了很大的代價。我的天啊,如果人們知道自己能用Java來表達SQL查詢,他們會經常使用ORM嗎?

Strings

?對於任何稍微複雜的內容,我都會將SQL查詢提取到屬性文件中,然後用Spring的配置屬性機制加載這些文件。

但是,我們可以在Java 14中做得更好!多行字符串終於出現在Java上了!它現在加入了Python、Ruby、C++、C#、Rust、PHP、Kotlin、Scala、Groovy、Go、JavaScript、Clojure以及其他十幾種語言的行列。我很高興它終於來了!

替換

sql

具有以下聲明的變量。

private final String findByIdSql =

"""

select * from PEOPLE

where ID = ?

""";

private final String insertSql =

"""

insert into PEOPLE(name, emotional_state)

values (?,?);

""";

太好了,那個!有一些方法可以用來修剪邊距等等。還可以使用反斜槓轉義序列(

\

)在每一行的末尾,指示下一行應該從那裡開始,否則換行符就會被逐字解釋。

讓我們看看

create

方法。

存儲

Person

emotionalState

在資料庫中作為

int

是實現細節。我不想讓用戶有這種想法。讓我們用一個枚舉來描述每個人的情緒狀態

Person

:

enum EmotionalState {

SAD, HAPPY, NEUTRAL

}

我想這是個開始。讓我們來討論實現。我們馬上就有機會在Java 14中使用另一個很好的新特性:智能開關表達式。Switch表達式為我們提供了一種從開關大小寫的分支返回值的方法,然後將其賦值給變量。語法是差不多了和我們以前用過的一樣,只是每個箱子都是用箭頭從樹枝上射出的,->,不是:,沒有必要break聲明。

在下面的示例中,我們分配int變量的值index,我們不需要指定它的類型,因為最近Java疊代中的另一個很好的特性是自動類型推斷var.

public Person create(String name, EmotionalState state) {

var index = switch (state) {

case SAD -> -1;

case HAPPY -> 1;

case NEUTRAL -> 0;

};

// todo

}

帶著

index

在手,我們可以創造必要的

PreparedStatement

需要對資料庫執行SQL語句。我們可以執行準備好的語句並傳入一個

KeyHolder

它將用於收集從新插入的行返回的生成密鑰。

public Person create(String name, EmotionalState state) {

var index = switch (state) {

case SAD -> -1;

case HAPPY -> 1;

case NEUTRAL -> 0;

};

var declaredParameters = List.of(

new SqlParameter(Types.VARCHAR, "name"),

new SqlParameter(Types.INTEGER, "emotional_state"));

var pscf = new PreparedStatementCreatorFactory(this.insertSql, declaredParameters) {

{

setReturnGeneratedKeys(true);

setGeneratedKeysColumnNames("id");

}

};

var psc = pscf.newPreparedStatementCreator(List.of(name, index));

var kh = new GeneratedKeyHolder();

this.template.update(psc, kh);

// todo

}

唯一的問題是返回的密鑰是

Number

,而不是

Integer

或者是

Double

或者任何更具體的東西。這讓我們有機會在Java 14中使用另一個有趣的新特性,即智能轉換。智能轉換允許我們在測試

instanceof

測試一下。它更進一步,給出了一個變量名,通過它我們可以引用測試範圍中的自動強制轉換變量。

public Person create(String name, EmotionalState state) {

var index = switch (state) {

case SAD -> -1;

case HAPPY -> 1;

case NEUTRAL -> 0;

};

var declaredParameters = List.of(

new SqlParameter(Types.VARCHAR, "name"),

new SqlParameter(Types.INTEGER, "emotional_state"));

var pscf = new PreparedStatementCreatorFactory(this.insertSql, declaredParameters) {

{

setReturnGeneratedKeys(true);

setGeneratedKeysColumnNames("id");

}

};

var psc = pscf.newPreparedStatementCreator(List.of(name, index));

var kh = new GeneratedKeyHolder();

this.template.update(psc, kh);

if (kh.getKey() instanceof Integer id) {

return findById(id);

}

throw new IllegalArgumentException("we couldn't create the " + Person.class.getName() + "!");

}

我們需要一個

int

才能把它傳遞給

findById(Integer)

這種方法對我們來說是可行的。方便,嗯?

一切正常,所以讓我們用一個簡單的

ApplicationListener<ApplicationReadyEvent

:

@Component

class Runner {

private final PeopleService peopleService;

Runner(PeopleService peopleService) {

this.peopleService = peopleService;

}

@EventListener(ApplicationReadyEvent.class)

public void exercise() throws Exception {

var elizabeth = this.peopleService.create("Elizabeth", EmotionalState.SAD);

System.out.println(elizabeth);

}

}

運行它,您將看到對象已經寫入資料庫,而且--最好的是--您得到了一個漂亮的新

toString()

列印結果時的結果。

Person

反對!

我們剛剛開始觸及Java 14中所有新特性的表面!在這個視頻中,我們已經開始在語言中引入了大量的新特性,並且在運行時本身有更多的安全性和性能特性。我非常誠懇地建議您找到擺脫JDK舊版本的方法(看看您,Java 8用戶!)轉移到最新的。


為感謝您對我們的認可,特意準備了一些IT入門和進階的乾貨

包括:Java、UI設計、H5前端、Python+人工智慧、軟體測試和新媒體運營六大學科視頻資料。以及IT就業大禮包。

線上視頻、音頻,隨時學習觀看

關注我們並私信「資料」即可獲取。

關鍵字: