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

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、1基于Spring的開發(fā)最佳實踐目 錄 HYPERLINK l _bookmark1 使用 Spring WebFlux、SpringData 和MongoDB 創(chuàng)建一個響應的 RESTful Web 服務 HYPERLINK l _bookmark2 Spring WebFlux和Spring Cloud進行反應式微服務開發(fā) HYPERLINK l _bookmark3 03. Spring-5-webflux和阻塞與非阻塞JDBC HYPERLINK l _bookmark4 Spring Webflux Kotlin DSL 片斷 HYPERLINK l _bookmark5 原始性能表

2、格 - Spring Boot 2 Webflux vs. Spring Boot 1 HYPERLINK l _bookmark6 06. Spring WebFlux:初探 HYPERLINK l _bookmark7 基于注解的控制器:Spring WebWebFlux 和 測試 HYPERLINK l _bookmark8 Spring WebFlux 編寫攔截器 HYPERLINK l _bookmark9 嘗試使用Spring WebFlux HYPERLINK l _bookmark10 利用OAuth2.0來構建一個基于Spring Boot的安全的端到端通信應用 HYPERL

3、INK l _bookmark11 微服務架構十條最佳實踐 HYPERLINK l _bookmark12 使用java10中的Hazelcast遷移hibernate的二級緩存 HYPERLINK l _bookmark13 13.本周的 Spring 新聞 -2018年6月19日 HYPERLINK l _bookmark14 14.Java程序員可以從Spring框架中學習的3個最佳實踐 HYPERLINK l _bookmark15 15.響應式Spring Cloud初探 HYPERLINK l _bookmark16 Spring Cloud Config(第一部分) HYPERL

4、INK l _bookmark17 微服務 - 第5部分:使用Spring Cloud Zuul Proxy來構建API網關18.Spring Cloud Config (第二部分) Git 后端 HYPERLINK l _bookmark18 19.使用 以太坊、web3j 和 Spring Boot 體驗區(qū)塊鏈 HYPERLINK l _bookmark19 20.17個最受歡迎的 Java 框架:優(yōu)點、缺點和更多(第一部分)1 PAGE 6使

5、用 Spring WebFlux、SpringData 和MongoDB 創(chuàng)建一個響應的 RESTful Web 服務了解如何在本教程中為 Spring WebFlux、Spring Data 和 MongoDB一步步創(chuàng)建一個響應式的 RESTful web 服務。這篇文章的基礎是從 Spring 框架開始 第四版。本文的源代碼可以在 ch19-tor3-webservice 項目中找到。( HYPERLINK http:/bit.ly/2zTuD0Y http:/bit.ly/2zTuD0Y) 要運行這個項目,可以在 Tomcat 9 上部署 ch19-reptor3-webservice

6、項目,并執(zhí)行 ReactiveWebClient 的主要方法(位于 src/test/java 文件夾中)。要創(chuàng)建一個響應的 RESTful web 服務,您需要確保 web 服務的每個層(數據訪問、服務和 web )在本質上都是響應的。使用 Spring Data 開發(fā)數據訪問層。對于 MongoDB 來說,可以使用動態(tài)數據庫驅動程序,可以使用 Spring Data (Kay release )來重新與MongoDB 數據庫交互。BankAccountReactorRepository (一個 Spring 數據存儲庫),它定義了返回響應類型的方法(由反應器定義):public inter

7、face BankAccountReactorRepository extends ReactiveMongoRepository, BankAccountReactorRepositoryCustom Mono countByBalance(int balance);Flux findByBalance(int balance);注意 從存儲庫方法返回反應類型( Flux 和 Mono ),也可以返回由 RxJava 2 定義的反應類型。MongoDB配置Spring Dataimport org.springframework.data.mongodb.ReactiveMongoDatab

8、aseFactory; import org.springframework.data.mongodb.core.ReactiveMongoTemplate;import org.springframework.data.mongodb.core.SimpleReactiveMongoDatabaseFactory;import org.springframework.data.mongodb.repository.config.EnableReactiveMongoRepositories;ConfigurationEnableReactiveMongoRepositories(basePa

9、ckages = sample.spring.chapter19.bankapp.repository) public class DatabaseConfig Beanpublic MongoClient mongoClient() throws UnknownHostException return MongoClients.create(mongodb:/localhost);public ReactiveMongoDatabaseFactory mongoDbFactory() . return new SimpleReactiveMongoDatabaseFactory(mongoC

10、lient(), test);Beanpublic ReactiveMongoTemplate reactiveMongoTemplate() . return new ReactiveMongoTemplate(mongoDbFactory();EnableReactiveMongoRepositories 注釋允許使用響應式 MongoDB 存儲庫。basepackage 屬性指定要掃描無反應 MongoDB 存儲庫的包。Bean 注解的 mongoDbFactory 方法創(chuàng)建并返回SimpleReactiveMongoDatabaseFactory 的一個實例。SimpleReactiv

11、eMongoDatabaseFactory 的構造函數接受 MongoClient 的實例和數據庫的名稱(在我們的例子中是測試)。Bean 注釋的 reactiveMongoTemplate 方法配置了一個Spring Data MongoDB的reactiveMongoTemplate 實例,該模板被存儲庫用于在 MongoDB 上執(zhí)行被動操作。開發(fā)服務層由于我們不希望服務層中的方法阻塞,所以服務方法返回響應的類型。下面的清單顯示了定義服務方法的 BankAccountService 接口:public interface BankAccountService Mono saveBankAc

12、count(BankAccountDetails bankAccountDetails); Flux findByBalance(int balance);Mono addFixedDeposit(String bankAccountId, int amount);以下清單顯示實現 BankAccountService 接口的 BankAccountServiceImpl 類:Servicepublic class BankAccountServiceImpl implements BankAccountService Autowiredprivate BankAccountReactorRe

13、pository bankAccountRepository;Overridepublic Mono countByBalance(int balance) return bankAccountRepository.countByBalance(balance);Overridepublic Flux findByBalance(int balance) return bankAccountRepository.findByBalance(balance);countByBalance 和 findByBalance 方法調用 BankAccountReactorRepository 中定義的

14、相應方法。使用Spring WebFlux 開發(fā)Web層Spring WebFlux 模塊(在 Spring 5中引入)支持開發(fā)響應式 web 應用程序和基于RESTful web 服務。就像 Spring Web MVC的情況一樣,您可以使用 Controller、GetMapping 等來編寫響應式的Web控制器。下面的清單顯示了 BankAccountController 類(一個響應式的web控制器),它調用 BankAccountService的方法:import reactor.core.publisher.Flux; import reactor.core.publisher.M

15、ono;RestController RequestMapping(/bankaccount) public class BankAccountController Autowiredprivate BankAccountService bankAccountService;GetMapping(/countByBalance/balance)public Mono countByBalance(PathVariable(balance) int balance) return bankAccountService.countByBalance(balance);GetMapping(/fin

16、dByBalance/balance)public Flux findByBalance(PathVariable(balance) int balance) return bankAccountService.findByBalance(balance);配置Spring WebFlux下面的清單展示了配置 WebFlux 的 WebConfig 類import org.springframework.web.reactive.config.EnableWebFlux;EnableWebFlux ConfigurationComponentScan(basePackages = sample

17、.spring.chapter19.bankapp.controller) public class WebConfig 在上面的清單中,EnableWebFlux 注解為項目配置 WebFlux 。ComponentScan 指定包含特定于web 層的類的包。作為控制器在sample.spring.chapter19.bankapp 中定義??刂破靼恢付镃omponentScan 注解的 basePackages 屬性的值。ServletContext 配置您可以通過使用Spring的AbstractAnnotationConfigDispatcherHandlerInitializ

18、er類以編程方式配置基于webflux的web應用程序(或RESTful web服務)的ServletContext,如下所示:importweb.reactive.support.AbstractAnnotationConfigDispatcherHandlerInitializer;public class BankAppInitializer extends AbstractAnnotationConfigDispatcherHandlerInitializer Overrideprotected Class getConfigClasses() return new Class Web

19、Config.class,DatabaseConfig.class, BankAccountServiceImpl.class ;getConfigClasses 方法返回我們想要在應用程序上下文中注冊的 Configuration(或Component)WebConfig.class 在web層注冊bean , DatabaseConfig.class 在數據訪問層中注冊bean。測試響應的RESTful Web 服務Spring的WebClient類(不像RestTemplate)允許您重新與一個響應式的RESTful web服務交互。下面的清單顯示了訪問BankAccountContro

20、ller定義的方法的ReactiveWebClient類:import org.springframework.web.reactive.function.BodyInserters; import org.springframework.web.reactive.function.client.WebClient;public class ReactiveWebClient private static Logger logger =LogManager.getLogger(ReactiveWebClient.class); private static WebClient webClien

21、t =WebClient.create(http:/localhost:8080/ ch19-reactor3-webservice/bankaccount);public static void main(String args) throws InterruptedException / -find BankAccountDetails entities with balance 1000 webClient.get().uri(/findByBalance/balance,1000).accept(MediaType.APPLICATION_JSON).retrieve().bodyTo

22、Flux(BankAccountDetails.class).subscribe(account - (account with balance 1000 - + account.getAccountId();WebClient的 create 方法創(chuàng)建了一個帶有基本URL、主機和端口信息的WebClient實例。在端口8080上本地部署了ch19- response -webservice, BankAccountController被映射到/bankaccount請求路徑,下面的URL被傳遞給創(chuàng)建方法http:/localhost:8080/ch19-tor3 -webservice/ba

23、nkaccount。retrieve 方法發(fā)送HTTP請求并檢索響應主體bodyToFlux方法將響應體提取到 Flux。當BankAccountController的findByBalance方法返回Flux類型時,調用bodyToFlux (BankAccountDetails.class)方法將響應主體轉換為Flux。 PAGE 59Spring WebFlux和Spring Cloud進行反應式微服務開發(fā)摘要:如果你想用Spring的最新和最好的工具開始使用反應式微服務,那么這篇文章就是為你準備的! 我已經在一年前的 HYPERLINK /2017/02/16/reactive-mic

24、roservices-with-spring-5/ Reactive microservices with Spring 5 這篇文章中描述了Spring對反應堆的支持。當時,Spring WebFlux項目一直處于積極的發(fā)展階段,現在,在Spring 5正式發(fā)布之后,它在這個版本是非常值得關注的。 此外,我們將嘗試把反應式微服務放入Spring Cloud組件中,其中包含諸如Eureka服務發(fā)現,使用Spring Cloud Commons LoadBalanced 進行負載均衡以及使用Spring Cloud Gateway(也基于WebFlux和Netty)的API網關等元素,。 我們還

25、將以Spring Data Reactive Mongo項目為例,介紹Spring對NoSQL數據庫的反應堆支持。 我們的體系結構示例圖如下,它包含兩個微服務,一個服務發(fā)現,一個網關和MongoDB數據庫。 源代碼 HYPERLINK /piomin/sample-spring-cloud-webflux.git sample-spring-cloud-webflux通常在GitHub上的一樣可用。接下來,我們進一步來描述創(chuàng)建上述系統的步驟。第1步:使用Spring WebFlux構建反應式應用程序為了在項目中使用庫Spring WebFlux,我們應該將 spring-boot-starte

26、r-webflux 添加到依賴關系中。 它包括一些依賴庫,如Reactor或Netty服務器。org.springframework.bootspring-boot-starter-webfluxREST控制器看起來與同步Web服務定義的控制器非常相似。 唯一的區(qū)別在于返回對象的類型。 如果我們返回單個對象,將使用Mono類的實例,如果我們返回的是多個對象,比如是一個列表,將返回一個Flux類的實例。 由于Spring Data Reactive Mongo,我們不需要做任何事情,只需調用相應接口上的所需方法即可。 實例代碼如下:RestControllerpublic class Accou

27、ntController private static final Logger LOGGER = LoggerFactory.getLogger(AccountController.class); Autowiredprivate AccountRepository repository; GetMapping(/customer/customer)public Flux findByCustomer(PathVariable(customer) String customerId) LOGGER.info(findByCustomer: customerId=, customerId);r

28、eturn repository.findByCustomerId(customerId);GetMappingpublic Flux findAll() LOGGER.info(findAll); return repository.findAll();GetMapping(/id)public Mono findById(PathVariable(id) String id) LOGGER.info(findById: id=, id);return repository.findById(id);PostMappingpublic Mono create(RequestBody Acco

29、unt account) LOGGER.info(create: , account);return repository.save(account);第2步:使用Spring Data Reactive Mongo將應用程序與數據庫集成應用程序和數據庫之間的集成實現也非常簡單。 首先,我們需要在項目依賴項中添加相關數據庫依賴 spring-boot-starter-data-mongodb-reactive 。org.springframework.bootspring-boot-starter-data-mongodb-reactive添加依賴過后,Mongo將自動支持響應式應用。 下一步

30、是使用ORM映射聲明一個實體。 以下類也作為AccountController的響應返回。Documentpublic class Account Idprivate String id; private String number; private String customerId; private int amount;.最后,我們可以創(chuàng)建一個擴展ReactiveCrudRepository的接口。 它遵循Spring Data JPA實現的模式,并提供了一些CRUD操作的基本方法。 它還允許我們自定義方法,這些名稱會自動映射到查詢。與標準Spring Data JPA庫相比唯一的區(qū)別在

31、于方法簽名。 這些對象將由Mono和Flux進行包裝。public interface AccountRepository extends ReactiveCrudRepository Flux findByCustomerId(String customerId);在這個例子中,我使用了Docker容器在本地運行MongoDB。 因為我使用Docker Toolkit在Windows上運行Docker,所以Docker機器的默認地址是00。 這是application.yml文件中數據源的配置。spring:data:mongodb:uri: mongodb:/00/test步驟3:使用Eu

32、reka啟用服務發(fā)現與 Spring Cloud Eureka 的集成非常類似于傳統的REST微服務。 要啟用發(fā)現客戶端功能,我們應該首先將啟動器 spring-cloud-starter-netflix-eureka-client 添加到項目依賴項中。org.springframework.cloudspring-cloud-starter-netflix-eureka-client然后我們必須使用 EnableDiscoveryClient 這個注解來啟用它的功能。SpringBootApplication EnableDiscoveryClientpublic class Account

33、Application public static void main(String args) SpringApplication.run(AccountApplication.class, args);微服務將自動在Eureka注冊中心進行注冊。 當然,我們可能會運行每個服務的多個實例。 以下是運行 account-service 實例和 customer-service 服務實例后的Eureka Dashboard 儀表板界面(http:/ localhost:8761)。 這里將不詳細講解使用嵌入式Eureka服務器運行應用程序的細節(jié)。 有關詳細信息,請參閱我之前的文章, HYPERL

34、INK /articles/quick-guide-to-microservices-with-spring-boot-20-e Spring Boot 2.0的微服務快速指南,Eureka和Spring Cloud。 Eureka服務器可作為 adiscovery-service 模塊使用。第4步:使用WebClient進行反應性微服務之間的服務間通信Spring WebFlux項目中的WebClient實現了一個服務間通信。 與RestTemplate相同,您應該使用Spring Cloud Commons LoadBalanced 對其進行注解。 它支持使用Netflix OSS Rib

35、bon客戶端與服務發(fā)現和負載均衡進行集成。 所以,第一步是使用 LoadBalanced 注解聲明一個客戶端構建器。Bean LoadBalancedpublic WebClient.Builder loadBalancedWebClientBuilder() return WebClient.builder();然后我們可以將WebClientBuilder注入到REST控制器中。 通過GET / id / with-accounts實現與 account-service 通信,首先我們使用一個基于響應式的Spring Data repository來搜索客戶實體。 它返回Mono對象,而W

36、ebClient返回Flux。 現在,我們的主要目的是將這些內容合并到訂閱者,并從Flux中返回一個包含帳戶列表的Mono對象。 下面的代碼片段說明了我如何使用WebClient與另一個微服務進行通信,然后將響應和結果合并到單個Mono對象。 這種合并可以用更“優(yōu)雅”的方式完成,所以你可以隨意創(chuàng)建一個推送請求。Autowiredprivate WebClient.Builder webClientBuilder; GetMapping(/id/with-accounts)public Mono findByIdWithAccounts(PathVariable(id) String id) L

37、OGGER.info(findByIdWithAccounts: id=, id);Flux accounts = webClientBuilder.build().get().uri( HYPERLINK http:/account-service/customer/ http:/account-service/customer/customer, id).re trieve().bodyToFlux(Account.class);return accounts.collectList().map(a - new Customer(a).mergeWith(repository.findBy

38、Id(id).collectList().map(CustomerMapper:map);第5步:使用Spring Cloud Gateway構建API網關Spring Cloud Gateway是最新的Spring Cloud項目之一。 它建立在Spring WebFlux的基礎之上,并且由于這一點,我們可以將它用作基于反應式微服務的入口。 與Spring WebFlux應用程序類似,它在嵌入式Netty服務器上運行。 要使用Spring Boot應用程序啟用它,只需在您的項目中包含以下依賴項。org.springframework.cloudspring-cloud-starter-gat

39、eway我們還應該啟用發(fā)現客戶端,以便網關能夠獲取已注冊的微服務列表。 但是,不需要在Eureka中注冊網關的應用程序。 要禁用注冊,可以在application.yml文件中將屬性 eureka.client.registerWithEureka 設置為 false 。SpringBootApplication EnableDiscoveryClientpublic class GatewayApplication public static void main(String args) SpringApplication.run(GatewayApplication.class, args

40、);默認情況下,Spring Cloud Gateway不支持與服務發(fā)現的集成。要啟用它,我們應該將屬性 spring.cloud.gateway.discovery.locator.enabled 設置為true。現在,應該完成的最后一件事情就是路由器的配置。 Spring Cloud Gateway提供了兩種可以在路由中配置的組件:filters(過濾器)和predicates(謂詞)。 Predicates用于將HTTP請求與路由進行匹配,而過濾器可用于在發(fā)送請求之前或之后修改請求和響應。這是網關的完整配置。它啟用服務發(fā)現位置,并根據服務注冊表中的條目定義兩種路由。我們使用Path Ro

41、ute Predicate工廠來匹配傳入的請求,并使用RewritePath GatewayFilter 工廠來修改請求的路徑,以使其匹配相應的服務格式(端點顯示在路徑/下,而網關將它們暴露在路徑下/account 和/customer下)。spring:cloud:gateway:discovery:locator:enabled: true routes:id: account-serviceuri: lb:/account-service predicates:Path=/account/* filters:RewritePath=/account/(?.*), /$pathid: cu

42、stomer-serviceuri: lb:/customer-service predicates:Path=/customer/* filters:RewritePath=/customer/(?.*), /$path第6步:測試樣本系統account-servicecustomer-在做一些測試之前,讓我們回顧一下我們的示例系統。 我們有兩個微服務 -,service - 使用MongoDB作為數據庫。 微服務customer-service調用account-service暴露的端點GET / customer / customer。 account-service的URL來自Eure

43、ka。 整個系統隱藏在網關后面,該網關位于localhost:8090的地址下。 現在,第一步是在Docker容器上運行MongoDB。 執(zhí)行以下命令后, Mongo在地址00:27017下可用。$ docker run -d -name mongo -p 27017:27017 mongo然后我們可以繼續(xù)運行 discovery-service 。 Eureka在其默認地址localhost:8761下可用。 您可以使用IDE運行它,或者執(zhí)行命令 java -jar target / discovery-service-1.0-SNAPHOT.jar 。 同樣的適用于我們的示例微服務。 但是

44、,account-service需要在兩個實例中進行通信,所以當使用-Dserver.port VM參數運行第二個實例時,您需要覆蓋默認的HTTP端口,例如 java -jar -Dserver.port = 2223 target /account- service-1.0-SNAPSHOT.jar 。 最后,在運行網關服務之后,我們可以添加一些測試數據。$ curl -header Content-Type: application/json -request POST -data firstName: John,lastName: Scott,age: 30 http:/localhos

45、t:8090/customerid: 5aec1debfa656c0b38b952b4,firstName: John,lastName: Scott,age: 30,accounts: null$ curl -header Content-Type: application/json -request POST -data number: 1234567890,amount: 5000,customerId: 5aec1debfa656c0b38b952b4 http:/localhost:8090/accountid: 5aec1e86fa656c11d4c655fb,number: 12

46、34567892,customerId: 5aec1debfa656c0b38b952b4,amoun t: 5000$ curl -header Content-Type: application/json -request POST -data number: 1234567891,amount: 12000,customerId: 5aec1debfa656c0b38b952b4 http:/localhost:8090/accountid: 5aec1e91fa656c11d4c655fc,number: 1234567892,customerId: 5aec1debfa656c0b3

47、8b952b4,amoun t: 12000$ curl -header Content-Type: application/json -request POST -data number: 1234567892,amount: 2000,customerId: 5aec1debfa656c0b38b952b4 http:/localhost:8090/accountid: 5aec1e99fa656c11d4c655fd,number: 1234567892,customerId: 5aec1debfa656c0b38b952b4,amoun t: 2000要測試服務間通信,只需在網關服務上

48、調用端點 GET / customer / id / with-accounts 。 它將請求轉發(fā)給customer-service,然后customer-service使用響應式WebClient調用由account-service 暴露的端點。結果如下所示。結論Spring 5和Spring Boot 2.0的出現,帶來了許多可用的方法來構建基于微服務的體系結構。我們可以使用與Spring Cloud Netflix項目的一對一通信,基于消息代理的消息傳遞微服務,以及與Spring Cloud Stream的發(fā)布/訂閱通信模型構建標準同步系統,最后使用Spring實現異步,反應式微服務We

49、bFlux。本文的主要目標是向您展示如何將Spring WebFlux與Spring Cloud項目一起使用,以便為構建在Spring Boot之上的響應式微服務提供服務發(fā)現,負載均衡或API網關等機制。在Spring 5之前,缺乏對響應式微服務的支持是Spring框架的缺點之一,但現在,Spring WebFlux已不再是這種情況。不僅如此,我們還可以利用Spring對最受歡迎的NoSQL數據庫(如MongoDB或Cassandra)的反應式支持,并輕松地將我們的反應式微服務與同步REST微服務一起放入一個系統中。Spring-5-webflux和阻塞與非阻塞JDBC期待良久的Spring5

50、提供了更多對反應式的支持,接下來我們來研究一下如何使JDBC更加異步,以及這么做帶來的問題 HYPERLINK https:/spring.io/blog/2017/05/08/spring-framework-5-0-goes-rc1 Spring Framework 5 為函數式響應型編程帶來了巨大的進步,你不需要使用ApplicationContext或幾十個注釋來啟動和運行最簡單的REST API。Spring 5將提供輕量級Web功能和被動的Web Flux支持,以幫助實現這種轉換。這些新特性使得Java和spring 5 更適合構建反應式的web 應用。為了實現反應式web應用,根

51、據反應式聲明 (The Reactive Manifesto)所說,應用必須是響應式,彈性的,可伸縮的,并且是消息驅動的。該列表中的最后一個條件消息驅動,導致了異步通信方式的大遷移,包括異步RPC和消息傳遞庫、數據庫驅動程序等等。關系型數據庫(RDBMS)是非常強大和有用的。數據庫供應商提供的JVM數據庫訪問的官方工具是實現JDBC API的驅動程序。但是JDBC被設計成阻塞并且每次數據庫的調用都是使用線程的。你無法在API本身的方法或接口中找到能在另一個線程中獲得查詢結果的接口。 還有 HYPERLINK https:/spring.io/blog/2017/02/23/spring-fra

52、mework-5-0-m5-update l comment-3174616521 一種觀點認為,事物型數據庫不適合反應性概念:事務的概念并不適用于反應性的世界,因為它是關于阻塞資源的,而這正是你想要避免的。我部分同意這種觀點。然而,這取決于你如何正確使用關系數據庫。此外,在高度可伸縮的SQL數據庫的新時代(如Amazon的Aurora或谷歌的Cloud Spanner),通過將它們一起使用來實現高吞吐量是合適的。問題是,當我們在一個SQL數據庫上構建反應式應用程序時,我們應該做什么? 一種選擇是使用完全非阻塞的替代SQL客戶機。比如這里和 HYPERLINK /finagle/roc 這里。

53、 當然,這些驅動程序還沒有得到數據庫廠商的官方支持。此外,與成熟的基于jdbc的抽象(如Hibernate或jOOQ)相比,功能的吸引力要小得多。另一種想法是我從Scala中找到的。我們可以將阻塞調用分發(fā)到一個單獨的線程池,以避免將阻塞和非阻塞調用混合在一起。這么做允許我們控制線程的總數量,并允許CPU在主執(zhí)行上下文中提供非阻塞任務,并應用各種優(yōu)化。 假設我們有一個基于jdbc的實現,比如Spring Data JPA,它確實是阻塞的。import org.springframework.data.repository.CrudRepository;public interface Addre

54、ssRepository extends CrudRepository 我們可以讓它異步執(zhí)行,并分發(fā)給專用的線程池。Servicepublic class AddressService private final AddressRepository repository; private final Scheduler scheduler;public AddressRouter(AddressRepository repository, Qualifier(jdbcScheduler) Scheduler scheduler)this.repository = repository;this

55、.scheduler = scheduler;public MonoIterable findAll() return async() - repository.findAll();private Mono async(Callable callable) return Mono.fromCallable(callable).publishOn(scheduler);我們的JDBC調度程序應該使用一個專用的線程池來配置,它的大小等于連接的數量。Configurationpublic class SchedulerConfiguration private final Integer conne

56、ctionPoolSize;public SchedulerConfiguration(Value($spring.datasource.maximum-pool-size) Integer connectionPoo lSize) this.connectionPoolSize = connectionPoolSize;Beanpublic Scheduler jdbcScheduler() return Schedulers.fromExecutor(Executors.newFixedThreadPool(connectionPoolSize);然而,這種方法也有困難。主要是事務管理。在

57、JDBC中,事務只能在一個java.sql.Connection中進行。要想在一個事務中進行多個操作,它們必須共享一個連接。如果想在兩者之間進行一些運算,則必須讓它們保持聯系。這么做的話效率不是很高,因為在他們運算的過程中保持了相對數量的閑置連接。異步JDBC包裝器的概念并不新鮮,并且已經在Scala HYPERLINK / Slick 3庫中實現了。最后,非阻塞JDBC可能會出現在Java路線圖上。正如它在2016年9月在JavaOne上宣布的 HYPERLINK /r/programming/comments/54janm/nonblocking_jdbc_api_slides_from_

58、talk_at_javaone/ 那樣,我們可能會在Java 10中看到它。Spring Webflux: Kotlin DSL 片斷如果您還沒有玩轉Spring Webflux,那么可以使用基于kotlin的DSL開發(fā)一個函數式API。Spring Webflux最近 HYPERLINK https:/spring.io/blog/2017/01/04/introducing-kotlin-support-in-spring-framework-5-0 介紹一個特性來定義函數式API,它使用一個非常直觀的基于 HYPERLINK / Kotlin的 HYPERLINK /docs/refer

59、ence/type-safe-builders.html DSL。這篇文章將簡單地展示一組具有鮮明對比的定義API的方式,一個是基于java流暢的API,一個是基于Kotlin的DSL。在Java中,使用函數式編程風格來定義一組CRUD的Spring Webflux API,代碼通常是這樣的:RouterFunction apis() return nest(path(/hotels), nest(accept(MediaType.APPLICATION_JSON), route(GET(/), messageHandler:getMessages).andRoute(POST(/), mes

60、sageHandler:addMessage).andRoute(GET(/id), messageHandler:getMessage).andRoute(PUT(/id), messageHandler:updateMessage).andRoute(DELETE(/id), messageHandler:deleteMessage);這些API的細節(jié)非常清楚,并且以一種流暢的方式定義,只有幾個關鍵字route、nest和HTTP行為。這些API也可以使用基于kotlin的DSL(以及一些巧妙地使用Kotlin擴展函數),用下面的方式來實現:Beanfun apis() = router

溫馨提示

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

評論

0/150

提交評論