您好,登錄后才能下訂單哦!
小編給大家分享一下spring-boot下滿足多生產環境中個性化定制功能的案例,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
在項目的開發中,我們很難做到開發一套標準的流程來解決所有客戶的需求。比如,我們當前的計量項目,分別運行于赤峰市和河北省。雖然兩個區域處理的業務相同,但是對細節的實現要求卻不同。前面也學習過計量檢定軟件,其為了解決各個定制者使用的功能需求,最后采取的方案是:將基礎項目復制多份,進而滿足不同的客戶需求。優點當然是有的,但比起缺點來,優點便不值一提。缺點很明顯,總結為一句話就是:項目變得難以維護。所以,當前讓我們看到的就是,幾個開發人員,每天處于解決問題當中。本文將給出一種方案,來有效的規避上述問題。
資源與環境
示例代碼:https://github.com/mengyunzhi/springBootSampleCode/tree/master/dynamic-autowire
開發環境:java1.8 + spring-boot:2.1.3.RELEASE
需求假設
假設使用本項目的人員為:中國人、美國人,分別能接受的語言為中文和英文。
項目運行后,可以根據當前的訪問人員是國籍來動態顯示:你好
或hello
有新的需求后,比如:增加德國人并顯示Hallo
。增加功能時,不更改核心代碼。
不使用if else
注意:如果你看完需求假設后,毫無觸動,請忽略本文以下內容
解決方案
解決方案中,我們涉及了兩種設計模塊,分別為:策略模式
及工廠模式
。
策略模式:一般用于將具體的算法
進行抽象及剝離。此項目中,我們的具體算法是說你好
。
工廠模式:一般用于根據環境來動態的創建BEAN的情況下。引項目中,我們將根據不同國家的人,來返回不同的說你好
這個算法。
先給出UML圖:
SpeakService
SpeakService
即為我們供其它模塊調用的說話服務
,調用其中的SayHello()
來完成說你好
功能。
package com.mengyunzhi.demo.dynamicautowire; /** * 你好 */ public interface SpeakService { void sayHello(); }
在其實現類中,我們注入SayHelloFactory
,讓其來返回正確的SayHelloService
,最終調用sayHello()
來完成目標。
package com.mengyunzhi.demo.dynamicautowire; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; /** * 你好 */ @Service public class SpeakServiceImpl implements SpeakService { private final SayHelloFactory sayHelloFactory; // 說話工廠 @Autowired public SpeakServiceImpl(SayHelloFactory sayHelloFactory) { this.sayHelloFactory = sayHelloFactory; } @Override public void sayHello() { this.sayHelloFactory.getSayHelloService().sayHello(); } }
SayHelloFactory
package com.mengyunzhi.demo.dynamicautowire; /** * 說話工廠 */ public interface SayHelloFactory { void setCountryCode(CountryCode countryCode); SayHelloService getSayHelloService(); }
在此,我們增加一個CountryCode
表示當前訪問者的國家。其實在獲取訪問者國家時,我們也可以調用其它Bean的其它來實現。
package com.mengyunzhi.demo.dynamicautowire; /** * 國家代碼 */ public enum CountryCode { CHINA((byte) 0, "中國"), USA((byte) 1, "美國"); private Byte code; private String name; CountryCode(Byte code, String name) { this.code = code; this.name = name; } public Byte getCode() { return code; } public String getName() { return name; } }
使用enum
來控制范圍,避免Factory
在獲取Bean時發生異常。
package com.mengyunzhi.demo.dynamicautowire; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.HashMap; import java.util.List; import java.util.Map; /** * 說話工廠 */ @Service public class SayHelloFactoryImpl implements SayHelloFactory { /** * BEAN列表 */ private final Map<Byte, SayHelloService> servicesByCode = new HashMap<>(); /** * 國家代碼 */ private CountryCode countryCode = CountryCode.CHINA; @Override public void setCountryCode(CountryCode countryCode) { this.countryCode = countryCode; } /** * 初始化 * * @param sayHelloServices spring獲取到的所以實現了SpeakService的BEAN */ @Autowired public void init(List<SayHelloService> sayHelloServices) { for (SayHelloService sayHelloService : sayHelloServices) { this.register(sayHelloService.getCode(), sayHelloService); } } /** * 注冊Bean * * @param code 代碼 * @param sayHelloService BEAN */ private void register(Byte code, SayHelloService sayHelloService) { this.servicesByCode.put(code, sayHelloService); } /** * 獲取BEAN * * @return 對應的SayHelloService BEAN */ @Override public SayHelloService getSayHelloService() { return this.servicesByCode.get(this.countryCode.getCode()); } }
增加Map<Byte, SayHelloService> servicesByCode
來存儲對應國家的SayHelloService
BEAN。增加getSayHelloService()
來根據當前國家代碼來返回相應的Bean。
SayHelloService
package com.mengyunzhi.demo.dynamicautowire; /** * 說話 */ public interface SayHelloService { void sayHello(); Byte getCode(); }
將sayHello()
方法抽離,getCode()
以獲取國家代碼。
中國人你好
package com.mengyunzhi.demo.dynamicautowire; import org.springframework.stereotype.Component; /** * 中國話 */ @Component public class SayHelloServiceChineseImpl implements SayHelloService { @Override public void sayHello() { System.out.println("您好"); } @Override public Byte getCode() { return CountryCode.CHINA.getCode(); } }
美國人Hello
package com.mengyunzhi.demo.dynamicautowire; import org.springframework.stereotype.Component; /** * 美國話 */ @Component public class SayHelloServiceEnglishImpl implements SayHelloService { @Override public void sayHello() { System.out.println("hello"); } @Override public Byte getCode() { return CountryCode.USA.getCode(); } }
測試
package com.mengyunzhi.demo.dynamicautowire; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @SpringBootTest @RunWith(SpringRunner.class) public class SpeakServiceImplTest { @Autowired SpeakService speakService; @Autowired SayHelloFactory sayHelloFactory; @Test public void sayHello() { // 默認說你好 speakService.sayHello(); // 將國家設置為美國,再說你好 sayHelloFactory.setCountryCode(CountryCode.USA); speakService.sayHello(); // 將國家設置為中國,再說你好 sayHelloFactory.setCountryCode(CountryCode.CHINA); speakService.sayHello(); } }
您好
hello
您好
時序圖
增加德國人
增加德國人SayHelloServiceGermanyImpl
.
在CountryCode
中,增加德國.
package com.mengyunzhi.demo.dynamicautowire; import org.springframework.stereotype.Component; @Component public class SayHelloServiceGermanyImpl implements SayHelloService { @Override public void sayHello() { System.out.println("Hallo"); } @Override public Byte getCode() { return CountryCode.GERMANY.getCode(); } }
package com.mengyunzhi.demo.dynamicautowire; /** * 國家代碼 */ public enum CountryCode { CHINA((byte) 0, "中國"), USA((byte) 1, "美國"), GERMANY((byte) 2, "德國"); private Byte code; private String name; CountryCode(Byte code, String name) { this.code = code; this.name = name; } public Byte getCode() { return code; } public String getName() { return name; } }
單元測試
@Test public void sayHello1() { // 默認說你好 speakService.sayHello(); // 將國家設置為美國,再說你好 sayHelloFactory.setCountryCode(CountryCode.USA); speakService.sayHello(); // 將國家設置為德國,再說你好 sayHelloFactory.setCountryCode(CountryCode.GERMANY); speakService.sayHello(); // 將國家設置為中國,再說你好 sayHelloFactory.setCountryCode(CountryCode.CHINA); speakService.sayHello(); }
測試結果如下:
您好
hello
Hallo
您好
在解決問題時,只所有我們看的不夠遠,可能是由于自己站的不夠高。同樣的問題,困惑我了多日,直到近期系統的學習設計模式
、angular官方教程
、Spring 實戰
后,結合近期項目變更帶來的新需求,才在使用設計模式解決此問題上有所啟發。
以上是“spring-boot下滿足多生產環境中個性化定制功能的案例”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。