javascript
Spring Boot 2中的功能切换
無論您是否喜歡,軟件開發都是一項協作活動。 整合工作一直被妖魔化,并被視為必不可少的邪惡。 有幾種方法可以解決有效集成的挑戰。 功能切換開關屬于該組。 在本文中,您將在實踐中看到如何在Spring Boot應用程序中使用功能切換(也稱為功能標志)。
1.什么是功能切換?
簡而言之, 功能切換是允許根據其當前值在應用程序中執行替代路徑的變量。 通過保持不同的執行方案,您可以在不更改代碼的情況下修改應用程序的行為。
根據您的需求,可以在啟動應用程序之前設置切換開關的值,也可以在運行時對其進行調整。 在后一種情況下,值的更改可以保留或僅影響應用程序的當前執行。
通常,您會讀到有關功能標志的信息, 以作為功能源代碼分支的替代方法 ,但是,實際上,兩種技術可以一起使用。 例如,您可以使用功能分支在應用程序中開發新的用戶故事,同時可以使用功能切換來控制對不同環境(例如,具有不同要求的客戶端)上功能的訪問。
盡管有許多用途,功能切換也有其缺點。 最大的問題是復雜性 。 如果沒有適當的策略,他們可能會Swift失控,成為維護的噩夢。 幸運的是,如果您遵循幾種良好的做法并圍繞features來組織應用程序 ,則使用Feature標志應該更加簡單。
2.使用功能切換選擇豆
在Spring Boot應用程序中使用功能切換的最常見情況是基于功能切換的當前值激活某些接口的不同實現。 我們來看一個示例來說明所描述的情況。
2.1依賴抽象
假設您有一個Web端點,該端點返回從數據庫存儲庫中獲取的產品列表。 您的目標是創建一個功能切換,該功能切換允許將存儲庫實現切換為使用Web服務作為數據源的實現。
如果要允許要素切換的類直接在其他類中使用,則您要做的第一件事是使用接口抽象依賴關系。
下面的代碼片段提供了一個示例Product REST端點,該端點依賴于ProductRepository接口。
@RestController @RequestMapping("/products") class ProductController {private final ProductRepository productRepository;ProductController(ProductRepository productRepository) {this.productRepository = productRepository;}@GetMappingCollection<Product> getAll() {return productRepository.findAll();}}目前,我們只有一個接口實現。 不久,我們將添加另一個,您將通過功能切換激活它。
@Repository class DbProductRepository implements ProductRepository {//... }2.2 application.properties中的功能切換
由于application.properties文件用于配置Spring Boot應用程序,因此是放置功能切換標志的好地方。
feature.toggles.productsFromWebService=true在提交代碼之前,將標志設置為false。 這樣,默認情況下,您的隊友將禁用新功能。 如果有人要激活該功能,則他們可以在本地開發環境中將標志值更改為true。
2.3有條件的Bean創建
下一步是創建要通過功能切換激活的接口的替代實現。 為了根據創建的屬性的值實例化bean,可以使用Spring Boot注釋@ConditionalOnProperty 。 設置切換屬性的名稱和應激活它的值。 該值應與放在application.properties文件中的值相同。
@Repository @ConditionalOnProperty(name = "feature.toggles.productsFromWebService",havingValue = "true" ) class WebServiceProductRepository implements ProductRepository {//... }在啟動應用程序之前,必須禁用數據庫存儲庫,否則,您將獲得有關接口的多個活動實現的異常。 返回第一個實現并應用以下更改:
@Repository @ConditionalOnProperty(name = "feature.toggles.productsFromWebService",havingValue = "false",matchIfMissing = true ) class DbProductRepository implements ProductRepository {我們使用與以前相同的功能切換名稱,只是其值已更改。 設置matchIfMissing屬性是可選的。 這樣,如果您從application.properties文件中刪除功能切換,即使缺少該值,也將創建該bean。
3.如何通過功能切換禁用控制器
您可以應用相同的策略有條件地激活整個Spring Web控制器。 您不需要創建其他接口,因為您只想通過功能切換控制一個實現。
@RestController @RequestMapping("/coupons") @ConditionalOnProperty(name = "feature.toggles.coupons", havingValue = "true") class CouponController {//... }application.properties應該包含以下行。
feature.toggles.coupons=true當您不將值設置為true時,Spring不會實例化控制器。 客戶端將僅收到404 HTTP狀態代碼。
不幸的是, @ ConditionalOnProperty批注不能在單個@RequestMapping方法上使用。 解決方法是,可以將所需的映射移動到單獨的控制器Bean。 或者,可以簡單地插入功能切換的值并在映射方法的主體中創建if語句。 但是,您應謹慎使用此解決方案。 如果您有興趣,為什么在下一段中找到答案。
private final boolean couponsToggled;CouponController(@Value("${feature.toggles.coupons}") boolean couponsToggled) {this.couponsToggled = couponsToggled; }@GetMapping List<String> listCouponNames() {if (!couponsToggled) {throw new NotSupportedException();}//... }4.多功能切換管理
正如您可以閱讀Martin Fowler的bliki上的功能切換一樣 , 功能標志傾向于在整個代碼庫中擴展,并且很快就會變得難以管理 。 即使您的應用程序中只有幾個功能切換,最好還是從使用標記的決策點抽象出標記的存儲。
4.1避免特征標記耦合
上一段中的最后一個代碼示例使用直接從application.properties文件注入的標志值,因此不會抽象存儲。 如果要在應用程序的不同部分中使用相同的標志,則必須重復注入。
相反,您可以做的是將所有功能切換值放在一個類中,這將作為單個true來源 。 使用單獨的類可為您提供更大的靈活性。 例如,您可以用數據庫替換標志的存儲,或者實現一種允許在運行時切換標志的機制。
4.2在Spring Boot中提取功能切換決策
一旦具有用于功能切換的單獨的bean,就可以使用@ConfigurationProperties批注輕松地從application.properties文件中注入所有標志。 在這里,您可以看到一個示例實現:
@Component @Component @ConfigurationProperties("feature") public class FeatureDecisions {private Map<String, Boolean> toggles = new HashMap<>();public Map<String, Boolean> getToggles() {return toggles;}public boolean couponEnabled() {return toggles.getOrDefault("coupons", false);}}上面的類將獲取所有以feature.toggles開頭的屬性,并將它們放入切換圖。 如您所見,有一個名為couponEnabled()的方法,可用于從決策背后的邏輯中提取功能決策點。
此外,您還需要一個額外的依賴項才能啟用對@ConfigurationProperties的處理。
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId> </dependency>5.用于功能切換的執行器端點
由于您已經將所有功能切換都放在一個位置,因此現在要做的就是使用自定義的Actuator端點公開列表。 以下示例將向您展示如何進行。
@Component @Endpoint(id = "feature-toggles") class FeatureToggleInfoEndpoint {private final FeatureDecisions featureDecisions;FeatureToggleInfoEndpoint(FeatureDecisions featureDecisions) {this.featureDecisions = featureDecisions;}@ReadOperationpublic Map<String, Boolean> featureToggles() {return featureDecisions.getToggles();}}如果您使用默認的Spring Boot 2 Actuator設置,則不會通過HTTP公開端點 。 為了在瀏覽器中對其進行測試,您必須通過將其標識符添加到application.properties文件中的Web include過濾器來啟用Actuator端點。
management.endpoints.web.exposure.include=health,info,feature-toggles運行應用程序后,請轉到http:// localhost:8080 / actuator / feature-toggles查看端點返回的結果:
根據您的需求,您還可以在創建的端點上使用@WriteOperation實現在運行時切換功能切換的可能性。 本示例僅涵蓋輸出部分。
結論
在本文中,您可以了解Spring Boot應用程序中功能切換的實際示例。 我們從一個非常基本的示例開始,該示例涵蓋了框架的所有需求。 之后,我們編寫一些自定義代碼來完成更多的自定義功能切換要求。 我們完成了有用的Actuator端點,以顯示應用程序中所有功能標志的狀態。
您可以在Github存儲庫中找到工作示例應用程序 。 如果您喜歡該帖子并認為它有用,請與您的關注者分享。 我也期待您在本文下面的問題和評論。
翻譯自: https://www.javacodegeeks.com/2018/03/feature-toggle-in-spring-boot-2.html
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的Spring Boot 2中的功能切换的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 不只有“鸡血版”骁龙8 Gen3!三星G
- 下一篇: 华为 WATCH GT 4 手表上架预约