İlkbaharda EhCache Ek Açıklamalarıyla Önbelleğe Alma
Yayınlanan: 2022-03-11EhCache, Spring ve Hibernate gibi en popüler Java çerçeveleriyle kolayca entegre edilebilen, yaygın olarak kullanılan, saf bir Java önbelleğidir. Projelere kolayca entegre edilebildiği için genellikle Java uygulamaları için en uygun seçim olarak kabul edilir. Özellikle:
- JAR'ı projenize dahil ederek kurulabilir. Ek kurulum adımları gerekmez.
- Uygulama ile aynı süreçte çalışır, bu nedenle hızlıdır. Çalıştırmak için ek bir hizmet gerekmez.
Kısacası, EhCache herhangi bir saf Java uygulaması için mükemmel bir seçimdir.
Ek olarak, EhCache Spring Annotations, yöntem uygulamalarını değiştirmeden önbelleğe alınabilir yöntemlere ek açıklamalar ekleyerek herhangi bir Spring uygulamasına sorunsuz entegrasyon sağlar.
EhCache, önbelleği programlı olarak işlemek için doğrudan, zengin API'ler sağlarken, bu makale esas olarak Spring uygulamalarınızı EhCache Spring Annotations ile daha az müdahaleci bir şekilde güçlendirmeye odaklanmaktadır. Bir Spring MVC projesi oluşturacağız ve Tomcat'te RESTful bir web servisi kuracağız. Ardından, EhCache web servisine entegre edilecektir.
Projeye Genel Bakış
Örnek bir proje bağlamında EhCache Ek Açıklamalarını göstereceğiz. Bir Tomcat 8 sunucusunda barındırılan Spring MVC tabanlı bir web hizmeti kuracağız.
Buradaki yönergeleri izleyerek kurulabilen projeyi Eclipse'de geliştirdim.
Tomcat'in en son kararlı sürümü Tomcat 8 buradan indirilebilir.
Tabii ki, bu belirli platformlar EhCache için bir gereklilik değildir; her zaman favori IDE ve sunucunuzu seçebilirsiniz.
EhCache Spring Annotations JAR burada mevcuttur. Gördüğümüz gibi, her sürüm için iki JAR vardır: biri bağımlılıkları olan ve diğeri olmayan. Bağımlılıkları olan, EhCache ek açıklamalarının çalışması için gerekli olan EhCache 2 ve Spring 3'ü de içerir. Bağımlılık içereni indirip derleme yolumuza eklersek kurulumu daha kolay olur.
EhCache Spring Annotations, ayrıca yapılandırılması gerekse de Spring 4 ile de uyumludur. Projenin yakın gelecekte EhCache 3'ü destekleyip desteklemeyeceği belli değil. EhCache 3'ü kullanan veya kullanmayı planlayanlar için bu makalede ele alınan açıklama yaklaşımı önerilmez.
Son olarak, her şeyi yönetmek için Maven'i kullanacağız. Maven, çoğu Eclipse kurulumuyla önceden paketlenmiş olarak gelir, ancak buradan da edinilebilir. Spring MVC ve EhCache Spring Annotations bağımlılıkları, bu makalenin ilerleyen bölümlerinde gösterildiği gibi, oldukça kolay bir şekilde eklenebilir.
Proje Kurulumu
Daha önce hiç Bahar projesi kurmadıysanız, Stefan Varga'nın konuyla ilgili yazısını da bilgilendirici bulabilirsiniz.
Bu gösteri için Maven arketipini maven-archetype-webapp kullanarak temel bir proje oluşturacağız. Genel dosya yapısı şöyle görünecektir:
src/main/java adında üç paket içeren bir dizin oluşturun: com.toptal.blog , com.toptal.blog.cache ve com.toptal.blog.service . Uygulama kaynağımız, aşağıda açıklandığı gibi bu paketlere girecektir.
web.xml içerisinde “springrest” adında bir Tomcat servlet tanımlayalım:
<web-app> ... <servlet> <servlet-name>springrest</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springrest</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> </web-app> Aksi açıkça belirtilmedikçe, Spring MVC DispatcherServlet , WEB-INF dizininde {servlet-name}-servlet.xml adlı bir XML yapılandırma dosyası arayacaktır. springrest-servlet.xml adında bir konfigürasyon dosyası oluşturalım. @RequestMapping ile açıklamalı Spring işlem denetleyicisi yöntemlerini etkinleştirmek için, bu dosyaya basitçe <mvc:annotation-driven /> ekleyelim. Ayrıca, <context:component-scan base-package="com.toptal.blog" /> ekleyerek Spring'in fasulyeleri otomatik olarak taraması ve kaydetmesi için temel paketi tanımlayalım. springrest-servlet.xml yapılandırması şu şekilde olur:
<beans ... > <mvc:annotation-driven /> <context:component-scan base-package="com.toptal.blog" /> </beans>Basit Bir RESTful Web Hizmeti
Artık projemiz düzgün bir şekilde yapılandırıldığına göre, basit bir “mesaj hizmeti” API'sini uygulayalım. Temel paketimiz project.toptal.blog , bir iletiyi kimliğe göre almak için bir GET yöntemi ve kimliğe göre bir ileti ayarlamak için bir POST yöntemiyle SpringRestControllerWithEhCache.java ekleyeceğiz:
@RestController @RequestMapping( "/" ) public class SpringRestControllerWithEhCache { @Autowired MessageService messageService; @RequestMapping( value = "/message/{id}", method = RequestMethod.GET ) public String getMessage( @PathVariable Integer id ) { String message = messageService.getMessage( id ); System.out.println( "get message ["+message+"] at "+new Date() ); return message; } @RequestMapping( value = "/message/set/{id}/{message}", method = RequestMethod.POST ) public String setMessage( @PathVariable Integer id, @PathVariable String message ) { System.out.println( "set message ["+message+"] at "+new Date() ); messageService.setMessage( id, message ); return message; } } MessageService sınıfını com.toptal.blog.service içinde tanımlayacağız. Kayıt Sistemimizde (SOR) saklanan mesajlara erişecektir. Bir üretim uygulamasında SOR, ilişkisel bir veritabanı gibi bir şey olacaktır. Basit olması için bir HashMap kullanacağız:
@Service public class MessageService { private ConcurrentHashMap<Integer, String> messages = new ConcurrentHashMap<Integer, String>(); public String getMessage( Integer id ) { System.out.println( "Getting data from SOR......" ); return messages.get( id ); } public void setMessage( Integer id, String message ){ messages.put( id, message ); } } Şimdi, projeyi bir WAR olarak dışa aktarırsak ve Tomcat'te dağıtırsak, http://localhost:8080/EhCacheExample/message/set/1/test_message bir HTTP POST isteği oluşturarak ID=1 için örneğin “test_message” gibi bir mesaj ayarlayabilmemiz gerekir. http://localhost:8080/EhCacheExample/message/set/1/test_message . Daha sonra http://localhost:8080/EhCacheExample/message/1 bir HTTP GET isteği ile “test_message”ı geri alabilmemiz gerekir. Testimi yapmak için Insomnia'yı uygun bir REST İstemcisi olarak kullandım.
EhCache Yay Açıklamalarını Takın
Şimdi EhCache'in bizim için çalışmasını sağlayalım. Projemizi EhCache'i düzgün çalıştıracak şekilde yapılandırmak yalnızca birkaç hızlı adım alır.
Adım 1: EhCache Yay Açıklamalarını kullanmak için Bağımlılıkları Güncelleyin
Maven'in pom.xml dosyasına EhCache Spring Annotations bağımlılığını ekleyin:
<!-- ehcache --> <dependency> <groupId>com.googlecode.ehcache-spring-annotations</groupId> <artifactId>ehcache-spring-annotations</artifactId> <version>1.2.0</version> </dependency>2. Adım: Özel Bir Önbellek Yöneticisi Kurun
Spring'in yerleşik bir EhCache önbellek yöneticisi vardır, org.springframework.cache.ehcache.EhCacheManagerFactoryBean . Bu, çoğu önbelleğe alma durumu için uygundur, ancak özel bir önbellek yöneticisi tanımlamayı yararlı buldum, çünkü önbelleği aynı önbellek yöneticisini kullanarak programlı olarak veya ek açıklamalarla kontrol etmeme izin veriyor. Bu makale ek açıklamalara odaklanıyor, ancak devam edelim ve ihtiyaç duymamız durumunda hazır olmamız için özel bir önbellek yöneticisi tanımlayalım. Varsayılan önbellek yöneticisine bağlı kalmayı tercih ederseniz, bu adımı atlayabilirsiniz.

Yeni sınıfı com.toptal.blog.cache.CustomCacheManager içinde tanımlayacağız:
public class CustomCacheManager extends net.sf.ehcache.CacheManager{ public CustomCacheManager(){ super(); } /* Add your own cache methods here. * * public void myCustomCacheMethod(){ * // your code here * } * */ } springrest-servlet.xml aşağıdaki gibi güncelleyerek etkinleştirin:
... <ehcache:annotation-driven cache-manager="customCacheManager" /> <bean class="com.toptal.blog.cache.CustomCacheManager" scope="singleton"></bean> ...3. Adım: EhCache'i Yapılandırın
Son olarak, sınıf yolunda EhCache yapılandırma dosyası ehcache.xml oluşturun. Eclipse varsayılan olarak sınıf yoluna src/main/resources ekler ve dosyayı buraya yerleştiririz. Bu dosya, EhCache'in düzgün çalışması için gereklidir. Önbellek adlarını ve timeToLiveSeconds gibi her önbelleğin bazı özelliklerini tanımlar:
<ehcache xmlms:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="ehcache.xsd"> <diskStore path="cache" /> <cache name="messageCache" maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="0" timeToLiveSeconds="10" overflowToDisk="false" memoryStoreEvictionPolicy="LFU" /> </ehcache>4. Adım: Önbelleği Test Edin
Şimdi, her şey hazır ve kullanıma hazırken, EhCache'i kullanmak kolay ve mutlu bir iş olmalı. Önbelleğe almak istediğimiz yönteme veya sınıfa basitçe @Cacheable ekleyebiliriz. Örneğin, MessageService içindeki getMessage yöntemine @Cacheable ekledim. Bu kadar kolay!
@Cacheable( cacheName = "messageCache" ) public String getMessage( Integer id ) { System.out.println( "Getting data from SOR......" ); return messages.get( id ); } Önbelleğimizin çalıştığını test etmek için http://localhost:8080/EhCacheExample/message/set/1/newMessage bir HTTP POST isteği göndererek ID=1 için bir mesaj oluşturabilir ve ardından ID= için mesajı alabiliriz. 1, http://localhost:8080/EhCacheExample/message/1 için GET istekleriyle birden çok kez. Aşağıdaki konsol çıktısında görebileceğiniz gibi, web hizmeti, mesajı ilk talep ettiğimizde SOR'dan mesajı almasını ister, ancak sonraki iki istek için değil, bunun yerine önbelleğe alınmış mesajı döndürür. timeToLiveSeconds 10 olarak tanımladığımız için, web hizmeti mesajı 10 saniye sonra tekrar almak için SOR'u arar:
set message [newMessage] at Sun Dec 06 23:55:39 MST 2015 get message [newMessage] at Sun Dec 06 23:55:42 MST 2015 Getting data from SOR...... get message [newMessage] at Sun Dec 06 23:55:47 MST 2015 get message [newMessage] at Sun Dec 06 23:55:49 MST 2015 get message [newMessage] at Sun Dec 06 23:55:54 MST 2015 Getting data from SOR......Önbelleği Yenileme
Şimdi önbelleğin bize sağladığı hız ve rahatlığın tadını çıkarıyoruz ve EhCache her 10 saniyede bir kendini yenileyecek kadar güzel. Peki ya SOR'umuz güncellendikten hemen sonra yenilenmesini istersek? EhCache Spring Annotation, açıklamalı yöntem çağrıldığında belirtilen anahtarları önbellekten kaldırmak için @TriggersRemove özelliğini sunar. Mesaj servis API'mizde, setMessage çağrıldığında önbelleğe alınan mesaj önbellekten kaldırılmalıdır. Böylece, bir daha getMessage isteği geldiğinde, önbellek SOR'dan yeni bir kayıt alır:
@Cacheable( cacheName = "messageCache", keyGenerator = @KeyGenerator ( // method name is not included in cache key to work with @TriggersRemove name = "HashCodeCacheKeyGenerator", properties = @Property( name="includeMethod", value="false" ))) public String getMessage( Integer id ) { System.out.println( "Getting data from SOR......" ); return messages.get( id ); } @TriggersRemove( cacheName = "messageCache", keyGenerator = @KeyGenerator ( name = "HashCodeCacheKeyGenerator", properties = @Property( name="includeMethod", value="false" ))) public void setMessage( @PartialCacheKey Integer id, String message ) { messages.put( id, message ); } Önbellek anahtarını oluşturmak için önbellek yöneticisi tarafından bir anahtar oluşturucu kullanılır. Önceden tanımlanmış önbellek anahtarı oluşturucularının bir listesi burada bulunabilir. Varsayılan olarak, @KeyGenerator , önbellek anahtarını oluşturmak için hem yöntem adını hem de iletilen parametreleri kullanır. Ancak setMessage yönteminin getMessage ile aynı anahtarı oluşturmasını ve bu anahtarla ilişkili önbelleğe alınmış değeri silmesini istediğimizden, anahtar olarak yalnızca ileti kimliğini kullanmalı ve anahtar oluşturma için yöntem adını ortadan kaldırmalıyız. Bu nedenle, anahtar includeMethod özelliğini her iki yöntem için de false olarak ayarladık. Ayrıca setMessage iki argümanı olduğundan, anahtar oluşturucu tarafından kullanılması gereken tek parametre olduğunu belirtmek için id parametresinde @PartialCacheKey ek açıklamasını kullanırız. Son olarak, bu kaynak türü için özel bir önbellek, messageCache yapılandırdığımızı hatırlayın, bu nedenle yalnızca anahtarın kimliğinin kullanılması diğer kaynak türleriyle herhangi bir çakışma tehlikesi oluşturmaz.
Şimdi, ID=1 olan mesaj için aşağıdaki gibi birkaç HTTP isteği yaparsak:
HTTP POST: http://localhost:8080/EhCacheExample/message/set/1/newMessage1 HTTP GET:http://localhost:8080/EhCacheExample/message/1 HTTP POST: http://localhost:8080/EhCacheExample/message/set/1/newMessage2 HTTP GET:http://localhost:8080/EhCacheExample/message/1Konsol şunları gösterecektir:
set message [newMessage1] at Tue Dec 08 17:53:44 MST 2015 get message [newMessage1] at Tue Dec 08 17:53:47 MST 2015 Getting data from SOR...... set message [newMessage2] at Tue Dec 08 17:53:50 MST 2015 get message [newMessage2] at Tue Dec 08 17:53:53 MST 2015 Getting data from SOR......Çözüm
Nihai proje yapısı şöyle görünür:
Bu örnekte önce basit bir Spring MVC RESTful web uygulaması oluşturduk. Mevcut uygulama kodunun bir satırını bile değiştirmeden, EhCache Spring Annotations'ı kullanarak EhCache'i uygulamaya sorunsuz bir şekilde entegre ettik. EhCache Spring Annotations'ın hem kurulumunun kolay (Maven bağımlılığını ekleyerek) hem de kullanımının zarif olduğunu (yöntemlere açıklama ekleyerek) gösterdik.
Daha fazla okuma
EhCache dokümantasyonu burada bulunabilir ve EhCache Spring Annotations dokümantasyonu burada.
Ayrıca GitHub'da bu makalede açıklanan örnek projeye göz atın.
