12、SpringBoot-mybatis-plus-ehcache
系列导航
6、SpringBoot-mybatis分页实现pagehelper
9、SpringBoot-mybatis-druid多源数据多源数据
10、SpringBoot-mybatis-plus-druid多源数据
11、SpringBoot-mybatis-plus-druid多源数据事务
12、SpringBoot-mybatis-plus-ehcache
14、SpringBoot-easyexcel导出excle
完结
1、数据库中创建表
CREATE TABLE TEST_BLOCK_T ( BLOCK_ID VARCHAR2(10 BYTE) PRIMARY KEY, --编码 BLOCK_NAME VARCHAR2(200 BYTE) --资源名称 );
2、pom.xml依赖
<properties> <java.version>1.8</java.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <spring-boot.version>2.1.16.RELEASE</spring-boot.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- ehcache依赖 --> <dependency> <groupId>net.sf.ehcache</groupId> <artifactId>ehcache</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency> <!-- 集成mybatis-plus --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.2.0</version> </dependency> <!-- oracle驱动 --> <dependency> <groupId>com.oracle</groupId> <artifactId>ojdbc6</artifactId> <version>11.2.0.3</version> </dependency> </dependencies>
3、工程结构
4、配置文件
application.properties
# 应用名称
spring.application.name=demo
# 应用服务 WEB 访问端口
server.port=8080
spring.cache.type=ehcache
spring.cache.ehcache.config=classpath:/config/ehcache.xml
# 数据库设置
spring.datasource.driverClassName=oracle.jdbc.OracleDriver
spring.datasource.url=jdbc:oracle:thin:@192.168.0.100:1521:orcl
spring.datasource.username=zy
spring.datasource.password=1
#mybatis-plus控制台打印sql
mybatis-plus.configuration.log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
ehcache.xml
<ehcache> <!-- 磁盘存储:将缓存中暂时不使用的对象,转移到硬盘,类似于Windows系统的虚拟内存 path:指定在硬盘上存储对象的路径 path可以配置的目录有: user.home(用户的家目录) user.dir(用户当前的工作目录) java.io.tmpdir(默认的临时目录) ehcache.disk.store.dir(ehcache的配置目录) 绝对路径(如:d:\\ehcache) 查看路径方法:String tmpDir = System.getProperty("java.io.tmpdir"); --> <diskStore path="java.io.tmpdir"/> <defaultCache maxElementsInMemory="10000" eternal="true" overflowToDisk="false" /> <cache name="myCache" maxElementsInMemory="10000" eternal="true" overflowToDisk="false" /> <!-- cache :自定的缓存,当自定的配置不满足实际情况时可以通过自定义(可以包含多个cache节点) name : 缓存的名称,可以通过指定名称获取指定的某个Cache对象 maxElementsInMemory :内存中允许存储的最大的元素个数,0代表无限个 clearOnFlush:内存数量最大时是否清除。 eternal :设置缓存中对象是否为永久的,如果是,超时设置将被忽略,对象从不过期。根据存储数据的不同,例如一些静态不变的数据如省市区等可以设置为永不过时 timeToIdleSeconds : 设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。 timeToLiveSeconds :缓存数据的生存时间(TTL),也就是一个元素从构建到消亡的最大时间间隔值,这只能在元素不是永久驻留时有效,如果该值是0就意味着元素可以停顿无穷长的时间。 overflowToDisk :内存不足时,是否启用磁盘缓存。 maxEntriesLocalDisk:当内存中对象数量达到maxElementsInMemory时,Ehcache将会对象写到磁盘中。 maxElementsOnDisk:硬盘最大缓存个数。 diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。 diskPersistent:是否在VM重启时存储硬盘的缓存数据。默认值是false。 diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。 --> </ehcache>
注:配置文件中注意eternal参数,建议设置为true让其一直存在缓存中,否则timeToIdleSeconds、timeToLiveSeconds参数如果设置的时间太短就会导致缓存删除了,导致缓存失效。具体参数含义看配置文件里的注释
5、源码
package com.example.ehcache; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCaching; @SpringBootApplication @EnableCaching @MapperScan("com.example.ehcache.mapper") public class EhcacheApplication { public static void main(String[] args) { SpringApplication.run(EhcacheApplication.class, args); } }
package com.example.ehcache.controller; import com.example.ehcache.domain.Block; import com.example.ehcache.service.DemoService; import org.springframework.web.bind.annotation.*; /** * @author lz * @date 2018/12/27 */ @RestController @RequestMapping("/cache") public class CacheController { private final DemoService demoService; public CacheController(DemoService demoService) { this.demoService = demoService; } @PostMapping( value = "/put" ) @ResponseBody public void put() { Block block = new Block(); block.setBlockId("9999"); block.setBlockName("哈哈哈"); demoService.save(block); } @GetMapping(value = "/get" ) @ResponseBody public void cacheable() { Block block = new Block(); block.setBlockId("9999"); Block blockResult = demoService.findOne(block); System.out.println("controller:"+blockResult); } @PostMapping( value = "/remove") @ResponseBody public String evict() { String id = "9999"; demoService.remove(id); return "ok"; } @PostMapping( value = "/put1" ) @ResponseBody public void put1() { String id ="oiline"; String name ="100"; demoService.put(id, name); } @GetMapping(value = "/get1" ) @ResponseBody public void cacheable1() { String id ="oiline"; String result = demoService.get(id); System.out.println("取到的数据result是:"+result); } @PostMapping( value = "/remove1") @ResponseBody public String evict1() { String id ="oiline"; demoService.delete(id); return "ok"; } }
package com.example.ehcache.domain; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; /** * <p> * 。 * </p> * * @author yc * @since 2021-09-18 */ @TableName(value = "TEST_BLOCK_T") public class Block { private static final long serialVersionUID = 1L; @TableId private String blockId; /** * $field.comment。 * */ private String blockName; public String getBlockId() { return blockId; } public void setBlockId(String blockId) { this.blockId = blockId; } public String getBlockName() { return blockName; } public void setBlockName(String blockName) { this.blockName = blockName; } @Override public String toString() { return "TEST_BLOCK_T{" + "blockId='" + blockId + '\'' + ", blockName='" + blockName + '\'' + '}'; } }
package com.example.ehcache.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.example.ehcache.domain.Block; public interface BlockMapper extends BaseMapper<Block> { }
package com.example.ehcache.service; import com.example.ehcache.domain.Block; import java.util.Map; /** * @author lz * @date 2018/12/27 */ public interface DemoService { Block save(Block block); void remove(String id); Block findOne(Block block); String put(String id,String value); String get(String id); void delete(String id); }
package com.example.ehcache.service.impl; import com.example.ehcache.domain.Block; import com.example.ehcache.mapper.BlockMapper; import com.example.ehcache.service.DemoService; 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; import java.util.HashMap; import java.util.Map; /** * @author lz * @date 2018/12/27 */ @Service @CacheConfig(cacheNames = {"myCache"}) public class DemoServiceImpl implements DemoService { /** * 注意:如果没有指定key,则方法参数作为key保存到缓存中 */ @Autowired BlockMapper blockMapper; /** * @param block * @return * @CachePut缓存新增的或更新的数据到缓存,其中缓存的名称为people,数据的key是person的id */ @CachePut(key = "#block.blockId") @Override public Block save(Block block) { blockMapper.insert(block); System.out.println("新增"); System.out.println("为id,key为:" + block.getBlockId() + "数据做了缓存"); return block; } /** * @param id * @CacheEvict从缓存people中删除key为id的数据 */ @CacheEvict @Override public void remove(String id) { System.out.println("删除"); System.out.println("删除了id,key为" + id + "的数据缓存"); //personRepository.deleteById(id); } /** * @param block * @return * @Cacheable缓存key为person的id数据到缓存people中 */ //@Cacheable(value="HelloWorldCache", key="#param") 这里可以用value指定缓存的名称 // 因为在@CacheConfig(cacheNames = {"myCache"}) 指定过了所以这里不用重复指定 @Cacheable(key = "#block.blockId") @Override public Block findOne(Block block) { Block BlockResult = blockMapper.selectById(block.getBlockId()); System.out.println("查询"); System.out.println("为id,key为:"+ block.getBlockId() + "数据做了缓存"); return BlockResult; } //-----------------------单纯存一个数的缓存,不需要存入数据库里----------------------------------- private final Map<String,String> map=new HashMap<>(); @Override @CachePut( key = "#id") public String put(String id, String value) { System.out.println("插入数据:"+id+" ==> "+value); map.put(id,value); return value; } @Override @Cacheable( key = "#id") public String get(String id) { System.out.println("查询数据:"+id); String result=map.get(id); if (result==null){ return "查询的数据不存在"; } return result; } @CacheEvict( key = "#id") public void delete(String id){ System.out.println("删除数据:"+id); map.remove(id); } }
6、测试
(1)get方法 : http://localhost:8080/cache/get 获取数据
结果:
说明:此时缓存和数据库里都没有数据。缓存里没有数据所以查了一次数据库。
(2)post方法 : http://localhost:8080/cache/put 新增数据
结果:
说明:此时向缓存和数据库里增加了数据。
(3)get方法 : http://localhost:8080/cache/get 获取数据
结果:
说明:此时缓存里有数据了,就没有查数据库找数据。(这是该缓存技术的闪光点)
(4)post方法 : http://localhost:8080/cache/remove 删除数据
结果:
说明:此时删除了缓存里的数据。注:代码里并没有删除数据库的数据
(5)get方法 : http://localhost:8080/cache/get 再次获取数据
结果:
说明:此时由于缓存里有数据,所以查询一次数据库。(这是该缓存技术的闪光点)
(6)get方法 : http://localhost:8080/cache/get 获取数据
结果:
说明:经过上一个查询,缓存里又有数据了,所以直接从缓存里取数据。
7、如何只单纯放一个数据在缓存里,不存在数据库里
请看如下Controller中的方法,测试方法和上面一样。
http://localhost:8080/cache/get1 GET