การแคชในฤดูใบไม้ผลิด้วยคำอธิบายประกอบ EhCache
เผยแพร่แล้ว: 2022-03-11EhCache เป็นแคช Java แท้ที่ใช้กันอย่างแพร่หลาย ซึ่งสามารถรวมเข้ากับเฟรมเวิร์ก Java ยอดนิยมส่วนใหญ่ได้อย่างง่ายดาย เช่น Spring และ Hibernate มักถูกมองว่าเป็นตัวเลือกที่สะดวกที่สุดสำหรับแอปพลิเคชัน Java เนื่องจากสามารถรวมเข้ากับโปรเจ็กต์ได้อย่างง่ายดาย โดยเฉพาะอย่างยิ่ง:
- ตั้งค่าได้โดยการรวม JAR ไว้ในโปรเจ็กต์ของคุณ ไม่จำเป็นต้องมีขั้นตอนการติดตั้งเพิ่มเติม
- มันทำงานในกระบวนการเดียวกันกับแอปพลิเคชันจึงรวดเร็ว ไม่จำเป็นต้องใช้บริการเพิ่มเติมเพื่อเรียกใช้
กล่าวโดยย่อ EhCache เป็นตัวเลือกที่ยอดเยี่ยมสำหรับแอปพลิเคชัน Java ล้วนๆ
นอกจากนี้ EhCache Spring Annotation ยังช่วยให้สามารถรวมเข้ากับแอพพลิเคชั่น Spring ได้อย่างราบรื่น โดยเพียงแค่เพิ่มคำอธิบายประกอบให้กับวิธีการที่แคชได้ โดยไม่ต้องแก้ไขการใช้งานเมธอด
แม้ว่า EhCache จะให้ API ที่ตรงไปตรงมาและสมบูรณ์เพื่อจัดการกับแคชโดยทางโปรแกรม บทความนี้เน้นที่การเพิ่มประสิทธิภาพแอปพลิเคชัน Spring ของคุณในลักษณะที่ไม่รบกวนผู้อื่นด้วย EhCache Spring Annotation เราจะตั้งค่าโปรเจ็กต์ Spring MVC และปรับใช้บริการเว็บ RESTful ใน Tomcat จากนั้น EhCache จะถูกรวมเข้ากับบริการเว็บ
ภาพรวมโครงการ
เราจะสาธิตคำอธิบายประกอบ EhCache ในบริบทของโครงการตัวอย่าง เราจะตั้งค่าบริการเว็บที่ใช้ Spring MVC ซึ่งโฮสต์บนเซิร์ฟเวอร์ Tomcat 8
ฉันพัฒนาโปรเจ็กต์ใน Eclipse ซึ่งสามารถติดตั้งได้โดยทำตามคำแนะนำที่นี่
Tomcat 8 เวอร์ชันเสถียรล่าสุดสามารถดาวน์โหลดได้ที่นี่
แน่นอนว่าแพลตฟอร์มเฉพาะเหล่านี้ไม่ใช่ข้อกำหนดสำหรับ EhCache คุณสามารถเลือก IDE และเซิร์ฟเวอร์ที่คุณชื่นชอบได้ตลอดเวลา
EhCache Spring Annotations JAR มีให้ที่นี่ ดังที่เราเห็น มี JAR สองรายการสำหรับแต่ละเวอร์ชัน: หนึ่งที่มีการพึ่งพาและอีกอันที่ไม่มี หนึ่งที่มีการขึ้นต่อกันยังรวมถึง EhCache 2 และ Spring 3 ซึ่งจำเป็นสำหรับคำอธิบายประกอบ EhCache ในการทำงาน ตั้งค่าได้ง่ายขึ้นหากเราดาวน์โหลดอันที่มีการพึ่งพาและเพิ่มไปยังเส้นทางการสร้างของเรา
คำอธิบายประกอบ EhCache Spring ยังเข้ากันได้กับ Spring 4 แม้ว่าจะต้องกำหนดค่าแยกต่างหาก ยังไม่ชัดเจนว่าโครงการจะรองรับ EhCache 3 ในอนาคตอันใกล้นี้หรือไม่ สำหรับผู้ที่กำลังใช้หรือตั้งใจจะใช้ EhCache 3 ไม่แนะนำให้ใช้วิธีการใส่คำอธิบายประกอบที่กล่าวถึงในบทความนี้
สุดท้ายนี้ เราจะใช้ Maven จัดการทุกอย่าง Maven มาพร้อมกับการติดตั้ง Eclipse ส่วนใหญ่ในแพ็คเกจล่วงหน้า แต่สามารถรับได้ที่นี่ คุณสามารถเพิ่มการอ้างอิง Spring MVC และ EhCache Spring Annotation ได้ค่อนข้างง่าย ดังที่แสดงในบทความนี้
การติดตั้งโครงการ
หากคุณไม่เคยตั้งโครงการ Spring มาก่อน คุณอาจพบว่าโพสต์ของ Stefan Varga ในหัวข้อนี้มีข้อมูลที่เป็นประโยชน์
สำหรับการสาธิตนี้ เราจะตั้งค่าโครงการพื้นฐานโดยใช้ Maven archetype maven-archetype-webapp
โครงสร้างไฟล์โดยรวมจะมีลักษณะดังนี้:
สร้างไดเร็กทอรี src/main/java
โดยมีสามแพ็คเกจ: com.toptal.blog
, com.toptal.blog.cache
และ com.toptal.blog.service
แหล่งที่มาของแอปพลิเคชันของเราจะอยู่ในแพ็คเกจเหล่านี้ตามที่อธิบายไว้ด้านล่าง
มากำหนดเซิร์ฟเล็ต Tomcat ที่เรียกว่า “springrest” ใน web.xml
กัน:
<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>
เว้นแต่จะระบุไว้อย่างชัดเจนเป็นอย่างอื่น Spring MVC DispatcherServlet
จะค้นหาไฟล์การกำหนดค่า XML ชื่อ {servlet-name}-servlet.xml
ในไดเรกทอรี WEB-INF
มาสร้างไฟล์คอนฟิกูเรชันชื่อ springrest-servlet.xml
กัน ในการเปิดใช้งานวิธีการควบคุมกระบวนการ Spring ที่มีคำอธิบายประกอบ @RequestMapping
ให้เพิ่ม <mvc:annotation-driven />
ลงในไฟล์นี้ นอกจากนี้ มากำหนดแพ็คเกจพื้นฐานสำหรับ Spring เพื่อสแกนและลงทะเบียน bean โดยอัตโนมัติโดยเพิ่ม <context:component-scan base-package="com.toptal.blog" />
springrest-servlet.xml
จะกลายเป็น:
<beans ... > <mvc:annotation-driven /> <context:component-scan base-package="com.toptal.blog" /> </beans>
บริการเว็บ RESTful ที่เรียบง่าย
ตอนนี้โปรเจ็กต์ของเราได้รับการกำหนดค่าอย่างเหมาะสมแล้ว มาใช้งาน API “บริการข้อความ” อย่างง่าย ในแพ็คเกจพื้นฐานของเรา project.toptal.blog
เราจะเพิ่ม SpringRestControllerWithEhCache.java
ด้วย GET วิธีหนึ่งเพื่อรับข้อความตาม ID และหนึ่งวิธี POST เพื่อตั้งค่าข้อความตาม ID:
@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
ใน com.toptal.blog.service
มันจะเข้าถึงข้อความที่จัดเก็บไว้ในระบบบันทึกของเรา (SOR) ในแอปที่ใช้งานจริง SOR จะเหมือนกับฐานข้อมูลเชิงสัมพันธ์ เพื่อความง่าย เราจะใช้ HashMap
:
@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 ); } }
ตอนนี้ หากเราส่งออกโปรเจ็กต์เป็น WAR และปรับใช้ใน Tomcat เราน่าจะตั้งค่าข้อความได้ เช่น “test_message” สำหรับ ID=1 โดยสร้างคำขอ HTTP POST ที่ http://localhost:8080/EhCacheExample/message/set/1/test_message
จากนั้นเราควรจะสามารถเรียก “test_message” กลับด้วยคำขอ HTTP GET ที่ http://localhost:8080/EhCacheExample/message/1
ฉันใช้ Insomnia เป็นไคลเอนต์ REST ที่สะดวกเพื่อทำการทดสอบ
เสียบคำอธิบายประกอบของสปริง EhCache
ตอนนี้ให้ EhCache ทำงานให้เรา กำหนดค่าโปรเจ็กต์ของเราให้รัน EhCache ได้อย่างเหมาะสมเพียงไม่กี่ขั้นตอนง่ายๆ
ขั้นตอนที่ 1: อัปเดตการพึ่งพาเพื่อใช้ EhCache Spring Annotations
เพิ่มการพึ่งพา EhCache Spring Annotations ใน pom.xml
ของ Maven:
<!-- ehcache --> <dependency> <groupId>com.googlecode.ehcache-spring-annotations</groupId> <artifactId>ehcache-spring-annotations</artifactId> <version>1.2.0</version> </dependency>
ขั้นตอนที่ 2: ตั้งค่า Custom Cache Manager
Spring มีตัวจัดการแคช EhCache ในตัว org.springframework.cache.ehcache.EhCacheManagerFactoryBean
เหมาะสำหรับสถานการณ์แคชส่วนใหญ่ แต่ฉันพบว่าการกำหนดตัวจัดการแคชแบบกำหนดเองมีประโยชน์เพราะช่วยให้ฉันควบคุมแคชได้ไม่ว่าจะโดยทางโปรแกรมหรือด้วยคำอธิบายประกอบโดยใช้ตัวจัดการแคชเดียวกัน บทความนี้เน้นที่คำอธิบายประกอบ แต่ให้ไปข้างหน้าและกำหนดตัวจัดการแคชที่กำหนดเอง เพื่อให้เราพร้อมในกรณีที่เราต้องการ หากคุณต้องการใช้ตัวจัดการแคชเริ่มต้น คุณสามารถข้ามขั้นตอนนี้ได้

เราจะกำหนดคลาสใหม่ใน com.toptal.blog.cache.CustomCacheManager
:
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
ดังต่อไปนี้:
... <ehcache:annotation-driven cache-manager="customCacheManager" /> <bean class="com.toptal.blog.cache.CustomCacheManager" scope="singleton"></bean> ...
ขั้นตอนที่ 3: กำหนดค่า EhCache
สุดท้าย สร้างไฟล์การกำหนดค่า ehcache.xml
ใน classpath โดยค่าเริ่มต้น Eclipse จะรวม src/main/resources
ใน classpath และเราจะวางไฟล์ไว้ที่นี่ ไฟล์นี้จำเป็นสำหรับ EhCache เพื่อให้ทำงานได้อย่างถูกต้อง มันกำหนดชื่อแคชและคุณสมบัติบางอย่างของแต่ละแคช เช่น timeToLiveSeconds
:
<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: ทดสอบ Cache
ตอนนี้ เมื่อทุกอย่างพร้อมและพร้อมใช้งานแล้ว การใช้ EhCache น่าจะเป็นเรื่องง่ายและมีความสุขในการทำงาน เราเพียงแค่เพิ่ม @Cacheable
ให้กับเมธอดหรือคลาสที่เราต้องการแคช ตัวอย่างเช่น ฉันเพิ่ม @Cacheable
ให้กับเมธอด getMessage
ใน MessageService
ง่ายมาก!
@Cacheable( cacheName = "messageCache" ) public String getMessage( Integer id ) { System.out.println( "Getting data from SOR......" ); return messages.get( id ); }
เพื่อทดสอบว่าแคชของเราทำงาน เราสามารถสร้างข้อความสำหรับ ID=1 โดยออกคำขอ HTTP POST ที่ http://localhost:8080/EhCacheExample/message/set/1/newMessage
แล้วรับข้อความสำหรับ ID= 1 หลายครั้งโดยมี GET ร้องขอ http://localhost:8080/EhCacheExample/message/1
ดังที่คุณเห็นในเอาต์พุตคอนโซลด้านล่าง บริการเว็บขอให้ SOR รับข้อความในครั้งแรกที่เราขอข้อความ แต่ไม่ใช่สำหรับสองคำขอถัดไป โดยจะส่งคืนข้อความที่แคชไว้แทน เนื่องจากเรากำหนด timeToLiveSeconds
เป็น 10 บริการเว็บจึงเรียก SOR เพื่อรับข้อความอีกครั้งหลังจาก 10 วินาที:
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......
กำลังรีเฟรชแคช
ตอนนี้ เรากำลังเพลิดเพลินกับความเร็วและความสะดวกที่แคชมอบให้ และ EhCache นั้นดีพอที่จะรีเฟรชได้เองทุกๆ 10 วินาที แต่ถ้าเราต้องการให้รีเฟรชทันทีหลังจากอัปเดต SOR ของเราแล้ว EhCache Spring Annotation เสนอ @TriggersRemove
เพื่อลบคีย์ที่ระบุออกจากแคชเมื่อมีการเรียกเมธอดที่มีคำอธิบายประกอบ ใน API บริการข้อความของเรา ข้อความที่แคชไว้ควรถูกลบออกจากแคชเมื่อมีการเรียก setMessage
ดังนั้นในครั้งต่อไปที่มีคำขอ getMessage
แคชจะดึงข้อมูลบันทึกใหม่จาก SOR:
@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 ); }
ตัวสร้างคีย์ใช้โดยตัวจัดการแคชเพื่อสร้างคีย์แคช รายการของตัวสร้างคีย์แคชที่กำหนดไว้ล่วงหน้าสามารถพบได้ที่นี่ โดยค่าเริ่มต้น @KeyGenerator
จะใช้ทั้งชื่อเมธอดและพารามิเตอร์ที่ส่งผ่านเพื่อสร้างคีย์แคช แต่เนื่องจากเราต้องการให้เมธอด setMessage
สร้างคีย์เดียวกันกับ getMessage
และลบค่าที่แคชไว้ซึ่งเชื่อมโยงกับคีย์นั้น เราจึงต้องใช้เฉพาะ ID ข้อความเป็นคีย์ และกำจัดชื่อเมธอดสำหรับการสร้างคีย์ ดังนั้นเราจึงตั้งค่าคุณสมบัติ includeMethod
ของตัวสร้างคีย์ให้เป็น false
สำหรับทั้งสองวิธี นอกจากนี้ เนื่องจาก setMessage
มีสองอาร์กิวเมนต์ เราจึงใช้คำอธิบายประกอบ @PartialCacheKey ของ @PartialCacheKey
บนพารามิเตอร์ id
เพื่อระบุว่าเป็นอาร์กิวเมนต์เดียวที่ตัวสร้างคีย์ควรใช้ สุดท้าย ให้ระลึกว่าเราได้กำหนดค่าแคชเฉพาะ messageCache
สำหรับทรัพยากรประเภทนี้ ดังนั้นการใช้เฉพาะ ID สำหรับคีย์จะไม่เกิดอันตรายจากความขัดแย้งกับทรัพยากรประเภทอื่น
ตอนนี้ หากเราทำการร้องขอ HTTP หลายครั้งสำหรับข้อความที่มี ID=1 ดังนี้:
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/1
คอนโซลจะแสดง:
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......
บทสรุป
โครงสร้างโครงการขั้นสุดท้ายมีลักษณะดังนี้:
ในตัวอย่างนี้ ก่อนอื่น เราได้สร้างเว็บแอปพลิเคชัน Spring MVC RESTful อย่างง่าย โดยไม่ต้องแก้ไขแม้แต่บรรทัดเดียวของโค้ดแอปพลิเคชันที่มีอยู่ เราจึงรวม EhCache เข้ากับแอปพลิเคชันอย่างราบรื่นโดยใช้ EhCache Spring Annotations เราได้แสดงให้เห็นว่า EhCache Spring Annotation นั้นติดตั้งง่าย (โดยเพิ่มการพึ่งพา Maven) และสวยงามในการใช้งาน (โดยการเพิ่มคำอธิบายประกอบให้กับเมธอด)
อ่านเพิ่มเติม
สามารถดูเอกสาร EhCache ได้ที่นี่ และเอกสารประกอบของ EhCache Spring Annotation อยู่ที่นี่
ตรวจสอบโครงการตัวอย่างที่อธิบายไว้ในบทความนี้ใน GitHub