基于Spring框架的開發(fā)最佳實踐_第1頁
基于Spring框架的開發(fā)最佳實踐_第2頁
基于Spring框架的開發(fā)最佳實踐_第3頁
基于Spring框架的開發(fā)最佳實踐_第4頁
基于Spring框架的開發(fā)最佳實踐_第5頁
已閱讀5頁,還剩90頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)

文檔簡介

1、1基于Spring框架的開發(fā)最佳實踐目 錄 HYPERLINK l _bookmark1 使用 Spring Data 進行 MongoDB 4.0 事務(wù)處理 HYPERLINK l _bookmark2 基于Spring Cloud Stream構(gòu)建和測試 message-driven 微服務(wù) HYPERLINK l _bookmark3 使用JDK11中String類的新方法 HYPERLINK l _bookmark4 24.Spring Data MongoDB 簡介 HYPERLINK l _bookmark5 25.Spring Data MongoDB Indexes, Anno

2、tations and Converters HYPERLINK l _bookmark6 26.Spring Data MongoDB 中的查詢指南 HYPERLINK l _bookmark0 本周Spring大事件- HYPERLINK l _bookmark7 Spring Data MongoDB中自定義級聯(lián) HYPERLINK l _bookmark8 29.Spring Boot 2 容器配置 HYPERLINK l _bookmark9 本周Spring大事件 HYPERLINK l _bookmark10 使用 Spring Boot 后端的 Vue.js 前端Spring

3、Boot 日志 HYPERLINK l _bookmark11 Spring Boot中嵌入式Servlet容器的比較 HYPERLINK l _bookmark12 34.在Spring WebFlux中處理錯誤 HYPERLINK l _bookmark13 Spring 中 BeanFactory 和 ApplicationContext 的區(qū)別 HYPERLINK l _bookmark14 Spring 5 WebFlux入門 HYPERLINK l _bookmark15 37.什么是 Spring Boot? HYPERLINK l _bookmark16 38.Spring v

4、s. Spring Boot:Java框架之間的比較 HYPERLINK l _bookmark17 39.使用 Docker 進行 Spring Boot 開發(fā) HYPERLINK l _bookmark18 40.排名前20的REST和Spring MVC面試題091.201.21 PAGE 45使用 Spring Data 進行 MongoDB 4.0 事務(wù)處理在 HYPERLINK /transactions MongoDB 4.0 中,ACID 事務(wù)已經(jīng)用于 D

5、ocument 的存儲,強制維護全執(zhí)行或全不執(zhí)行的數(shù)據(jù)一致性狀態(tài)。所以讓我們直接在 synchronous 模型和 reactive 執(zhí)行模型中驗證該特性。在撰寫本文時,MongoDB 的多文檔事務(wù)在單副本集中受支持,并且給用戶的感受像是在使用關(guān)系型數(shù)據(jù)庫的事務(wù)一樣??吹津?qū)動程序提供的 API 立刻會感覺到回到家里一樣。try (ClientSession session = client.startSession() session.startTransaction();try collection.insertOne(session, documentOne); collection.in

6、sertOne(session, documentTwo); mitTransaction(); catch (Exception e) session.abortTransaction();邏輯會話建立在 MongoDB的基礎(chǔ)上,當(dāng)然,事務(wù),當(dāng)然還有事務(wù)構(gòu)建了基礎(chǔ)。邏輯會話通過幫助跨分布式節(jié)點協(xié)調(diào)操作來為MangoDB的 HYPERLINK /manual/core/read-isolation-consistency-recency/ l causal-consistency 因果一致性和事務(wù)建立基礎(chǔ)。客戶端從 client.startSession() 中獲取會話,會話的生命周期不應(yīng)過長

7、,在不再使用的時候應(yīng)該立刻關(guān)閉它。所以確保使用 close() 來關(guān)閉客戶端會話。在底層的協(xié)議層,上面的代碼片段將會轉(zhuǎn)變?yōu)槿缦乱幌盗忻?,你可以清楚的發(fā)現(xiàn)在每個命令中都包含會話( lsid )。 startTransaction 標(biāo)志位將會與第一個命令一起發(fā)送,表示事務(wù)的開始。在事務(wù)完成后, 發(fā)送 commitTransaction 表示事務(wù)的提交。 insert: col, ordered: true, $db: db,$clusterTime: ,lsid: id: $binary: base64 : I3M7Nj, , txnNumber: 1,startTransaction: tru

8、e, documents: insert: col, ordered: true, $db: db,$clusterTime: ,lsid: id: $binary: base64 : I3M7Nj, , txnNumber: 1,autocommit: false, documents: commitTransaction: 1,$db: admin,$clusterTime: ,lsid: id: $binary: base64 : I3M7Nj, , txnNumber: 1 隨著即將發(fā)布的 Spring Data HYPERLINK /spring-projects/spring-da

9、ta-commons/wiki/Release-Train-Lovelace Lovelace 版本,MongoDB 模塊將提供對 synchronous 和 reactive 事務(wù)的支持。 HYPERLINK https:/docs.spring.io/spring/docs/current/spring-framework-reference/data-access.html l transaction 我們從 synchronous 模式開始,你可以能已經(jīng)非常熟悉 Spring 框架對事務(wù)的支持 (Spring Frameworks transaction support) 。因此,一個

10、 MongoTransactionManager 的存在并不令人吃驚。該事務(wù)管理器是在命令式世界中基于注解的事務(wù)支持的入口。現(xiàn)在,因為 MongoDB 在早期版本中不支持事務(wù),你必須明確的在 ApplicationContext 中注冊 MongoTransactionManager 。如果你這樣做的話, MongoTemplate 將會開始參與管理事務(wù)。這是一個你需要記住的要點。下面的例子展示了你應(yīng)該如何配置事務(wù)管理器。Configurationclass Config extends AbstractMongoConfiguration BeanMongoTransactionManage

11、r transactionManager(MongoDbFactory dbFactory) return new MongoTransactionManager(dbFactory);Serviceclass DocumentService private final MongoOperations operations; DocumentService(MongoOperations operations) this.operations = operations;Transactionalvoid insertDocuments() operations.insert(documentO

12、ne); operations.insert(documentTwo);非常直播的操作是吧?但是,這里有一些隱含的缺點。 HYPERLINK /manual/sharding/ l sharded-cluster 集群環(huán)境下的事務(wù)支持在下一個 MongDB 的release 主要版本中才會支持,因此在您使用時會發(fā)生錯誤。此外,作為一個 MongoDB 的用戶,你可能已經(jīng)習(xí)慣了他提供的所有的便利,但一些特性在事務(wù)中無法使用了,包括了幾乎所有的元命令,創(chuàng)建集合,索引以及受此使用集合時隱式創(chuàng)建集合。為了避免錯誤和折騰,請務(wù)必設(shè)置所需的結(jié)構(gòu)。此外, 某些命令可能還會有一些不同。例如使用集合集合統(tǒng)計信息

13、的 count 命令可能在事務(wù)中并不準(zhǔn)確。命令將會出錯并且需要使用聚合計數(shù)文檔,當(dāng)前的驅(qū)動已經(jīng)提供一個替代方法 countDocuments 來利用聚合策略解決這個問題??紤]到這一點,讓我們繼續(xù)進行 reactive 使用的部分。在 HYPERLINK https:/mongodb.github.io/mongo-java-driver-reactivestreams/ MongoDB的ReactiveStreams驅(qū)動程序 提供了一個反應(yīng)切入點多文檔交易。將本機驅(qū)動程序管道 Publisher 化為 HYPERLINK https:/projectreactor.io/ Reactor 類型

14、可讓您表達事務(wù)用法,如下所示:Mono.from(client.startSession().flatMap(session - session.startTransaction();return Mono.from(collection.insertOne(session, documentOne).then(Mono.from(collection.insertOne(session, documentTwo).onErrorResume(e - Mono.from(session.abortTransaction().then(Mono.error(e).flatMap(val - Mo

15、no.from(mitTransaction().then(Mono.just(val).doFinally(signal - session.close(););不管事務(wù)的結(jié)果是成功還是回滾,我們都需要保證事務(wù)的終止。因此, onErrorResume(.) 保證了事務(wù)在失敗的時候可以回滾,然后在 flatMap(.) 中提交,這兩個階段都保存了主流 (main flow) 的結(jié)果或錯誤。 不同于 sync 部分,截止撰稿時還沒有 reactive 模型可用的事務(wù)管理器能夠讓你通過注解 Transactional 那樣簡單的完成事務(wù)工作。 相反,你需要通過 ReactiveMongoTemp

16、late.inTransaction(.)獲取一個 transaction 閉包。它在保持主流 (main flow) 結(jié)果的同事負(fù)責(zé)所有必需的會話,提交和終止操作。回調(diào)方法中的操作在MongoDB事務(wù)中執(zhí)行,而外部的處理步驟將不會影響事務(wù)。這意味著閉包之外的處理錯誤不會導(dǎo)致事務(wù)終止,就像下面的例子描述的那樣。template.inTransaction().execute(action -/ All code in here runs inside the transaction action.insert(documentOne).then(action.insert(documentTw

17、o).flatMap(val - / An exception here does not affect the transaction);在這個例子中,你能夠通過流訪問到 ClientSession ,它存放在 Reactor 的 Context 中,并且你可以通過 ReactiveMongoContext.getSession() 來獲取它。 HYPERLINK /spring-projects/spring-data-examples 最后一件事情:我們非常高興你能夠嘗試并且給我們提供一些反饋,所以請查看 Spring Data Examples,您可以在其中找到相關(guān)的 HYPERLIN

18、K /spring-projects/spring-data-examples/tree/master/mongodb/transactions 項目 HYPERLINK /spring-projects/spring-data-examples 。如果你想要學(xué)習(xí)更多有關(guān) Spring Data 或者通用的 Spring eco-system,即將在華盛頓召開的 HYPERLINK https:/springoneplatform.io/ SpringOne Platform 會議對您來說是一個非常好的機會。查看 HYPERLINK https:/springoneplatform.io/20

19、18/sessions 會話并注冊。基于Spring Cloud Stream構(gòu)建和測試 message- driven 微服務(wù)Spring Boot和Spring Cloud HYPERLINK /2018/04/26/quick-guide-to-microservices-with-spring-boot-2-0-eureka-and-spring-cloud/ 為您提供了一個利用不同的通信方式快速構(gòu)建微服務(wù)的解決方案。您可以基于Spring Cloud Netflix庫創(chuàng)建同步REST微服務(wù),正如我在之前的一篇文章中所展示的那樣 使用Spring Boot 2.0, Eureka an

20、d Spring Cloud快速搭建微服務(wù)指南。您可以使用Spring WebFlux項目在Netty上創(chuàng) HYPERLINK /2018/05/04/reactive-microservices-with-spring-webflux-and-spring-cloud/ 建異步的、響應(yīng)式的微服務(wù),并將其與一些Spring Cloud庫相結(jié)合,如我的文章所示 使用Spring WebFlux and Spring Cloud搭建響應(yīng)式微服務(wù)。最后,您可以使用Spring Cloud Stream和類似Apache Kafka或RabbitMQ這樣的broker來實現(xiàn)基于發(fā)布/訂閱模型的mess

21、age-driven微服務(wù)。構(gòu)建微服務(wù)的最后一種方法是本文的主要主題。我將向您展示如何在RabbitMQ broker的基礎(chǔ)上有效地構(gòu)建、擴展、運行和測試消息傳遞微服務(wù)。體系結(jié)構(gòu)為了演示Spring Cloud Stream的特性,我們將設(shè)計一個示例系統(tǒng),該系統(tǒng)使用發(fā)布/訂閱模型進行跨服務(wù)通信。我們有三個微服務(wù): order-service 、 product-service 和 account-service 。應(yīng)用程序 order- service 暴露了負(fù)責(zé)處理發(fā)送到我們系統(tǒng)的訂單的HTTP endpoint。所有傳入的訂單都是異步處理的 order-service 準(zhǔn)備并發(fā)送消息到Ra

22、bbitMQ exchange,然后就對調(diào)用的客戶端進行響應(yīng),不需要等到消息被消費后再響應(yīng)。應(yīng)用程序的 account-service 和 product-service 正在偵聽進入該RabbitMQ exchange的訂單消息。微服務(wù) account-service 負(fù)責(zé)檢查客戶賬戶是否有足夠的資金來支付該訂單需要的金額,如果有就從該賬戶扣款。微服務(wù) product-service 檢查是否有足夠的庫存,并在處理訂單后改變可用產(chǎn)品的數(shù)量。 account-service 和 product-service 都通過RabbitMQ exchange(這一次是使用direct exchange

23、的一對一通信)發(fā)送帶有操作狀態(tài)的異步響應(yīng)。微服務(wù) order-service 根據(jù)接收到的響應(yīng)消息來更新訂單狀態(tài),并通過REST endpoint GET /order/id 提供給外部客戶端。如果您覺得我們的示例描述有點難以理解,這里有一個用于澄清的架構(gòu)圖。啟用 Spring Cloud Stream在項目中使用Spring Cloud Stream的推薦方法是使用依賴管理系統(tǒng)。Spring Cloud Stream有一個與整個Spring Cloud framework相關(guān),并且獨立發(fā)布的依賴管理。然而,如果我們已經(jīng)在 Elmhurst.RELEASE 版本的 dependencyMana

24、gement 部分聲明了 spring-cloud-dependencies ,就不需要在 pom.xml 中聲明任何其他內(nèi)容。如果您喜歡只使用Spring Cloud Stream項目,那么您應(yīng)該定義以下部分。下一步是將 spring-cloud-stream artifact添加到項目依賴項中。我還建議您至少包括 spring-cloud-sleuth 庫,以提供作為源請求進入 order-service 的發(fā)送消息用的 traceId 。Spring Cloud Stream 編程模型為了使您的應(yīng)用程序能夠連接到一個message broker,請在主類上使用 EnableBinding

25、 注解。 EnableBinding 注解將一個或多個接口作為參數(shù)。您可以在Spring Cloud Stream提供的三個接口之間進行選擇:Sink:這是用來標(biāo)記從入站通道接收消息的服務(wù)。Source: 這是用來向出站通道發(fā)送消息的。Processor:當(dāng)你需要一個入站通道和一個出站通道時,它可以被使用,因為它繼承了Source and Sink接口。因為order-service發(fā)送消息,并接收它們,它的主類已經(jīng)使用了EnableBinding(Processor.class)order-service注解。下面是項目中啟用了Spring Cloud Stream binding的主類。S

26、pringBootApplication EnableBinding(Processor.class) public class OrderApplication .public static void main(String args) new SpringApplicationBuilder(OrderApplication.class).web(true).run(args);.增加 message broker在Spring Cloud Stream術(shù)語中,負(fù)責(zé)與特定message broker集成的實現(xiàn)稱為binder。默認(rèn)情況下, Spring Cloud Stream為 Kafk

27、a and RabbitMQ提供了binder實現(xiàn)。它能夠自動檢測和在類路徑上查找binder。任何特定于中間件的設(shè)置都可以通過Spring Boot支持的外部配置屬性來覆蓋,譬如應(yīng)用程序參數(shù)、環(huán)境變量,或者僅僅是 application.yml 文件。為了包含對RabbitMQ的支持,RabbitMQ將這篇文章用作message broker,您應(yīng)該向項目添加以下依賴項。現(xiàn)在,我們的應(yīng)用程序需要連接RabbitMQ broker的一個共享實例。這就是為什么我使用RabbitMQ在默認(rèn)的5672端口上運行Docker鏡像。它還可以在地址http:/00:15672(00:15672/)下啟動w

28、eb儀表板。我們需要通過設(shè)置屬性 spring.rabbitmq.host 為Docker機器IP 00 ,來覆蓋Spring Boot application的中的默認(rèn)設(shè)置。實現(xiàn)消息驅(qū)動的微服務(wù)Spring Cloud Stream是在Spring Integration項目之上構(gòu)建的。Spring Integration擴展了Spring編程模型,以支持眾所周知的企業(yè)集成模式(EIP)。EIP定義了許多在分布式系統(tǒng)中經(jīng)常使用的經(jīng)典組件。您可能已經(jīng)聽說過諸如消息通道、路由器、聚合器或endpoints之類的模式。讓我們回到上面的例子。讓我們從 order-service 開始,它負(fù)責(zé)接收訂單

29、,將它們發(fā)布在shared topic上,然后從下游服務(wù)收集異步響應(yīng)。下面是service,它使用 Source bean來構(gòu)建消息并將其發(fā)布到遠程topic。這個 Service 是由controller調(diào)用,controller暴露提交新訂單和通過 id 獲得訂單狀態(tài)的HTTP endpoints。現(xiàn)在,讓我們更仔細地看看消費端。來自 order-service 的 OrderSender bean所發(fā)送的消息是由 account- service 和 product-service 接收。為了從 topic exchange中接收消息,我們只需要在入?yún)镺rder的方法上添加 Strea

30、mListener 注解。我們還必須為監(jiān)聽器定義目標(biāo)通道在這種情況下,它是 Processor.INPUT 。譬如:StreamListener(Processor.INPUT)public void receiveOrder(Order order) throws JsonProcessingException LOGGER.info(Order received: , mapper.writeValueAsString(order); cess(order);接收訂單由 AccountService bean處理。 account-service 會根據(jù)客戶賬戶上是否有足夠的資金來實現(xiàn)訂單

31、接受或拒絕訂單。驗收狀態(tài)的響應(yīng)通過 OrderSender bean調(diào)用的輸出通道發(fā)回 order-service 。最后一步是配置。它是在 application.yml 中提供的。我們必須正確地定義通道的destination。而 order- service 則將 orders-out destination分配給輸出通道,而 orders-in destination則是輸入通道, account- service 和 product-service 則恰恰相反。這是合乎邏輯的,因為通過其輸出destination通過 order- service 發(fā)送的消息是通過其輸入destina

32、tion接收的服務(wù)接收的。但在shared brokers exchange中,它仍然是相同的destination。下面是 order-service 的配置設(shè)置。spring:application:name: order-service rabbitmq:host: 00port: 5672 cloud:stream:bindings:output:destination: orders-out producer:partitionKeyExpression: payload.customerId partitionCount: 2input:destination: orders-in

33、 rabbit:bindings:input:consumer: exchangeType: direct這是為 account-service 和 product-service 提供的配置。最后,您可以運行上面示例中的微服務(wù)?,F(xiàn)在,我們只需要運行每個微服務(wù)的單個實例。您可以通過運行JUnit測試類 OrderControllerTest 來輕松地生成一些測試請求,這是在我的源代碼庫中提供的 order- service 中提供的。這種情況下很簡單。在下一篇文章中,我們將學(xué)習(xí)更高級的示例,其中包含多個正在運行的消費服務(wù)實例。擴展為了擴展我們的Spring Cloud Stream應(yīng)用程序,我

34、們只需要啟動每個微服務(wù)的附加實例。他們?nèi)匀粫陕犈c當(dāng)前正在運行的實例相同的 topic exchange 中的傳入消息。在添加了一個 account-service 和 product-service 的實例之后,我們可以發(fā)送一個測試訂單。這個測試的結(jié)果對我們來說是不令人滿意的 為什么?每個微服務(wù)運行的所有實例都接收到了這個訂單。這正是 topic exchanges 的工作方式發(fā)送到topic的消息被所有的消費者接收,他們正在偵聽這個topic。幸運的是,Spring Cloud Stream能夠通過提供稱為 consumer group的解決方案來解決這個問題。它負(fù)責(zé)保證一個消息只被一個實

35、例處理,如果它們被放置在一個相互競爭的消費者關(guān)系中。在運行多項服務(wù)實例時,對consumer group機制的轉(zhuǎn)換已經(jīng)在下圖中可視化了。一個 consumer group 機制的配置不是很困難。我們只需要設(shè)定 group 參數(shù),并給出給定destination的組名。下面是 account-service 的當(dāng)前binding配置。 orders-in destination地是一個為直接與 order- service 通信而創(chuàng)建的隊列,因此只有 orders-out 被分組使用 spring.cloud.stream.bindings.group 屬性。Consumer group機制是A

36、pache Kafka的一個概念,它也在Spring Cloud Stream中實現(xiàn),也適用于RabbitMQ broker,它本身并不支持它。因此,我認(rèn)為它在RabbitMQ上的配置非常有趣。如果您在destination運行兩個服務(wù)實例,而沒有在destination設(shè)置組名,那么就會有兩個為單個交易所創(chuàng)建的bindings(每個實例一個bindings),如下圖所示。因為有兩個應(yīng)用程序在這個exchange中監(jiān)聽,總共有四個binding分配給那個exchange。如果您為選定的destination Spring Cloud Stream設(shè)置組名,則將為給定服務(wù)的所有運行實例創(chuàng)建單一b

37、inding。binding的名稱將以組名為后綴。因為,我們已經(jīng)在項目依賴項中包含了 spring-cloud-starter-sleuth ,在實現(xiàn) order-service POST endpoint的單個請求時,在交換的所有異步請求之間發(fā)送相同的 traceId 頭部。由于這個原因,我們可以使用Elastic Stack (Kibana)輕松地將所有日志關(guān)聯(lián)起來。自動化測試您可以輕松地測試您的微服務(wù),而不需要連接到message broker。要實現(xiàn)它,您需要將 spring-cloud- stream-test-support 包含到您的項目依賴項中。它包含 TestSupportB

38、inder bean,它允許您與綁定通道進行交互,并檢查應(yīng)用程序發(fā)送和接收的任何消息。在測試類中,我們需要聲明 MessageCollector bean,它負(fù)責(zé)接收由 TestSupportBinder 保留的消息。這是我的 account-service 測試類。使用 Processor bean,我將測試訂單發(fā)送到輸入通道。然后, MessageCollector 接收到通過輸出通道發(fā)送回 order-service 的消息。測試方法的 testAccepted 創(chuàng)建了應(yīng)該被帳戶服務(wù)接受的順序,而 testRejected 方法則設(shè)置了過高的訂單價格,從而導(dǎo)致拒絕訂單。總結(jié)當(dāng)您不需要來自

39、API的同步響應(yīng)時,Message-driven的微服務(wù)是一個不錯的選擇。在本文中,我展示了 在您的微服務(wù)之間的跨服務(wù)通信中發(fā)布/訂閱模型的示例用例。源代碼在GitHub上是常見的(/helloworldtang/sample-message-driven-microservices.git【原文源碼maven不能運行,這個項目fork原代碼并修復(fù)了錯誤】)。對于使用Spring Cloud Stream庫、Apache Kafka的更有 趣 的 例 子 , 您 可 以 參 考 我 的 書 中 第 11 章 , Mastering Spring Cloud(https:/ HYPERLINK

40、/application-development/mastering-spring-cloud) /application-development/mastering-spring-cloud)。使用JDK11中String類的新方法在 HYPERLINK /2018/05/jdk-11-string-methods.html JDK11中String的新方法和 HYPERLINK /2018/02/string-repeat-coming-to-java.html java帶來了String的repeat方法兩篇文章中,我討論了 HYPERLINK /projects/jdk/11/ JDK

41、11中 HYPERLINK /javase/10/docs/api/java/lang/String.html java String的六個新方法。目前已經(jīng)可用的 HYPERLINK /11/ early access JDK 11 builds版本已經(jīng)包括了這些新的方法。 HYPERLINK /jdk/jdk/log?revcount=10000&rev=reverse(%22jdk-11%2B19%22%3A%3A%22jdk-11%2B20%22 在這篇文章中,我將要給大家演示如何使用這些新的方法。在下面的例子中,我使用了OpenJDK JDK 11 Early Access Build

42、 20)這個版本來編譯和運行代碼。在OpenJDK JDK 11 Early Access Build 20這個版本中新加入的六個方法分別是:String.repeat(int) String.lines() String.strip() String.stripLeading() String.stripTrailing() String.isBlank()這些示例的源碼已經(jīng)放在git上:示例源碼String.repeat(int)因為我之前在groovy中曾使用過這個方法提供的功能,因此String.repeat(int)方法終于提供了我一直想在java中看到的便捷功能。正如方法名字一樣,

43、這個方法會按照參數(shù)int提供的次數(shù)來重復(fù)字符串。我將會使用這個方法來生成更多的簡單的示例,并且也用這個方法來演示這篇文章中的例子。下面的代碼演示了通過String.repeat(int)方法來生成并輸出header separater。String.repeat(int)示例/*Write provided code String in header. Note that thisimplementation uses code String.repeat(int).*param headerText Title of header.*/private static void writeHea

44、der(final String headerText)final String headerSeparator = =.repeat(headerText.length()+4); out.println(n + headerSeparator);out.println(= + headerText + =); out.println(headerSeparator);writeHeader(String)方法使用String.repeat(int)就能很容易地通過=來生成header separater,從而能蓋住headerText的內(nèi)容。它額外添加了4個=,因為headerText前后

45、各加了一個=和一個空格。在這篇文章中,writeHeader(String)方法將會被用在其他示例中,同時也在其他示例中被用來展示其功能。String.lines()String.lines() 方法通過換行符把字符串分開,并返回一個字符串流,并且該字符串流也是根據(jù)換行符來分隔的。String.lines()示例/* Demonstrate method code String.lines() added with JDK 11.*/public static void demonstrateStringLines()final String originalString = prepareS

46、tringWithLineTerminators(); final String stringWithoutLineSeparators= originalString.replaceAll(n, n); writeHeader(String.lines() on + stringWithoutLineSeparators + ); final Stream strings = originalString.lines(); strings.forEach(out:println);上面的代碼輸出結(jié)果如下:String.strip()/String.stripLeading()/String.

47、stripTrailing()String.strip(), String.stripLeading()和String.stripTrailing()方法的作用是分別去掉了字符串頭和尾的空白符,字符串頭的空白符,字符串尾的空白符(空白符如Character.isWhiteSpace(int)方法結(jié)果驗證)。String.strip/String.stripLeading()/String.stripTrailing()示例/* Demonstrate method code String.strip() added with JDK 11.*/public static void demons

48、trateStringStrip()final String originalString = prepareStringSurroundedBySpaces(); writeHeader(String.strip() on + originalString + ); out.println( + originalString.strip() + );/* Demonstrate method code String.stripLeading() added with JDK 11.*/public static void demonstrateStringStripLeading()fina

49、l String originalString = prepareStringSurroundedBySpaces(); writeHeader(String.stripLeading() on + originalString + ); out.println( + originalString.stripLeading() + );/* Demonstrate method code String.stripTrailing() added with JDK 11.*/public static void demonstrateStringStripTrailing()final Stri

50、ng originalString = prepareStringSurroundedBySpaces(); writeHeader(String.stripTrailing() on + originalString + ); out.println( + originalString.stripTrailing() + );上面的代碼執(zhí)行結(jié)果如下所示:String.isBlank()String.isBlank()方法用來驗證當(dāng)前字符串是否是空的, 或者是否只包括空白字符(空白字符由Character.isWhiteSpace(int)來驗證)/* Demonstrate method c

51、ode String.isBlank() added with JDK 11.*/public static void demonstrateStringIsBlank()writeHeader(String.isBlank(); final String emptyString = ;out.println(Empty String - + emptyString.isBlank();final String onlyLineSeparator = System.getProperty(line.separator); out.println(Line Separator Only - +

52、onlyLineSeparator.isBlank(); final String tabOnly = t;out.println(Tab Only - + tabOnly.isBlank(); final String spacesOnly = ;out.println(Spaces Only - + spacesOnly.isBlank();代碼執(zhí)行結(jié)果如下所示:上面示例中有些方法沒有直接在代碼中展示,詳情可以查看GitHub上面的方法添加到JDK 11中是對String類的一些小補充,但是卻讓String一些展示性的功能更加容易,也減少了對第三方庫包的依賴。Spring Data Mon

53、goDB 簡介概述本文將對進行快速實用的 Spring Data MongoDB 介紹。我們將使用 MongoTemplate 和 MongoRepository 的基礎(chǔ)知識來實際測試說明每個操作。MongoTemplate 和 MongoRepositoryMongoTemplate 遵循 Spring 的標(biāo)準(zhǔn)模板模式,并提供一個到底層持久化引擎的準(zhǔn)備好的、基礎(chǔ)的API。repository 遵循 Spring 以數(shù)據(jù)為中心的理念,并基于所有 Spring Data 項目中眾所周知的訪問模式, 提供更靈活、更復(fù)雜的 API 操作。對于這兩者,我們需要首先定義依賴項舉個例子,在 pom.xml

54、 中,使用 Maven:org.springframework.dataspring-data-mongodb1.10.4.RELEASE要檢查是否有任何新版本的庫發(fā)布,請 HYPERLINK / l search%7Cgav%7C1%7Cg%3A%22org.springframework.data%22%20AND%20a%3A%22spring-data-mongodb%22 在此處追蹤版本。MongoTemplate 的配置XML 配置讓我們從 MongoTemplate 的簡單 XML 配置開始:首先,我們需要定義負(fù)責(zé)創(chuàng)建 Mongo 實例的工廠 bean。接下來,我們需要實際定義(

55、和配置)模板 bean:最后,我們需要定義翻譯任何被 Repository 注解的類中拋出的 MongoExceptions 的后置處理器:Java 配置現(xiàn)在讓我們使用 Java 通過繼承 MongoDB 配置的基類 AbstractMongoConfiguration 來創(chuàng)建一個類似的配置:Configurationpublic class MongoConfig extends AbstractMongoConfiguration Overrideprotected String getDatabaseName() return test;Overridepublic Mongo mong

56、o() throws Exception return new MongoClient(, 27017);Overrideprotected String getMappingBasePackage() return org.baeldung;注意:我們不需要在前面的配置中定義 MongoTemplate bean,因為它已經(jīng)在AbstractMongoConfiguration 中定義好了。我們也可以從零開始使用我們配置而不繼承 AbstractMongoConfiguration,如下所示:Configurationpublic class SimpleMongoConfig Beanpu

57、blic Mongo mongo() throws Exception return new MongoClient(localhost);Beanpublic MongoTemplate mongoTemplate() throws Exception return new MongoTemplate(mongo(), test);MongoRepository 的配置XML 配置要使用自定義 repositories(繼承自 MongoRepository),我們需要繼續(xù) 3.1 節(jié)的配置并設(shè)置存儲庫。Java 配置相同的,我們將在 3.2 節(jié)船艦的配置的基礎(chǔ)上在混合時添加一個新的注解:E

58、nableMongoRepositories(basePackages = org.baeldung.repository)創(chuàng)建 Repository現(xiàn)在,在配置之后,我們需要創(chuàng)建一個 repository,繼承現(xiàn)有的 MongoRepository 接口:public interface UserRepository extends MongoRepository /現(xiàn)在我們可以自動連接此 UserRepository 并使用 MongoRepository 中的操作或添加自定義操作。使用 MongoTemplateInsert讓我們從插入操作開始;我們也從一個空數(shù)據(jù)庫開始:現(xiàn)在,如果我們插

59、入一個新用戶:User user = new User(); user.setName(Jon); mongoTemplate.insert(user, user);數(shù)據(jù)庫將如下所示:_id : ObjectId(55b4fda5830b550a8c2ca25a), _class : org.baeldung.model.User,name : JonSave插入在 保存 操作有保存或更新語義:如果 ID 存在,它執(zhí)行更新,如果沒有,它將執(zhí)行插入。讓我們看第一種語義插入;這是數(shù)據(jù)庫的初始狀態(tài):我們現(xiàn)在保存新用戶時:User user = new User(); user.setName(Alb

60、ert); mongoTemplate.save(user, user);該實體將被保存進數(shù)據(jù)庫:_id : ObjectId(55b52bb7830b8c9b544b6ad5), _class : org.baeldung.model.User,name : Albert接下來,我們將查看相同的操作 save,使用其更新語義。Save更新現(xiàn)在讓我們查看使用更新語義的 save,對現(xiàn)有實體進行操作:_id : ObjectId(55b52bb7830b8c9b544b6ad5), _class : org.baeldung.model.User,name : Jack現(xiàn)在,當(dāng)我們 save 現(xiàn)

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論