您好,登錄后才能下訂單哦!
這篇文章主要講解了“Spring Cache和EhCache緩存管理方式有哪些”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“Spring Cache和EhCache緩存管理方式有哪些”吧!
Spring Cache是Spring提供的一整套緩存解決方案。它本身并不提供緩存實(shí)現(xiàn),而是提供統(tǒng)一的接口和代碼規(guī)范、配置、注解等,以便整合各種Cache方案,使用戶不用關(guān)心Cache的細(xì)節(jié)。
Spring支持“透明”地向應(yīng)用程序添加緩存,將緩存應(yīng)用于方法,在方法執(zhí)行前檢查緩存中是否有可用的數(shù)據(jù)。這樣可以減少方法執(zhí)行的次數(shù),同時(shí)提高響應(yīng)的速度。緩存的應(yīng)用方式“透明”,不會(huì)對調(diào)用者造成任何干擾。只要通過注解@EnableCaching啟用了緩存支持,Spring Boot就會(huì)自動(dòng)處理好緩存的基礎(chǔ)配置。
Spring Cache作用在方法上。當(dāng)調(diào)用一個(gè)緩存方法時(shí),會(huì)把該方法參數(shù)和返回結(jié)果作為一個(gè)“鍵值對”(key / value)存放在緩存中,下次用同樣的參數(shù)來調(diào)用該方法時(shí)將不再執(zhí)行該方法,而是直接從緩存中獲取結(jié)果進(jìn)行返回。所以在使用Spring Cache時(shí),要保證在緩存的方法和方法參數(shù)相同時(shí)返回相同的結(jié)果。
Spring Boot提供的聲明式緩存(cache)注解,如下表:
注解 | 說明 |
---|---|
@EnableCaching | 開啟緩存。 |
@Cacheable | 可以作用在類和方法上,以鍵值對的方式緩存類或方法的返回值。 |
@CachePut | 方法被調(diào)用,然后結(jié)果被緩存。 |
@CacheEvict | 清空緩存。 |
@Caching | 用來組合多個(gè)注解標(biāo)簽。 |
Spring Boot支持多種不同的緩存產(chǎn)品。在默認(rèn)情況下使用的是簡單緩存,不建議在正式環(huán)境中使用。我們可以配置一些更加強(qiáng)大的緩存,比如Ehcache。
Ehcache是一種廣泛使用的開源Java分布式緩存,它具有內(nèi)存和磁盤存儲(chǔ)、緩存加載器、緩存擴(kuò)展、緩存異常處理、GZIP緩存、Servlet 過濾器,以及支持 REST 和 SOAP API 等特點(diǎn)。
【實(shí)例】創(chuàng)建SpringBoot與MyBatis的整合項(xiàng)目,實(shí)現(xiàn)用戶信息的查詢、新增、修改、刪除功能。并使用 Spring Cache 和 EhCache 實(shí)現(xiàn)緩存管理,執(zhí)行結(jié)果如下圖:
在MySQL數(shù)據(jù)庫中創(chuàng)建用戶信息表(tb_user),并添加數(shù)據(jù)。
-- 判斷數(shù)據(jù)表是否存在,存在則刪除 DROP TABLE IF EXISTS tb_user; -- 創(chuàng)建“用戶信息”數(shù)據(jù)表 CREATE TABLE IF NOT EXISTS tb_user ( user_id INT AUTO_INCREMENT PRIMARY KEY COMMENT '用戶編號(hào)', user_name VARCHAR(50) NOT NULL COMMENT '用戶姓名', age INT DEFAULT(0) NOT NULL COMMENT '年齡', blog_url VARCHAR(50) NOT NULL COMMENT '博客地址', blog_remark VARCHAR(50) COMMENT '博客信息' ) COMMENT = '用戶信息表'; -- 添加數(shù)據(jù) INSERT INTO tb_user(user_name,age,blog_url,blog_remark) VALUES('pan_junbiao的博客',32,'https://blog.csdn.net/pan_junbiao','您好,歡迎訪問 pan_junbiao的博客');
(1)創(chuàng)建SpringBoot項(xiàng)目,項(xiàng)目結(jié)構(gòu)如下圖:
(2)添加pom.xml配置信息
在pom.xml配置文件中添加MyBatis、 MySQL的JDBC數(shù)據(jù)庫驅(qū)動(dòng)、Spring Boot 緩存支持啟動(dòng)器、Ehcache 緩存等。
<!-- MyBatis與SpringBoot整合依賴 --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.3</version> </dependency> <!-- MySQL的JDBC數(shù)據(jù)庫驅(qū)動(dòng) --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.20</version> </dependency> <!-- 引入Thymeleaf模板引擎 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <!-- Spring Boot緩存支持啟動(dòng)器 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> <version>2.3.2.RELEASE</version> </dependency> <!-- Ehcache緩存管理器 --> <dependency> <groupId>net.sf.ehcache</groupId> <artifactId>ehcache</artifactId> </dependency>
(3)配置相關(guān)信息
將默認(rèn)的application.properties文件的后綴修改為“.yml”,即配置文件名稱為:application.yml,并配置以下信息:
#Spring配置 spring: #緩存管理器 cache: type: ehcache ehcache: config: classpath:ehcache.xml #緩存加載配置文件 #使用Thymeleaf模板引擎 thymeleaf: mode: HTML5 encoding: UTF-8 cache: false #使用Thymeleaf模板引擎,關(guān)閉緩存 servlet: content-type: text/html #DataSource數(shù)據(jù)源 datasource: url: jdbc:mysql://localhost:3306/db_admin?useSSL=false& username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver #MyBatis配置 mybatis: type-aliases-package: com.pjb.entity #別名定義 configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #指定 MyBatis 所用日志的具體實(shí)現(xiàn),未指定時(shí)將自動(dòng)查找 map-underscore-to-camel-case: true #開啟自動(dòng)駝峰命名規(guī)則(camel case)映射 lazy-loading-enabled: true #開啟延時(shí)加載開關(guān) aggressive-lazy-loading: false #將積極加載改為消極加載(即按需加載),默認(rèn)值就是false #lazy-load-trigger-methods: "" #阻擋不相干的操作觸發(fā),實(shí)現(xiàn)懶加載 cache-enabled: true #打開全局緩存開關(guān)(二級環(huán)境),默認(rèn)值就是true
在 resources (資源目錄)下,創(chuàng)建 ehcache.xml 配置文件,配置信息如下:
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd"> <!-- 這個(gè)是磁盤存儲(chǔ)路徑,當(dāng)內(nèi)存緩存滿了的時(shí)候,就會(huì)往這里面放, java.io.tmdir是操作系統(tǒng)緩存的臨時(shí)目錄,不同操作系統(tǒng)緩存目錄不一樣 --> <diskStore path="java.io.tmpdir"/> <!--defaultCache:echcache的默認(rèn)緩存策略 --> <defaultCache maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" maxElementsOnDisk="10000000" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU"> <persistence strategy="localTempSwap"/> </defaultCache> <cache name="userCache" maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" maxElementsOnDisk="10000000" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU"> <persistence strategy="localTempSwap"/> </cache> </ehcache>
配置屬性說明:
屬性 | 說明 |
---|---|
<diskStore path="java.io.tmpdir"/> | 這個(gè)是磁盤存儲(chǔ)路徑,當(dāng)內(nèi)存緩存滿了的時(shí)候,就會(huì)往這里面放,java.io.tmdir是操作系統(tǒng)緩存的臨時(shí)目錄,不同操作系統(tǒng)緩存目錄不一樣。 |
maxElementsInMemory | 內(nèi)存緩存中最多可以存放的元素?cái)?shù)量,若放入Cache中的元素超過這個(gè)數(shù)值,則有以下兩種情況: (1)若 overflowToDisk=true,則會(huì)將Cache中多出的元素放入磁盤文件中。 (2)若 overflowToDisk=false,則根據(jù)memoryStoreEvictionPolicy策略替換Cache中原有的元素。 |
overflowToDisk | 內(nèi)存不足時(shí),是否啟用磁盤緩存。 |
eternal | 緩存中對象是否永久有效。 |
timeToIdleSeconds | 緩存數(shù)據(jù)在失效前的允許閑置時(shí)間(單位:秒),僅當(dāng) eternal=false 時(shí)使用,默認(rèn)值是0表示可閑置時(shí)間無窮大,若超過這個(gè)時(shí)間沒有訪問此Cache中的某個(gè)元素,那么此元素將被從Cache中清除。 |
timeToLiveSeconds | 緩存數(shù)據(jù)的總的存活時(shí)間(單位:秒),僅當(dāng) eternal=false 時(shí)使用,從創(chuàng)建開始計(jì)時(shí),失效結(jié)束。 |
maxElementsOnDisk | 磁盤緩存中最多可以存放的元素?cái)?shù)量,0表示無窮大。 |
diskExpiryThreadIntervalSeconds | 磁盤緩存的清理線程運(yùn)行間隔,默認(rèn)是120秒。 |
memoryStoreEvictionPolicy | 內(nèi)存存儲(chǔ)與釋放策略,即達(dá)到 maxElementsInMemory 限制時(shí),Ehcache會(huì)根據(jù)指定策略清理內(nèi)存,共有三種策略,分別為LRU(最近最少使用)、LFU(最常用的)、FIFO(先進(jìn)先出)。 |
defaultCache | 默認(rèn)緩存方式。 |
cache | 自定義的緩存方式,自行設(shè)置 name。 |
在 application.yml 配置文件中配置目標(biāo)緩存管理器,支持 Ehcache、Generic、Redis、Jcache等。這里配置使用Ehcache。
#Spring配置 spring: #緩存管理器 cache: type: ehcache ehcache: config: classpath:ehcache.xml #緩存加載配置文件
在SpringBoot項(xiàng)目啟動(dòng)入口類中添加注解@EnableCaching,開啟緩存功能。
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCaching; @SpringBootApplication @EnableCaching public class SpringcacheDemoApplication { public static void main(String[] args) { SpringApplication.run(SpringcacheDemoApplication.class, args); } }
在com.pjb.entity包中,創(chuàng)建UserInfo類(用戶信息實(shí)體類)。
package com.pjb.entity; import java.io.Serializable; /** * 用戶信息實(shí)體類 * @author pan_junbiao **/ public class UserInfo implements Serializable { private int userId; //用戶編號(hào) private String userName; //用戶姓名 private int age; //年齡 private String blogUrl; //博客地址 private String blogRemark; //博客信息 //省略getter與setter方法... }
注意:實(shí)體類必須實(shí)現(xiàn) Serializable 接口,否則無法實(shí)現(xiàn)緩存功能。
在com.pjb.mapper包中,創(chuàng)建UserMapper接口(用戶信息Mapper動(dòng)態(tài)代理接口)。
package com.pjb.mapper; import com.pjb.entity.UserInfo; import org.apache.ibatis.annotations.*; import org.springframework.stereotype.Repository; /** * 用戶信息Mapper動(dòng)態(tài)代理接口 * @author pan_junbiao **/ @Mapper @Repository public interface UserMapper { /** * 根據(jù)用戶ID,獲取用戶信息 */ @Select("SELECT * FROM tb_user WHERE user_id = #{userId}") public UserInfo getUserById(int userId); /** * 新增用戶,并獲取自增主鍵 */ @Insert("INSERT INTO tb_user(user_name,age,blog_url,blog_remark) VALUES(#{userName},#{age},#{blogUrl},#{blogRemark});") @Options(useGeneratedKeys = true, keyColumn = "user_id", keyProperty = "userId") public int insertUser(UserInfo userInfo); /** * 修改用戶 */ @Update("UPDATE tb_user SET user_name = #{userName} ,age = #{age} ,blog_url = #{blogUrl} ,blog_remark = #{blogRemark} WHERE user_id = #{userId}") public int updateUser(UserInfo userInfo); /** * 刪除用戶 */ @Delete("DELETE FROM tb_user WHERE user_id = #{userId}") public int deleteUser(int userId); }
在com.pjb.service包下,創(chuàng)建UserService接口(用戶信息業(yè)務(wù)邏輯接口)。
package com.pjb.service; import com.pjb.entity.UserInfo; /** * 用戶信息業(yè)務(wù)邏輯接口 * @author pan_junbiao **/ public interface UserService { /** * 根據(jù)用戶ID,獲取用戶信息 */ public UserInfo getUserById(int userId); /** * 新增用戶,并獲取自增主鍵 */ public UserInfo insertUser(UserInfo userInfo); /** * 修改用戶 */ public UserInfo updateUser(UserInfo userInfo); /** * 刪除用戶 */ public int deleteUser(int userId); }
在com.pjb.service.impl包下,創(chuàng)建UserServiceImpl類(用戶信息業(yè)務(wù)邏輯類)。
package com.pjb.service.impl; import com.pjb.entity.UserInfo; import com.pjb.mapper.UserMapper; import com.pjb.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.annotation.CacheConfig; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.CachePut; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; /** * 用戶信息業(yè)務(wù)邏輯類 * @author pan_junbiao **/ //注意:必須對應(yīng)配置文件ehcache.xml中cache節(jié)點(diǎn)的name屬性值 //@CacheConfig(cacheNames = "userCache") @Service public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper; //注意:必須對應(yīng)配置文件ehcache.xml中cache節(jié)點(diǎn)的name屬性值 private static final String CACHE_NAME = "userCache"; /** * 根據(jù)用戶ID,獲取用戶信息 */ @Override @Cacheable(value = CACHE_NAME, key = "#userId") public UserInfo getUserById(int userId) { return userMapper.getUserById(userId); } /** * 新增用戶,并獲取自增主鍵 */ @Override @CachePut(value = CACHE_NAME, key = "#userInfo.userId") public UserInfo insertUser(UserInfo userInfo) { userMapper.insertUser(userInfo); return userInfo; } /** * 修改用戶 */ @Override @CachePut(value = CACHE_NAME, key = "#userInfo.userId") public UserInfo updateUser(UserInfo userInfo) { userMapper.updateUser(userInfo); return userInfo; } /** * 刪除用戶 */ @Override @CacheEvict(value = CACHE_NAME, key = "#userId") public int deleteUser(int userId) { return userMapper.deleteUser(userId); } }
從上述代碼可以看出,查詢用戶的方法使用了 @Cacheable 注解來開啟緩存。添加和修改方法使用了 @CachePut 注解,它是先處理方法,然后把結(jié)果進(jìn)行緩存的。要想刪除數(shù)據(jù),則需要使用 @CacheEvict 注解來清空緩存。
@CacheConfig注解:如果所有的 @Cacheable() 里面都有一個(gè) value=“xxx” 的屬性,這顯然如果方法多了,寫起來也是挺累的,如果可以一次性聲明完 那就省事了,所以有了 @CacheConfig 這個(gè)配置,@CacheConfig is a class-level annotation that allows to share the cache names,如果你在方法寫別的名字,那么依然以方法的名字為準(zhǔn)。
在com.pjb.controller包中,創(chuàng)建UserController類(用戶控制器),實(shí)現(xiàn)用戶數(shù)據(jù)的查詢、新增、修改、刪除,并實(shí)現(xiàn)數(shù)據(jù)的返回。
package com.pjb.controller; import com.pjb.entity.UserInfo; import com.pjb.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.servlet.ModelAndView; /** * 用戶信息控制器 * @author pan_junbiao **/ @Controller @RequestMapping("/user") public class UserController { @Autowired private UserService userService; /** * 獲取用戶信息 */ @RequestMapping("getUserById") public ModelAndView getUserById(int userId) { //根據(jù)用戶ID,獲取用戶信息 UserInfo userInfo = userService.getUserById(userId); if(userInfo==null) { userInfo = new UserInfo(); } //返回結(jié)果 ModelAndView modelAndView = new ModelAndView(); modelAndView.addObject("userInfo",userInfo); modelAndView.setViewName("/user-info.html"); return modelAndView; } /** * 新增用戶 */ @ResponseBody @RequestMapping("insertUser") public boolean insertUser() { //創(chuàng)建新用戶 UserInfo userInfo = new UserInfo(); userInfo.setUserName("pan_junbiao的博客"); userInfo.setAge(32); userInfo.setBlogUrl("https://blog.csdn.net/pan_junbiao"); userInfo.setBlogRemark("您好,歡迎訪問 pan_junbiao的博客"); //執(zhí)行新增方法 userService.insertUser(userInfo); //返回結(jié)果 return userInfo.getUserId() > 0 ? true : false; } /** * 修改用戶 */ @ResponseBody @RequestMapping("updateUser") public boolean updateUser(int userId) { UserInfo userInfo = new UserInfo(); userInfo.setUserId(userId); userInfo.setUserName("pan_junbiao的博客_02"); userInfo.setAge(35); userInfo.setBlogUrl("https://blog.csdn.net/pan_junbiao"); userInfo.setBlogRemark("您好,歡迎訪問 pan_junbiao的博客"); //執(zhí)行修改方法 userService.updateUser(userInfo); //返回結(jié)果 return true; } /** * 刪除用戶 */ @ResponseBody @RequestMapping("deleteUser") public boolean deleteUser(int userId) { //執(zhí)行新增方法 int result = userService.deleteUser(userId); //返回結(jié)果 return result > 0 ? true : false; } }
在 resources/templates 目錄下,創(chuàng)建 user-info.html 用戶信息顯示頁面。
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>用戶信息</title> <meta name="author" content="pan_junbiao的博客"> <style> table { border-collapse: collapse; margin-bottom: 10px} table,table tr th, table tr td { border:1px solid #000000; padding: 5px 10px;} </style> </head> <body> <div align="center"> <table> <caption>用戶信息</caption> <tr> <th>用戶ID:</th> <td th:text="${userInfo.userId}"></td> </tr> <tr> <th>用戶名稱:</th> <td th:text="${userInfo.userName}"></td> </tr> <tr> <th>年齡:</th> <td th:text="${userInfo.age}"></td> </tr> <tr> <th>博客地址:</th> <td th:text="${userInfo.blogUrl}"></td> </tr> <tr> <th>備注信息:</th> <td th:text="${userInfo.blogRemark}"></td> </tr> </table> </div> </body> </html>
至此,項(xiàng)目已經(jīng)編寫完成,執(zhí)行結(jié)果如下圖:
接著運(yùn)行項(xiàng)目的其他方法,然后多次訪問查詢方法的URL,體驗(yàn)緩存效果。主要觀察數(shù)據(jù)庫是否進(jìn)行了操作,如果數(shù)據(jù)庫沒有操作數(shù)據(jù)而正常返回?cái)?shù)據(jù),則代表緩存成功。
感謝各位的閱讀,以上就是“Spring Cache和EhCache緩存管理方式有哪些”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對Spring Cache和EhCache緩存管理方式有哪些這一問題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。