ejb构建_如何使用单例EJB和MBean构建和清除参考数据缓存
ejb構(gòu)建
在我的一個(gè)項(xiàng)目中,我需要使用EclipseLink作為ORM框架從Java EE 6 WebLogic環(huán)境中的多個(gè)源中加載參考數(shù)據(jù)。 由于我在Java EE世界中找不到與Spring YET的@Cacheable相當(dāng)?shù)淖⑨?#xff0c;因此我不得不編寫自己的緩存解決方案。 盡管參考數(shù)據(jù)幾乎不會隨時(shí)間變化,但是一項(xiàng)額外的要求是能夠從外部清除緩存。 所以就這樣...
1.快取
原來這是一個(gè)只讀緩存,可以從外部刷新它。 我希望將緩存作為服務(wù)的一種包裝,為應(yīng)用程序提供實(shí)際的參考數(shù)據(jù)–帶代碼的AOP樣式!
接口
簡單的緩存界面,用于參考數(shù)據(jù)
@Local public interface ReferenceDataCache {/*** Returns all reference data required in the application */ReferenceData getReferenceData();/*** evict/flush all data from cache */void evictAll(); }緩存功能定義了兩種簡單的方法:
- getReferenceData() –緩存所有不同來源在后臺收集的參考數(shù)據(jù)
- evictAll() –調(diào)用方法以完全清除緩存
實(shí)作
使用@Singleton的簡單參考數(shù)據(jù)緩存實(shí)現(xiàn)
@ConcurrencyManagement(ConcurrencyManagementType.CONTAINER) @Singleton public class ReferenceDataCacheBean implements ReferenceDataCache {private static final String ALL_REFERENCE_DATA_KEY = "ALL_REFERENCE_DATA";private ConcurrentHashMap<String, Object> refDataCache = null;@EJBReferenceDataService referenceDataService;@PostConstructpublic void initialize(){this.refDataCache = new ConcurrentHashMap<>(); }@Override@Lock(LockType.READ)public ReferenceData getReferenceData() {if(refDataCache.containsKey(ALL_REFERENCE_DATA_KEY)){ return refDataCache.get(ALL_REFERENCE_DATA_KEY);} else {ReferenceData referenceData = referenceDataService.getReferenceData();refDataCache.put(ALL_REFERENCE_DATA_KEY, referenceData);return referenceData;} }@Overridepublic void evictAll() {refDataCache.clear(); } .......... }注意:
- @Singleton –可能是此類中最重要的代碼行。 此注釋指定在應(yīng)用程序中將僅存在一個(gè)這種類型的bean的單例。 該bean可以由多個(gè)線程同時(shí)調(diào)用。 它還帶有@PostConstruct批注。 此注釋用于需要依賴注入完成后才能執(zhí)行任何初始化的方法,在本例中是初始化“緩存”(哈希映射)
- @ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)聲明單例會話bean的并發(fā)管理類型。 默認(rèn)情況下,它設(shè)置為Container 。 我在這里使用它只是為了強(qiáng)調(diào)它的存在。 另一個(gè)選項(xiàng)ConcurrencyManagementType.BEAN指定Bean開發(fā)人員負(fù)責(zé)管理對Bean實(shí)例的并發(fā)訪問。
- 實(shí)際的“緩存”是ConcurrentHashMap ,它具有基于String的鍵并存儲Object 。 由于bean的單例性質(zhì),它被保留在內(nèi)存中
- 注入的ReferenceDataService是@Stateless @EJB ,它在后臺收集來自不同來源的參考數(shù)據(jù)
- getReferenceData()方法的實(shí)現(xiàn)非常簡單–它檢查ConcurrentHashMap是否具有將String鍵指定為常量“ ALL_REFERENCE_DATA ”的條目。 如果是這樣,它將從內(nèi)存中檢索,否則將由服務(wù)Bean加載。
- @Lock(LockType.READ)指定具有容器管理的并發(fā)性的單例bean的并發(fā)鎖定類型。 設(shè)置為LockType.READ ,它將強(qiáng)制執(zhí)行該方法以允許對其進(jìn)行完全并發(fā)訪問(假定未持有任何寫鎖)。 這正是我想要的,因?yàn)槲抑恍枰獔?zhí)行讀取操作。 另一個(gè)更保守的選項(xiàng)@Lock(LockType.WRITE)順便說一下是DEFAULT,它強(qiáng)制對bean實(shí)例的獨(dú)占訪問。 這應(yīng)該在高度并發(fā)的環(huán)境中使方法變慢。
- evictAll()方法,只是從哈希圖中刪除所有元素。
2.刷新緩存
這篇文章的第二部分將討論清除緩存的可能性。 由于緩存實(shí)現(xiàn)是一個(gè)企業(yè)Java Bean,因此我們可以從MBean或從Web服務(wù)中調(diào)用它。
MBean
如果您不熟悉Java管理擴(kuò)展(JMX), 這是一種Java技術(shù),它提供用于管理和監(jiān)視應(yīng)用程序,系統(tǒng)對象,設(shè)備(例如打印機(jī))和面向服務(wù)的網(wǎng)絡(luò)的工具。 這些資源由稱為MBeans(用于Managed Bean)的對象表示 ,我強(qiáng)烈建議您從本教程的路徑:Java管理擴(kuò)展(JMX)開始。
2.1.1。 接口
公開的方法僅允許通過JMX重置緩存:
CacheRest MBean
@MXBean public interface CacheResetMXBean {void resetReferenceDataCache(); }“ MXBean是一種MBean,僅引用一組預(yù)定義的數(shù)據(jù)類型。 這樣,您可以確保您的MBean可被任何客戶端(包括遠(yuǎn)程客戶端)使用,而無需客戶端有權(quán)訪問代表MBean類型的特定于模型的類。 MXBean提供了一種將相關(guān)值捆綁在一起的便捷方法,而無需將客戶端特別配置為處理捆綁?!?[4]
2.1.2。 實(shí)作
MBean的CacheReset實(shí)現(xiàn)
@Singleton @Startup public class CacheReset implements CacheResetMXBean {private MBeanServer platformMBeanServer;private ObjectName objectName = null;@EJBReferenceDataCache referenceDataCache;@PostConstructpublic void registerInJMX() {try {objectName = new ObjectName("org.codingpedia.simplecacheexample:type=CacheReset");platformMBeanServer = ManagementFactory.getPlatformMBeanServer();//unregister the mbean before registerting againSet<ObjectName> existing = platformMBeanServer.queryNames(objectName, null);if(existing.size() > 0){platformMBeanServer.unregisterMBean(objectName);}platformMBeanServer.registerMBean(this, objectName);} catch (Exception e) {throw new IllegalStateException("Problem during registration of Monitoring into JMX:" + e);}} @Overridepublic void resetReferenceDataCache() {referenceDataCache.evictAll();}}注意:
- 如前所述,該實(shí)現(xiàn)僅調(diào)用上一節(jié)中介紹的注入的單例bean的evictAll()方法
- 該bean也被定義為@Singleton
- @Startup批注導(dǎo)致在應(yīng)用程序啟動時(shí)由容器實(shí)例化Bean – 渴望初始化
- 我再次使用@PostConstruct功能。 在這里, 此 bean已在JMX中注冊,如果有的話,請檢查是否使用ObjectName將其刪除。
休息服務(wù)電話
我還內(nèi)置了通過調(diào)用REST資源清除緩存的可能性。 在(rest-context)/ reference-data / flush-cache上執(zhí)行HTTP POST時(shí)會發(fā)生這種情況:
在參考數(shù)據(jù)緩存上進(jìn)行剩余調(diào)用
@Path("/reference-data") public class ReferenceDataResource {@EJBReferenceDataCache referenceDataCache;@POST@Path("flush-cache")public Response flushReferenceDataCache() {referenceDataCache.evictAll();return Response.status(Status.OK).entity("Cache successfully flushed").build();} @GET@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })public Response getReferenceData(@QueryParam("version") String version) {ReferenceData referenceData = referenceDataCache.getReferenceData(); if(version!=null && version.equals(referenceData.getVersion())){return Response.status(Status.NOT_MODIFIED).entity("Reference data was not modified").build(); } else {return Response.status(Status.OK).entity(referenceData).build(); }} }注意@GET getReferenceData(...)方法中存在版本查詢參數(shù)。 這表示參考數(shù)據(jù)上的哈希,如果尚未修改,則客戶端將收到304未修改HTTP狀態(tài) 。 這是節(jié)省帶寬的好方法,尤其是在您擁有移動客戶端的情況下。 有關(guān)REST服務(wù)設(shè)計(jì)和實(shí)現(xiàn)的詳細(xì)討論,請參閱我的教程“使用Jersey和Spring的Java REST API設(shè)計(jì)和實(shí)現(xiàn)”。
注意:
在集群環(huán)境中,當(dāng)參考數(shù)據(jù)更改時(shí),需要在部署了應(yīng)用程序的每個(gè)JVM上調(diào)用resetCache(…)。
好,就是這樣。 在本文中,我們學(xué)習(xí)了如何使用Java EE批注構(gòu)建簡單的緩存。 當(dāng)然,您可以輕松擴(kuò)展緩存功能,以提供對緩存對象的更精細(xì)的訪問/清除。 在這種情況下,請不要忘記使用LockType.WRITE作為清除方法……
翻譯自: https://www.javacodegeeks.com/2014/09/how-to-build-and-clear-a-reference-data-cache-with-singleton-ejbs-and-mbeans.html
ejb構(gòu)建
總結(jié)
以上是生活随笔為你收集整理的ejb构建_如何使用单例EJB和MBean构建和清除参考数据缓存的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: HttpClient 4 API –获取
- 下一篇: SSL Kafka经纪人从Kafka M